Merge branch 'feature/36' into develop
26
README.md
|
@ -10,16 +10,12 @@ generated using Luminus version "2.9.11.05"
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
**Nothing works yet**. This is very early development code, a long way pre-alpha.
|
Very early pre-alpha; user interface mostly works (enough to demonstrate), back end is hardly started.
|
||||||
|
|
||||||
## What is it supposed to do?
|
## What is it supposed to do?
|
||||||
|
|
||||||
To understand what I'm aiming for, read [this essay](http://blog.journeyman.cc/2016/10/preparing-for-next-independence.html). Design documentation, such as there is of it yet, is in the *dummy* sub-directory. Also look at [src/clj/youyesyet/db/schema.clj](https://github.com/simon-brooke/youyesyet/blob/master/src/clj/youyesyet/db/schema.clj).
|
To understand what I'm aiming for, read [this essay](http://blog.journeyman.cc/2016/10/preparing-for-next-independence.html). Design documentation, such as there is of it yet, is in the *dummy* sub-directory. Also look at [src/clj/youyesyet/db/schema.clj](https://github.com/simon-brooke/youyesyet/blob/master/src/clj/youyesyet/db/schema.clj).
|
||||||
|
|
||||||
### Dummy website
|
|
||||||
|
|
||||||
I've put a [dummy site](http://www.journeyman.cc/~simon/tmp/yyy-dummy/index.html) up for people to play with. Obviously it's intended to work with mobile phones.
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
You will need [Leiningen][1] 2.0 or above installed. The database required must be [Postgres][2] 9.3 or above.
|
You will need [Leiningen][1] 2.0 or above installed. The database required must be [Postgres][2] 9.3 or above.
|
||||||
|
@ -49,6 +45,16 @@ You should also read the [User-Oriented Specification](doc/specification/userspe
|
||||||
|
|
||||||
## Getting the database up
|
## Getting the database up
|
||||||
|
|
||||||
|
You'll need a file *profiles.clj*, with content similar to the following; it's not in the repository because it contains passwords.
|
||||||
|
|
||||||
|
;; WARNING
|
||||||
|
;; The profiles.clj file is used for local environment variables, such as database credentials.
|
||||||
|
;; This file is listed in .gitignore and will be excluded from version control by Git.
|
||||||
|
|
||||||
|
{:profiles/dev {:env {:database-url "jdbc:postgresql://127.0.0.1/youyesyet_dev?user=youyesyet&password=yourverysecurepassword"}}
|
||||||
|
:profiles/test {:env {:database-url "jdbc:postgresql://127.0.0.1/youyesyet_test?user=youyesyet&password=yourverysecurepassword"}}}
|
||||||
|
|
||||||
|
|
||||||
Do get the database initialised, run
|
Do get the database initialised, run
|
||||||
|
|
||||||
createdb youyesyet_dev
|
createdb youyesyet_dev
|
||||||
|
@ -59,9 +65,11 @@ followed by
|
||||||
|
|
||||||
**NOTE THAT** in the namespace *youyesyet.db.schema*, there are a series of functions *create-xxx-table!*. These are a snare and a delusion; they are how I originally bootstrapped the database, but are no longer used (and should probably be deleted). The database is now constructed using [migratus](https://github.com/yogthos/migratus).
|
**NOTE THAT** in the namespace *youyesyet.db.schema*, there are a series of functions *create-xxx-table!*. These are a snare and a delusion; they are how I originally bootstrapped the database, but are no longer used (and should probably be deleted). The database is now constructed using [migratus](https://github.com/yogthos/migratus).
|
||||||
|
|
||||||
## Running
|
## Running in a dev environment
|
||||||
|
|
||||||
To start a web server for the application, run:
|
To run in a dev environment, checkout the *develop* branch
|
||||||
|
|
||||||
|
To start a development web server for the application, run:
|
||||||
|
|
||||||
lein run
|
lein run
|
||||||
|
|
||||||
|
@ -73,6 +81,10 @@ as above; in the other, run
|
||||||
|
|
||||||
lein figwheel
|
lein figwheel
|
||||||
|
|
||||||
|
## Running in a production environment
|
||||||
|
|
||||||
|
Doesn't really work yet; if you want to try it, see [Bug #36](https://github.com/simon-brooke/youyesyet/issues/36) and check out the associated feature branch.
|
||||||
|
|
||||||
## Working on this project
|
## Working on this project
|
||||||
|
|
||||||
You should get the [ZenHub](https://github.com/integrations/zenhub) plug-in for your favourite browser; I use ZenHub for project management, and you (and I) will find collaborating much easier if you do. To join in
|
You should get the [ZenHub](https://github.com/integrations/zenhub) plug-in for your favourite browser; I use ZenHub for project management, and you (and I) will find collaborating much easier if you do. To join in
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
/* I'm not certain that this file is still needed at all; however, it doesn't seem to be doing any harm. */
|
||||||
/* Things which should not get renamed when compiling ClojureScript */
|
/* Things which should not get renamed when compiling ClojureScript */
|
||||||
|
|
||||||
/* this block relates to the use of Leaflet */
|
/* this block relates to the use of Leaflet */
|
||||||
var L = {
|
var L = {
|
||||||
"map": {
|
"map": {
|
||||||
"setView": function(){}
|
"setView": function(){},
|
||||||
|
"eg": function(){}
|
||||||
},
|
},
|
||||||
"tileLayer": {
|
"tileLayer": {
|
||||||
"addTo": function(){}
|
"addTo": function(){}
|
||||||
|
|
BIN
favicon.ico
Before Width: | Height: | Size: 13 KiB |
22
project.clj
|
@ -8,6 +8,7 @@
|
||||||
[ring/ring-servlet "1.5.1"]
|
[ring/ring-servlet "1.5.1"]
|
||||||
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
|
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
|
||||||
[clj-oauth "1.5.5"]
|
[clj-oauth "1.5.5"]
|
||||||
|
[cljsjs/react-leaflet "0.12.3-4"]
|
||||||
[ch.qos.logback/logback-classic "1.2.2"]
|
[ch.qos.logback/logback-classic "1.2.2"]
|
||||||
[re-frame "0.9.2"]
|
[re-frame "0.9.2"]
|
||||||
[cljs-ajax "0.5.8"]
|
[cljs-ajax "0.5.8"]
|
||||||
|
@ -65,12 +66,25 @@
|
||||||
|
|
||||||
:hooks [leiningen.less]
|
:hooks [leiningen.less]
|
||||||
|
|
||||||
:uberwar
|
:uberwar {:handler youyesyet.handler/app
|
||||||
{:prep-tasks ["compile" "bower" ["cljsbuild" "once" "min"]]
|
|
||||||
:handler youyesyet.handler/app
|
|
||||||
:init youyesyet.handler/init
|
:init youyesyet.handler/init
|
||||||
:destroy youyesyet.handler/destroy
|
:destroy youyesyet.handler/destroy
|
||||||
:name "youyesyet.war"}
|
:name "youyesyet.war"
|
||||||
|
:uberjar {:omit-source true
|
||||||
|
:prep-tasks ["compile" ["bower" "install"] ["cljsbuild" "once" "min"]]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:min
|
||||||
|
{:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:main "youyesyet.core"
|
||||||
|
:optimizations :advanced
|
||||||
|
:pretty-print false
|
||||||
|
:verbose true}}}}
|
||||||
|
:aot :all
|
||||||
|
:uberjar-name "youyesyet.jar"
|
||||||
|
:source-paths ["env/prod/clj"]
|
||||||
|
:resource-paths ["env/prod/resources"]}}
|
||||||
|
|
||||||
:clean-targets ^{:protect false}
|
:clean-targets ^{:protect false}
|
||||||
[:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
|
[:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
|
||||||
|
|
156
project.new.clj
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
(defproject youyesyet "0.1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
:description "Canvassing tool for referenda"
|
||||||
|
:url "https://github.com/simon-brooke/youyesyet"
|
||||||
|
|
||||||
|
:dependencies [[bouncer "1.0.1"]
|
||||||
|
[clj-oauth "1.5.4"]
|
||||||
|
[cljs-ajax "0.5.8"]
|
||||||
|
[compojure "1.5.2"]
|
||||||
|
[conman "0.6.3"]
|
||||||
|
[cprop "0.1.10"]
|
||||||
|
[funcool/struct "1.0.0"]
|
||||||
|
[korma "0.4.3"]
|
||||||
|
;; TODO: Latest Luminus no longer includes noir, and I only
|
||||||
|
;; use it in home.clj for routing. Worth looking at how Luminus
|
||||||
|
;; currently does roouting, and perhaps removing this dependency.
|
||||||
|
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
|
||||||
|
[luminus-migrations "0.3.0"]
|
||||||
|
[luminus-nrepl "0.1.4"]
|
||||||
|
[luminus/ring-ttl-session "0.3.1"]
|
||||||
|
[markdown-clj "0.9.98"]
|
||||||
|
[metosin/muuntaja "0.1.0"]
|
||||||
|
[metosin/ring-http-response "0.8.2"]
|
||||||
|
[mount "0.1.11"]
|
||||||
|
[org.clojure/clojure "1.8.0"]
|
||||||
|
[org.clojure/clojurescript "1.9.495" :scope "provided"]
|
||||||
|
[org.clojure/tools.cli "0.3.5"]
|
||||||
|
[org.clojure/tools.logging "0.3.1"]
|
||||||
|
[org.postgresql/postgresql "42.0.0"]
|
||||||
|
[org.webjars.bower/tether "1.4.0"]
|
||||||
|
[org.webjars/bootstrap "4.0.0-alpha.5"]
|
||||||
|
[org.webjars/font-awesome "4.7.0"]
|
||||||
|
[re-frame "0.9.2"]
|
||||||
|
[reagent "0.6.1"]
|
||||||
|
[reagent-utils "0.2.1"]
|
||||||
|
[ring-webjars "0.1.1"]
|
||||||
|
[ring/ring-core "1.6.0-RC1"]
|
||||||
|
[ring/ring-defaults "0.2.3"]
|
||||||
|
[ring/ring-servlet "1.4.0"]
|
||||||
|
[secretary "1.2.3"]
|
||||||
|
[selmer "1.10.7"]]
|
||||||
|
|
||||||
|
:min-lein-version "2.0.0"
|
||||||
|
|
||||||
|
:license {:name "GNU General Public License v2"
|
||||||
|
:url "http://www.gnu.org/licenses/gpl-2.0.html"}
|
||||||
|
|
||||||
|
:jvm-opts ["-server" "-Dconf=.lein-env"]
|
||||||
|
:source-paths ["src/clj" "src/cljc"]
|
||||||
|
:test-paths ["test/clj"]
|
||||||
|
:resource-paths ["resources" "target/cljsbuild"]
|
||||||
|
:target-path "target/%s/"
|
||||||
|
:main ^:skip-aot youyesyet.core
|
||||||
|
:migratus {:store :database :db ~(get (System/getenv) "DATABASE_URL")}
|
||||||
|
|
||||||
|
:plugins [[lein-cprop "1.0.1"]
|
||||||
|
[migratus-lein "0.4.4"]
|
||||||
|
[lein-cljsbuild "1.1.5"]
|
||||||
|
[lein-immutant "2.1.0"]
|
||||||
|
[lein-kibit "0.1.2"]
|
||||||
|
[lein-uberwar "0.2.0"]
|
||||||
|
[lein-bower "0.5.1"]]
|
||||||
|
|
||||||
|
:bower-dependencies [[leaflet "0.7.3"]]
|
||||||
|
|
||||||
|
:uberwar
|
||||||
|
{:handler youyesyet.handler/app
|
||||||
|
:init youyesyet.handler/init
|
||||||
|
:destroy youyesyet.handler/destroy
|
||||||
|
:name "youyesyet.war"}
|
||||||
|
|
||||||
|
:clean-targets ^{:protect false}
|
||||||
|
[:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
|
||||||
|
|
||||||
|
:figwheel
|
||||||
|
{:http-server-root "public"
|
||||||
|
:nrepl-port 7002
|
||||||
|
:css-dirs ["resources/public/css"]
|
||||||
|
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
|
||||||
|
|
||||||
|
:externs ["externs.js"]
|
||||||
|
|
||||||
|
:profiles
|
||||||
|
{:uberjar {:omit-source true
|
||||||
|
:prep-tasks ["compile" ["bower" "install"] ["cljsbuild" "once" "min"]]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:min
|
||||||
|
{:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:output-to "target/cljsbuild/public/js/app.js"
|
||||||
|
:optimizations :advanced
|
||||||
|
:pretty-print false
|
||||||
|
:closure-warnings
|
||||||
|
{:externs-validation :off :non-standard-jsdoc :off}
|
||||||
|
:externs ["react/externs/react.js"]}}}}
|
||||||
|
|
||||||
|
|
||||||
|
:aot :all
|
||||||
|
:uberjar-name "youyesyet.jar"
|
||||||
|
:source-paths ["env/prod/clj"]
|
||||||
|
:resource-paths ["env/prod/resources"]}
|
||||||
|
|
||||||
|
:dev [:project/dev :profiles/dev]
|
||||||
|
:test [:project/dev :project/test :profiles/test]
|
||||||
|
|
||||||
|
:project/dev {:dependencies [[prone "1.1.4"]
|
||||||
|
[ring/ring-mock "0.3.0"]
|
||||||
|
[ring/ring-devel "1.5.1"]
|
||||||
|
[org.webjars/webjars-locator-jboss-vfs "0.1.0"]
|
||||||
|
[luminus-immutant "0.2.3"]
|
||||||
|
[pjstadig/humane-test-output "0.8.1"]
|
||||||
|
[binaryage/devtools "0.9.2"]
|
||||||
|
[com.cemerick/piggieback "0.2.2-SNAPSHOT"]
|
||||||
|
[directory-naming/naming-java "0.8"]
|
||||||
|
[doo "0.1.7"]
|
||||||
|
[figwheel-sidecar "0.5.9"]]
|
||||||
|
:plugins [[com.jakemccrary/lein-test-refresh "0.18.1"]
|
||||||
|
[lein-doo "0.1.7"]
|
||||||
|
[lein-figwheel "0.5.9"]
|
||||||
|
[org.clojure/clojurescript "1.9.495"]]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:app
|
||||||
|
{:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:main "youyesyet.app"
|
||||||
|
:asset-path "/js/out"
|
||||||
|
:output-to "target/cljsbuild/public/js/app.js"
|
||||||
|
:output-dir "target/cljsbuild/public/js/out"
|
||||||
|
:source-map true
|
||||||
|
:optimizations :none
|
||||||
|
:pretty-print true}}}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
:doo {:build "test"}
|
||||||
|
:source-paths ["env/dev/clj"]
|
||||||
|
:resource-paths ["env/dev/resources"]
|
||||||
|
:repl-options {:init-ns user}
|
||||||
|
:injections [(require 'pjstadig.humane-test-output)
|
||||||
|
(pjstadig.humane-test-output/activate!)]}
|
||||||
|
:project/test {:resource-paths ["env/test/resources"]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:test
|
||||||
|
{:source-paths ["src/cljc" "src/cljs" "test/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:output-to "target/test.js"
|
||||||
|
:main "youyesyet.doo-runner"
|
||||||
|
:optimizations :whitespace
|
||||||
|
:pretty-print true}}}}
|
||||||
|
|
||||||
|
}
|
||||||
|
:profiles/dev {}
|
||||||
|
:profiles/test {}})
|
163
project.old.clj
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
(defproject youyesyet "0.1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
:description "Canvassing tool for referenda"
|
||||||
|
:url "https://github.com/simon-brooke/youyesyet"
|
||||||
|
|
||||||
|
:dependencies [[org.clojure/clojure "1.8.0"]
|
||||||
|
[org.clojure/clojurescript "1.9.229" :scope "provided"]
|
||||||
|
[ring/ring-servlet "1.5.1"]
|
||||||
|
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
|
||||||
|
[clj-oauth "1.5.5"]
|
||||||
|
[ch.qos.logback/logback-classic "1.2.2"]
|
||||||
|
[re-frame "0.9.2"]
|
||||||
|
[cljs-ajax "0.5.8"]
|
||||||
|
[secretary "1.2.3"]
|
||||||
|
[reagent-utils "0.2.1"]
|
||||||
|
[reagent "0.6.1"]
|
||||||
|
[korma "0.4.3"]
|
||||||
|
[selmer "1.10.6"]
|
||||||
|
[markdown-clj "0.9.98"]
|
||||||
|
[ring-middleware-format "0.7.2"]
|
||||||
|
[metosin/ring-http-response "0.8.2"]
|
||||||
|
[bouncer "1.0.1"]
|
||||||
|
[org.webjars/bootstrap "4.0.0-alpha.6-1"]
|
||||||
|
[org.webjars/font-awesome "4.7.0"]
|
||||||
|
[org.webjars.bower/tether "1.4.0"]
|
||||||
|
[org.clojure/tools.logging "0.3.1"]
|
||||||
|
[compojure "1.5.2"]
|
||||||
|
[metosin/compojure-api "1.1.10"]
|
||||||
|
[ring-webjars "0.1.1"]
|
||||||
|
[ring/ring-defaults "0.2.3"]
|
||||||
|
[luminus/ring-ttl-session "0.3.1"]
|
||||||
|
[mount "0.1.11"]
|
||||||
|
[cprop "0.1.10"]
|
||||||
|
[org.clojure/tools.cli "0.3.5"]
|
||||||
|
[migratus "0.8.33"]
|
||||||
|
[luminus-nrepl "0.1.4"]
|
||||||
|
[luminus-migrations "0.3.0"]
|
||||||
|
[conman "0.6.3"]
|
||||||
|
[org.postgresql/postgresql "9.4.1212"]
|
||||||
|
]
|
||||||
|
|
||||||
|
:min-lein-version "2.0.0"
|
||||||
|
|
||||||
|
:license {:name "GNU General Public License v2"
|
||||||
|
:url "http://www.gnu.org/licenses/gpl-2.0.html"}
|
||||||
|
|
||||||
|
:jvm-opts ["-server" "-Dconf=.lein-env"]
|
||||||
|
:source-paths ["src/clj" "src/cljc"]
|
||||||
|
:resource-paths ["resources" "target/cljsbuild"]
|
||||||
|
:target-path "target/%s/"
|
||||||
|
:main youyesyet.core
|
||||||
|
:migratus {:store :database :db ~(get (System/getenv) "DATABASE_URL")}
|
||||||
|
|
||||||
|
:plugins [[lein-cprop "1.0.1"]
|
||||||
|
[migratus-lein "0.4.2"]
|
||||||
|
[org.clojars.punkisdead/lein-cucumber "1.0.5"]
|
||||||
|
[lein-cljsbuild "1.1.4"]
|
||||||
|
[lein-uberwar "0.2.0"]
|
||||||
|
[lein-bower "0.5.1"]
|
||||||
|
[lein-less "1.7.5"]]
|
||||||
|
|
||||||
|
:bower-dependencies [[leaflet "0.7.3"]]
|
||||||
|
|
||||||
|
:cucumber-feature-paths ["test/clj/features"]
|
||||||
|
|
||||||
|
:hooks [leiningen.less]
|
||||||
|
|
||||||
|
:uberwar
|
||||||
|
{:handler youyesyet.handler/app
|
||||||
|
:init youyesyet.handler/init
|
||||||
|
:destroy youyesyet.handler/destroy
|
||||||
|
:name "youyesyet.war"}
|
||||||
|
|
||||||
|
:clean-targets ^{:protect false}
|
||||||
|
[:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
|
||||||
|
|
||||||
|
:figwheel
|
||||||
|
{:http-server-root "public"
|
||||||
|
:nrepl-port 7002
|
||||||
|
:css-dirs ["resources/public/css"]
|
||||||
|
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
|
||||||
|
|
||||||
|
:externs ["externs.js"]
|
||||||
|
|
||||||
|
:profiles
|
||||||
|
{:uberjar {:omit-source true
|
||||||
|
:prep-tasks ["compile" ["bower" "install"] ["cljsbuild" "once" "min"]]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:min
|
||||||
|
{:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:asset-path "/youyesyet/js/out"
|
||||||
|
:externs "externs.js"
|
||||||
|
:main "youyesyet.core"
|
||||||
|
:optimizations :advanced
|
||||||
|
:output-dir "resources/public/js"
|
||||||
|
:output-to "resources/public/js/app.js"
|
||||||
|
:pretty-print false
|
||||||
|
:verbose true}}}}
|
||||||
|
:aot :all
|
||||||
|
:uberjar-name "youyesyet.jar"
|
||||||
|
:source-paths ["env/prod/clj"]
|
||||||
|
:resource-paths ["env/prod/resources"]}
|
||||||
|
|
||||||
|
:dev [:project/dev :profiles/dev]
|
||||||
|
:test [:project/dev :project/test :profiles/test]
|
||||||
|
|
||||||
|
:project/dev {:dependencies [[prone "1.1.4"]
|
||||||
|
[ring/ring-mock "0.3.0"]
|
||||||
|
[ring/ring-devel "1.5.1"]
|
||||||
|
[luminus-jetty "0.1.4"]
|
||||||
|
[pjstadig/humane-test-output "0.8.1"]
|
||||||
|
[org.clojure/core.cache "0.6.5"]
|
||||||
|
[org.apache.httpcomponents/httpcore "4.4.6"]
|
||||||
|
[clj-webdriver/clj-webdriver "0.7.2"]
|
||||||
|
[org.seleniumhq.selenium/selenium-server "3.3.1" :exclusions [org.seleniumhq.selenium/selenium-support]]
|
||||||
|
[doo "0.1.7"]
|
||||||
|
[binaryage/devtools "0.9.2"]
|
||||||
|
[figwheel-sidecar "0.5.9"]
|
||||||
|
[com.cemerick/piggieback "0.2.2-SNAPSHOT"]
|
||||||
|
[directory-naming/naming-java "0.8"]]
|
||||||
|
:plugins [[com.jakemccrary/lein-test-refresh "0.14.0"]
|
||||||
|
[lein-doo "0.1.7"]
|
||||||
|
[lein-figwheel "0.5.9"]
|
||||||
|
[org.clojure/clojurescript "1.9.229"]]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:app
|
||||||
|
{:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:asset-path "/youyesyet/js/out"
|
||||||
|
:main "youyesyet.app"
|
||||||
|
:externs ["react/externs/react.js" "externs.js"]
|
||||||
|
:output-to "target/cljsbuild/public/js/app.js"
|
||||||
|
:output-dir "target/cljsbuild/public/js/out"
|
||||||
|
:source-map true
|
||||||
|
:optimizations :none
|
||||||
|
:pretty-print true}}}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
:doo {:build "test"}
|
||||||
|
:source-paths ["env/dev/clj" "test/clj"]
|
||||||
|
:resource-paths ["env/dev/resources"]
|
||||||
|
:repl-options {:init-ns user}
|
||||||
|
:injections [(require 'pjstadig.humane-test-output)
|
||||||
|
(pjstadig.humane-test-output/activate!)]}
|
||||||
|
:project/test {:resource-paths ["env/dev/resources" "env/test/resources"]
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:test
|
||||||
|
{:source-paths ["src/cljc" "src/cljs" "test/cljs"]
|
||||||
|
:compiler
|
||||||
|
{:output-to "target/test.js"
|
||||||
|
:externs ["react/externs/react.js" "externs.js"]
|
||||||
|
:main "youyesyet.doo-runner"
|
||||||
|
:optimizations :whitespace
|
||||||
|
:pretty-print true}}}}
|
||||||
|
|
||||||
|
}
|
||||||
|
:profiles/dev {}
|
||||||
|
:profiles/test {}})
|
|
@ -60,13 +60,9 @@ footer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0.25em 0;
|
padding: 0.25em 0;
|
||||||
bottom:0;
|
bottom: 0;
|
||||||
position:fixed;
|
position: fixed;
|
||||||
vertical-align: top;
|
|
||||||
z-index:150;
|
z-index:150;
|
||||||
_position:absolute;
|
|
||||||
_top:expression(eval(document.documentElement.scrollTop+
|
|
||||||
(document.documentElement.clientHeight-this.offsetHeight)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer div {
|
footer div {
|
||||||
|
@ -365,8 +361,12 @@ th {
|
||||||
/* phones, and, indeed, smaller phones. Adapted to touch; display radically
|
/* phones, and, indeed, smaller phones. Adapted to touch; display radically
|
||||||
* decluttered */
|
* decluttered */
|
||||||
@media all and (max-device-width: 768px) {
|
@media all and (max-device-width: 768px) {
|
||||||
footer {
|
button, input, select {
|
||||||
display: none;
|
background-color: rgb( 50, 109, 177);
|
||||||
|
color: white;
|
||||||
|
font-size: 1.1em;
|
||||||
|
padding: 0.25em 1em;
|
||||||
|
border-radius: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -375,14 +375,6 @@ th {
|
||||||
padding-left: 75px;
|
padding-left: 75px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input, select {
|
|
||||||
background-color: rgb( 50, 109, 177);
|
|
||||||
color: white;
|
|
||||||
font-size: 1.1em;
|
|
||||||
padding: 0.25em 1em;
|
|
||||||
border-radius: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 665 KiB |
Before Width: | Height: | Size: 2.8 KiB |
|
@ -37,16 +37,16 @@
|
||||||
<footer>
|
<footer>
|
||||||
<div id="credits">
|
<div id="credits">
|
||||||
<div>
|
<div>
|
||||||
<img src="img/ric-logo.png" width="24" height="24"/>
|
<img src="img/credits/ric-logo.png" width="24" height="24"/>
|
||||||
A project of the
|
A project of the
|
||||||
<a href="https://radical.scot/">Radical Independence Campaign</a> ||
|
<a href="https://radical.scot/">Radical Independence Campaign</a> ||
|
||||||
Version {{version}}
|
Version {{version}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img height="16" width="16" alt="Clojure" src="img/luminus-logo.png"/>Built with <a href="http://www.luminusweb.net/">LuminusWeb</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/clojure-icon.gif"/> Powered by <a href="http://clojure.org">Clojure</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/github-logo-transparent.png"/>Find me/fork me on <a href="https://github.com/simon-brooke/smeagol">Github</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/smeagol">Github</a> ||
|
||||||
<img height="16" width="16" alt="Free Software Foundation" src="img/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="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>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
115
src/cljc/youyesyet/outqueue.cljc
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
(ns youyesyet.outqueue
|
||||||
|
(:require
|
||||||
|
#?(:clj [clojure.core]
|
||||||
|
:cljs [reagent.core :refer [atom]])))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;
|
||||||
|
;;;; youyesyet.outqueue: queue of messages waiting to be sent to the server.
|
||||||
|
;;;;
|
||||||
|
;;;; 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
|
||||||
|
;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;;; The items are (obviously) the actual items in the queue;
|
||||||
|
;;; the queue is locked if an attempt is currently being made to transmit
|
||||||
|
;;; an item.
|
||||||
|
|
||||||
|
(defn new-queue
|
||||||
|
"Create a new queue"
|
||||||
|
([]
|
||||||
|
(new-queue '()))
|
||||||
|
([items]
|
||||||
|
(atom {:locked false
|
||||||
|
:items (if
|
||||||
|
(seq? items)
|
||||||
|
(reverse items)
|
||||||
|
(list items))})))
|
||||||
|
|
||||||
|
(defn add!
|
||||||
|
"Add this item to the queue."
|
||||||
|
[q item]
|
||||||
|
(swap! q
|
||||||
|
(fn [a]
|
||||||
|
(assoc a :items
|
||||||
|
(cons item (:items a))))))
|
||||||
|
|
||||||
|
(defn q?
|
||||||
|
[x]
|
||||||
|
(try
|
||||||
|
(let [q (deref x)
|
||||||
|
locked (:locked q)]
|
||||||
|
(and
|
||||||
|
(seq? (:items q))
|
||||||
|
(or (true? locked) (false? locked))))
|
||||||
|
(catch #?(:clj Exception :cljs js/Object) any
|
||||||
|
#?(:clj (print (.getMessage any))
|
||||||
|
:cljs (js/console.log (str any))))))
|
||||||
|
|
||||||
|
(defn peek
|
||||||
|
"Look at the next item which could be removed from the queue."
|
||||||
|
[q]
|
||||||
|
(last (:items (deref q))))
|
||||||
|
|
||||||
|
(defn locked?
|
||||||
|
[q]
|
||||||
|
(:locked (deref q)))
|
||||||
|
|
||||||
|
(defn unlock!
|
||||||
|
([q ]
|
||||||
|
(unlock! q true))
|
||||||
|
([q value]
|
||||||
|
(swap! q (fn [a] (assoc a :locked (not (true? value)))))))
|
||||||
|
|
||||||
|
(defn lock!
|
||||||
|
[q]
|
||||||
|
(unlock! q false))
|
||||||
|
|
||||||
|
|
||||||
|
(defn count
|
||||||
|
"Return the count of items currently in the queue."
|
||||||
|
[q]
|
||||||
|
(count (deref q)))
|
||||||
|
|
||||||
|
(defn take!
|
||||||
|
"Return the first item from the queue, rebind the queue to the remaining
|
||||||
|
items. If the queue is empty return nil."
|
||||||
|
[q]
|
||||||
|
(swap! q (fn [a]
|
||||||
|
(let [items (reverse (:items a))
|
||||||
|
item (first items)
|
||||||
|
new-queue (reverse (rest items))]
|
||||||
|
(assoc (assoc a :items new-queue) :v item))))
|
||||||
|
(:v (deref q)))
|
||||||
|
|
||||||
|
(defn maybe-process-next
|
||||||
|
"Apply this process, assumed to be a function of one argument, to the next
|
||||||
|
item in the queue, if the queue is not currently locked; return the value
|
||||||
|
returned by process."
|
||||||
|
[q process]
|
||||||
|
(if (and (q? q)(not (locked? q)))
|
||||||
|
(try
|
||||||
|
(lock! q)
|
||||||
|
(let [v (apply process (list (peek q)))]
|
||||||
|
(take! q)
|
||||||
|
v)
|
||||||
|
(catch #?(:clj Exception :cljs js/Object) any
|
||||||
|
#?(:clj (print (.getMessage any))
|
||||||
|
:cljs (js/console.log (str any))))
|
||||||
|
(finally (unlock! q)))
|
||||||
|
))
|
|
@ -1,11 +1,12 @@
|
||||||
(ns youyesyet.core
|
(ns youyesyet.core
|
||||||
(:require [reagent.core :as r]
|
(:require cljsjs.react-leaflet
|
||||||
[re-frame.core :as rf]
|
[ajax.core :refer [GET POST]]
|
||||||
[secretary.core :as secretary]
|
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[goog.history.EventType :as HistoryEventType]
|
[goog.history.EventType :as HistoryEventType]
|
||||||
[markdown.core :refer [md->html]]
|
[markdown.core :refer [md->html]]
|
||||||
[ajax.core :refer [GET POST]]
|
[reagent.core :as r]
|
||||||
|
[re-frame.core :as rf]
|
||||||
|
[secretary.core :as secretary]
|
||||||
[youyesyet.ajax :refer [load-interceptors!]]
|
[youyesyet.ajax :refer [load-interceptors!]]
|
||||||
[youyesyet.handlers]
|
[youyesyet.handlers]
|
||||||
[youyesyet.subscriptions]
|
[youyesyet.subscriptions]
|
||||||
|
@ -71,16 +72,26 @@
|
||||||
:map #'map-page
|
:map #'map-page
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
(defn page
|
(defn page
|
||||||
"Render the single page of the app, taking the current panel from
|
"Render the single page of the app, taking the current panel from
|
||||||
the :page key in the state map."
|
the :page key in the state map."
|
||||||
[]
|
[]
|
||||||
|
(let [content (pages @(rf/subscribe [:page]))
|
||||||
|
error @(rf/subscribe [:error])
|
||||||
|
feedback @(rf/subscribe [:feedback])
|
||||||
|
outqueue @(rf/subscribe [:outqueue])]
|
||||||
[:div
|
[:div
|
||||||
[:header
|
[:header
|
||||||
[ui/navbar]]
|
[ui/navbar]]
|
||||||
(let [content (pages @(rf/subscribe [:page]))]
|
|
||||||
(if content [content]
|
(if content [content]
|
||||||
[:div.error (str "No content in page " :page)]))])
|
[:div.error (str "No content in page " :page)])
|
||||||
|
[:footer
|
||||||
|
[:div.error {:style [:display (if error "block" "none")]} (str error)]
|
||||||
|
[:div.feedback {:style [:display (if feedback :block :none)]} (str feedback)]
|
||||||
|
[:div.queue (if
|
||||||
|
(nil? outqueue) ""
|
||||||
|
(str (count outqueue) " items queued to send"))]]]))
|
||||||
|
|
||||||
;; -------------------------
|
;; -------------------------
|
||||||
;; Routes
|
;; Routes
|
||||||
|
@ -108,7 +119,7 @@
|
||||||
(rf/dispatch [:set-elector-and-page {:elector-id elector-id :page :issues}]))
|
(rf/dispatch [:set-elector-and-page {:elector-id elector-id :page :issues}]))
|
||||||
|
|
||||||
(secretary/defroute "/issue/:issue" {issue :issue}
|
(secretary/defroute "/issue/:issue" {issue :issue}
|
||||||
(rf/dispatch [:set-issue issue]))
|
(rf/dispatch [:set-and-go-to-issue issue]))
|
||||||
|
|
||||||
(secretary/defroute "/map" []
|
(secretary/defroute "/map" []
|
||||||
(rf/dispatch [:set-active-page :map]))
|
(rf/dispatch [:set-active-page :map]))
|
||||||
|
|
|
@ -57,7 +57,12 @@
|
||||||
{:id 2 :name "Ann Anderson" :gender :female}
|
{:id 2 :name "Ann Anderson" :gender :female}
|
||||||
{:id 3 :name "Alex Anderson" :gender :fluid :intention :yes}
|
{:id 3 :name "Alex Anderson" :gender :fluid :intention :yes}
|
||||||
{:id 4 :name "Andy Anderson" :intention :yes}]
|
{:id 4 :name "Andy Anderson" :intention :yes}]
|
||||||
|
;;; any error to display
|
||||||
|
:error nil
|
||||||
;;; the issue from among the issues which is currently selected.
|
;;; the issue from among the issues which is currently selected.
|
||||||
|
;;; any confirmation message to display
|
||||||
|
:feedback nil
|
||||||
|
;;; the currently selected issue
|
||||||
:issue "Currency"
|
:issue "Currency"
|
||||||
;;; the issues selected for the issues page on this day.
|
;;; the issues selected for the issues page on this day.
|
||||||
:issues {"Currency" "Scotland could keep the Pound, or use the Euro. But we could also set up a new currency of our own. Yada yada yada"
|
:issues {"Currency" "Scotland could keep the Pound, or use the Euro. But we could also set up a new currency of our own. Yada yada yada"
|
||||||
|
@ -68,5 +73,6 @@
|
||||||
;;; the options from among which electors can select.
|
;;; the options from among which electors can select.
|
||||||
:options [{:id :yes :description "Yes"} {:id :no :description "No"}]
|
:options [{:id :yes :description "Yes"} {:id :no :description "No"}]
|
||||||
;;; the currently displayed 'page' within the app.
|
;;; the currently displayed 'page' within the app.
|
||||||
|
:outqueue ()
|
||||||
:page :home
|
:page :home
|
||||||
})
|
})
|
||||||
|
|
|
@ -27,6 +27,27 @@
|
||||||
;;;;
|
;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn clear-messages
|
||||||
|
"Return a state like this state except with the error and feedback messages
|
||||||
|
set nil"
|
||||||
|
[state]
|
||||||
|
(merge state {:error nil :feedback nil}))
|
||||||
|
|
||||||
|
|
||||||
|
(defn get-elector
|
||||||
|
"Return the elector at this address (or the current address if not specified)
|
||||||
|
with this id."
|
||||||
|
([elector-id state]
|
||||||
|
(get-elector elector-id state (:address state)))
|
||||||
|
([elector-id state address]
|
||||||
|
(first
|
||||||
|
(remove
|
||||||
|
nil?
|
||||||
|
(map
|
||||||
|
#(if (= elector-id (:id %)) %)
|
||||||
|
(:electors address))))))
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:initialize-db
|
:initialize-db
|
||||||
(fn [_ _]
|
(fn [_ _]
|
||||||
|
@ -34,40 +55,10 @@
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:set-active-page
|
:send-intention
|
||||||
(fn [db [_ page]]
|
|
||||||
(if page
|
|
||||||
(assoc db :page page))))
|
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
|
||||||
:set-address
|
|
||||||
(fn [db [_ address-id]]
|
|
||||||
(let [id (read-string address-id)
|
|
||||||
address (first (remove nil? (map #(if (= id (:id %)) %) (:addresses db))))]
|
|
||||||
(assoc (assoc db :address address) :page :electors))))
|
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
|
||||||
:set-elector-and-page
|
|
||||||
(fn [db [_ args]]
|
|
||||||
(let [page (:page args)
|
|
||||||
elector-id (read-string (:elector-id args))
|
|
||||||
elector
|
|
||||||
(first
|
|
||||||
(remove nil?
|
|
||||||
(map
|
|
||||||
#(if (= elector-id (:id %)) %)
|
|
||||||
(:electors (:address db)))))]
|
|
||||||
(js/console.log (str "Setting page to " page ", elector to " elector))
|
|
||||||
(assoc (assoc db :elector elector) :page page))))
|
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
|
||||||
:set-intention
|
|
||||||
(fn [db [_ args]]
|
(fn [db [_ args]]
|
||||||
(let [intention (:intention args)
|
(let [intention (:intention args)
|
||||||
elector-id (read-string (:elector-id args))
|
elector-id (:elector-id args)
|
||||||
elector
|
elector
|
||||||
(first
|
(first
|
||||||
(remove nil?
|
(remove nil?
|
||||||
|
@ -77,16 +68,84 @@
|
||||||
old-address (:address db)
|
old-address (:address db)
|
||||||
new-address (assoc old-address :electors (cons (assoc elector :intention intention) (remove #(= % elector) (:electors old-address))))]
|
new-address (assoc old-address :electors (cons (assoc elector :intention intention) (remove #(= % elector) (:electors old-address))))]
|
||||||
(cond
|
(cond
|
||||||
(nil? elector)(do (js/console.log "No elector found; not setting intention") db)
|
(nil? elector)
|
||||||
|
(assoc db :error "No elector found; not setting intention")
|
||||||
(= intention (:intention elector)) (do (js/console.log "Elector's intention hasn't changed; not setting intention") db)
|
(= intention (:intention elector)) (do (js/console.log "Elector's intention hasn't changed; not setting intention") db)
|
||||||
true
|
true
|
||||||
(do
|
(do
|
||||||
(js/console.log (str "Setting intention of elector " elector " to " intention))
|
(js/console.log (str "Setting intention of elector " elector " to " intention))
|
||||||
(assoc db :addresses (cons new-address (remove old-address (:addresses db)))))))))
|
(merge
|
||||||
|
(clear-messages db)
|
||||||
|
{:addresses
|
||||||
|
(cons new-address (remove old-address (:addresses db)))
|
||||||
|
:address new-address
|
||||||
|
:outqueue (cons (assoc args :action :set-intention) (:outqueue db))}))))))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:send-request
|
||||||
|
(fn [db [_ _]]
|
||||||
|
(if (and (:elector db) (:issue db) (:telephone db))
|
||||||
|
(do
|
||||||
|
(js/console.log "Sending request")
|
||||||
|
(assoc db
|
||||||
|
:feedback "Request has been queued"
|
||||||
|
:outqueue (cons
|
||||||
|
{:elector-id (:id (:elector db))
|
||||||
|
:issue (:issue db)
|
||||||
|
:action :add-request} (:outqueue db))))
|
||||||
|
(assoc db :error "Please supply a telephone number to call"))))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:set-active-page
|
||||||
|
(fn [db [_ page]]
|
||||||
|
(if page
|
||||||
|
(assoc (clear-messages db) :page page))))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:set-address
|
||||||
|
(fn [db [_ address-id]]
|
||||||
|
(let [id (read-string address-id)
|
||||||
|
address (first (remove nil? (map #(if (= id (:id %)) %) (:addresses db))))]
|
||||||
|
(assoc (clear-messages db) :address address :page :electors))))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:set-and-go-to-issue
|
||||||
|
(fn [db [_ issue]]
|
||||||
|
(js/console.log (str "Setting page to :issue, issue to " issue))
|
||||||
|
(assoc (assoc (clear-messages db) :issue issue) :page :issue)))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:set-elector-and-page
|
||||||
|
(fn [db [_ args]]
|
||||||
|
(let [page (:page args)
|
||||||
|
elector-id (read-string (:elector-id args))
|
||||||
|
elector (get-elector elector-id db)]
|
||||||
|
(js/console.log (str "Setting page to " page ", elector to " elector))
|
||||||
|
(assoc (clear-messages db) :elector elector :page page))))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:set-elector
|
||||||
|
(fn [db [_ elector-id]]
|
||||||
|
(let [elector (get-elector (read-string elector-id) db)]
|
||||||
|
(js/console.log (str "Setting elector to " elector))
|
||||||
|
(assoc (clear-messages db) :elector elector))))
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:set-issue
|
:set-issue
|
||||||
(fn [db [_ issue]]
|
(fn [db [_ issue]]
|
||||||
(js/console.log (str "Setting page to :issue, issue to " issue))
|
(js/console.log (str "Setting issue to " issue))
|
||||||
(assoc (assoc db :issue issue) :page :issue)))
|
(assoc (clear-messages db) :issue issue)))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-db
|
||||||
|
:set-telephone
|
||||||
|
(fn [db [_ telephone]]
|
||||||
|
(js/console.log (str "Setting telephone to " telephone))
|
||||||
|
(assoc (clear-messages db) :telephone telephone)))
|
||||||
|
|
|
@ -39,11 +39,26 @@
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(:addresses db)))
|
(:addresses db)))
|
||||||
|
|
||||||
|
(reg-sub
|
||||||
|
:changes
|
||||||
|
(fn [db _]
|
||||||
|
(:changes db)))
|
||||||
|
|
||||||
(reg-sub
|
(reg-sub
|
||||||
:elector
|
:elector
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(:elector db)))
|
(:elector db)))
|
||||||
|
|
||||||
|
(reg-sub
|
||||||
|
:error
|
||||||
|
(fn [db _]
|
||||||
|
(:error db)))
|
||||||
|
|
||||||
|
(reg-sub
|
||||||
|
:feedback
|
||||||
|
(fn [db _]
|
||||||
|
(:feedback db)))
|
||||||
|
|
||||||
(reg-sub
|
(reg-sub
|
||||||
:issue
|
:issue
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
|
@ -63,3 +78,9 @@
|
||||||
:options
|
:options
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(:options db)))
|
(:options db)))
|
||||||
|
|
||||||
|
(reg-sub
|
||||||
|
:outqueue
|
||||||
|
(fn [db _]
|
||||||
|
(:outqueue db)))
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;
|
;;;;
|
||||||
;;;; youyesyet.views.electors: about/credits view for youyesyet.
|
;;;; youyesyet.views.about: about/credits view for youyesyet.
|
||||||
;;;;
|
;;;;
|
||||||
;;;; This program is free software; you can redistribute it and/or
|
;;;; This program is free software; you can redistribute it and/or
|
||||||
;;;; modify it under the terms of the GNU General Public License
|
;;;; modify it under the terms of the GNU General Public License
|
||||||
|
@ -41,23 +41,23 @@
|
||||||
[:p.motd {:dangerouslySetInnerHTML
|
[:p.motd {:dangerouslySetInnerHTML
|
||||||
{:__html (md->html motd)}}]
|
{:__html (md->html motd)}}]
|
||||||
[:p
|
[:p
|
||||||
[:img {:src "img/ric-logo.png" :width "24" :height "24"}]
|
[:img {:src "img/credits/ric-logo.png" :width "24" :height "24"}]
|
||||||
" A project of the "
|
" A project of the "
|
||||||
[:a {:href "https://radical.scot/"} "Radical Independence Campaign"]]
|
[:a {:href "https://radical.scot/"} "Radical Independence Campaign"]]
|
||||||
[:p
|
[:p
|
||||||
[:img {:src "img/luminus-logo.png" :alt "Luminus" :height "24" :width "24"}]
|
[:img {:src "img/credits/luminus-logo.png" :alt "Luminus" :height "24" :width "24"}]
|
||||||
" Built with "
|
" Built with "
|
||||||
[:a {:href "http://www.luminusweb.net/"} "Luminus Web"]]
|
[:a {:href "http://www.luminusweb.net/"} "Luminus Web"]]
|
||||||
[:p
|
[:p
|
||||||
[:img {:src "img/clojure-icon.gif" :alt "Clojure" :height "24" :width "24"}]
|
[:img {:src "img/credits/clojure-icon.gif" :alt "Clojure" :height "24" :width "24"}]
|
||||||
" Powered by "
|
" Powered by "
|
||||||
[:a {:href "http://clojure.org"} "Clojure"]]
|
[:a {:href "http://clojure.org"} "Clojure"]]
|
||||||
[:p
|
[:p
|
||||||
[:img {:src "img/github-logo-transparent.png" :alt "GitHub" :height "24" :width "24"}]
|
[:img {:src "img/credits/github-logo-transparent.png" :alt "GitHub" :height "24" :width "24"}]
|
||||||
" Find me/fork me on "
|
" Find me/fork me on "
|
||||||
[:a {:href "https://github.com/simon-brooke/youyesyet"} "GitHub"]]
|
[:a {:href "https://github.com/simon-brooke/youyesyet"} "GitHub"]]
|
||||||
[:p
|
[:p
|
||||||
[:img {:src "img/gnu.small.png" :alt "Free Software Foundation" :height "24" :width "24"}]
|
[:img {:src "img/credits/gnu.small.png" :alt "Free Software Foundation" :height "24" :width "24"}]
|
||||||
" Licensed under the "
|
" Licensed under the "
|
||||||
[:a {:href "http://www.gnu.org/licenses/gpl-2.0.html"}
|
[:a {:href "http://www.gnu.org/licenses/gpl-2.0.html"}
|
||||||
"GNU General Public License v2.0"]]
|
"GNU General Public License v2.0"]]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns youyesyet.views.electors
|
(ns youyesyet.views.electors
|
||||||
(:require [re-frame.core :refer [reg-sub subscribe]]
|
(:require [reagent.core :refer [atom]]
|
||||||
|
[re-frame.core :refer [reg-sub subscribe dispatch]]
|
||||||
[youyesyet.ui-utils :as ui]))
|
[youyesyet.ui-utils :as ui]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -47,12 +48,14 @@
|
||||||
image (if gender (name gender) "unknown")]
|
image (if gender (name gender) "unknown")]
|
||||||
[:td {:key (:id elector)} [:img {:src (str "img/gender/" image ".png") :alt image}]]))
|
[:td {:key (:id elector)} [:img {:src (str "img/gender/" image ".png") :alt image}]]))
|
||||||
|
|
||||||
|
|
||||||
(defn genders-row
|
(defn genders-row
|
||||||
[electors]
|
[electors]
|
||||||
[:tr
|
[:tr
|
||||||
(map
|
(map
|
||||||
#(gender-cell %) electors)])
|
#(gender-cell %) electors)])
|
||||||
|
|
||||||
|
|
||||||
(defn name-cell
|
(defn name-cell
|
||||||
[elector]
|
[elector]
|
||||||
[:td {:key (str "name-" (:id elector))} (:name elector)])
|
[:td {:key (str "name-" (:id elector))} (:name elector)])
|
||||||
|
@ -63,26 +66,33 @@
|
||||||
(map
|
(map
|
||||||
#(name-cell %) electors)])
|
#(name-cell %) electors)])
|
||||||
|
|
||||||
|
|
||||||
(defn options-row
|
(defn options-row
|
||||||
[electors option]
|
[electors option]
|
||||||
(let [optid (:id option)
|
(let [optid (:id option)
|
||||||
optname (name optid)]
|
optname (name optid)]
|
||||||
[:tr {:key (str "options-" optid)}
|
[:tr {:key (str "options-" optname)}
|
||||||
(map
|
(map
|
||||||
#(let [selected (= optid (:intention %))
|
(fn [elector] (let [selected (= optid (:intention elector))
|
||||||
image (if selected (str "img/option/" optname "-selected.png")
|
image (if selected (str "img/option/" optname "-selected.png")
|
||||||
(str "img/option/" optname "-unselected.png"))]
|
(str "img/option/" optname "-unselected.png"))]
|
||||||
[:td {:key (str "option-" optid "-" (:id %))}
|
[:td {:key (str "option-" optid "-" (:id elector))}
|
||||||
[:a {:href (str "#/set-intention/" (:id %) "/" optid)}
|
[:img
|
||||||
[:img {:src image :alt optname}]]])
|
{:src image
|
||||||
|
:alt optname
|
||||||
|
:on-click #(dispatch
|
||||||
|
[:send-intention {:elector-id (:id elector)
|
||||||
|
:intention optid}])}]]))
|
||||||
|
;; TODO: impose an ordering on electors - by name or by id
|
||||||
electors)]))
|
electors)]))
|
||||||
|
|
||||||
|
|
||||||
(defn issue-cell
|
(defn issue-cell
|
||||||
"Create an issue cell for a particular elector"
|
"Create an issue cell for a particular elector"
|
||||||
[elector]
|
[elector]
|
||||||
[:td {:key (:id elector)}
|
[:td {:key (:id elector)}
|
||||||
[:a {:href (str "#/issues/" (:id elector))}
|
[:a {:href (str "#/issues/" (:id elector))}
|
||||||
[:img {:src "/img/issues.png" :alt "Issues"}]]])
|
[:img {:src "img/issues.png" :alt "Issues"}]]])
|
||||||
|
|
||||||
|
|
||||||
(defn issues-row
|
(defn issues-row
|
||||||
|
@ -97,8 +107,9 @@
|
||||||
[]
|
[]
|
||||||
(let [address @(subscribe [:address])
|
(let [address @(subscribe [:address])
|
||||||
addresses @(subscribe [:addresses])
|
addresses @(subscribe [:addresses])
|
||||||
electors (:electors address)
|
electors (sort-by :id (:electors address))
|
||||||
options @(subscribe [:options])]
|
options @(subscribe [:options])
|
||||||
|
changes @(subscribe [:changes])]
|
||||||
(if address
|
(if address
|
||||||
[:div
|
[:div
|
||||||
[:h1 (:address address)]
|
[:h1 (:address address)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(ns youyesyet.views.followup
|
(ns youyesyet.views.followup
|
||||||
(:require [re-frame.core :refer [reg-sub subscribe]]
|
(:require [re-frame.core :refer [reg-sub subscribe dispatch]]
|
||||||
[youyesyet.ui-utils :as ui]))
|
[youyesyet.ui-utils :as ui]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -50,25 +50,28 @@
|
||||||
[:div
|
[:div
|
||||||
[:h1 "Followup Request"]
|
[:h1 "Followup Request"]
|
||||||
[:div.container {:id "main-container"}
|
[:div.container {:id "main-container"}
|
||||||
[:form {}
|
[:div {}
|
||||||
[:p.widget
|
[:p.widget
|
||||||
[:label {:for "elector"} "Elector"]
|
[:label {:for "elector"} "Elector"]
|
||||||
[:select {:id "elector" :name "elector" :value (:id elector)}
|
[:select {:id "elector" :name "elector" :defaultValue (:id elector)
|
||||||
|
:on-change #(dispatch [:set-elector (.-value (.-target %))])}
|
||||||
(map
|
(map
|
||||||
#(let []
|
#(let []
|
||||||
[:option {:value (:id %) :key (:id %)} (:name %)]) (:electors address))]]
|
[:option {:value (:id %) :key (:id %)} (:name %)]) (:electors address))]]
|
||||||
[:p.widget
|
[:p.widget
|
||||||
[:label {:for "issue"} "Issue"]
|
[:label {:for "issue"} "Issue"]
|
||||||
[:select {:id "issue" :name "issue" :value issue}
|
;; #(reset! val (-> % .-target .-value))
|
||||||
|
[:select {:id "issue" :name "issue" :defaultValue issue
|
||||||
|
:on-change #(dispatch [:set-issue (.-value (.-target %))])}
|
||||||
(map
|
(map
|
||||||
#(let []
|
#(let []
|
||||||
[:option {:key % :value %} %]) (keys issues))]]
|
[:option {:key % :value %} %]) (keys issues))]]
|
||||||
[:p.widget
|
[:p.widget
|
||||||
[:label {:for "telephone"} "Telephone number"]
|
[:label {:for "telephone"} "Telephone number"]
|
||||||
[:input {:type "text" :id "telephone" :name "telephone"}]]
|
[:input {:type "text" :id "telephone" :name "telephone"
|
||||||
|
:on-change #(dispatch [:set-telephone (.-value (.-target %))])}]]
|
||||||
[:p.widget
|
[:p.widget
|
||||||
[:label {:for "submit"} "To request a call"]
|
[:label {:for "send"} "To request a call"]
|
||||||
[:input {:id "submit" :name "submit" :type "submit" :value "Send this!"}]]
|
[:button {:id "send" :on-click #(dispatch [:send-request])} "Send this!"]]]
|
||||||
]
|
|
||||||
(ui/back-link)]])))
|
(ui/back-link)]])))
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
[id]
|
[id]
|
||||||
(js/console.log (str "Click handler for address #" id))
|
(js/console.log (str "Click handler for address #" id))
|
||||||
(set! window.location.href (str "#electors/" id)))
|
(set! window.location.href (str "#electors/" id)))
|
||||||
;; This way is probably more idiomatic React, but back links don't work:
|
;; This way is probably more idiomatic React, but history doesn't work:
|
||||||
;; (defn map-pin-click-handler
|
;; (defn map-pin-click-handler
|
||||||
;; [id]
|
;; [id]
|
||||||
;; (dispatch [:set-address id]))
|
;; (dispatch [:set-address id]))
|
||||||
|
|