#31, #44, #45: GDPR workflow complete; started on locality data

This commit is contained in:
Simon Brooke 2018-07-03 10:04:59 +01:00
parent b42a593e34
commit 6b44b70330
15 changed files with 223 additions and 384 deletions

View file

@ -0,0 +1,35 @@
------------------------------------------------------------------------------;
----
---- locality-trigger.sql: compute localities for addresses
----
---- 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
----
------------------------------------------------------------------------------;
---- See also: src/cljc/locality.cljc
CREATE FUNCTION compute_locality() RETURNS trigger AS $compute_locality$
BEGIN
NEW.locality = (10000 * floor (NEW.latitude * 1000)) -
(NEW.longitude * 1000);
RETURN NEW;
END;
$compute_locality$ LANGUAGE plpgsql;
CREATE TRIGGER compute_locality BEFORE INSERT OR UPDATE ON addresses
FOR EACH ROW EXECUTE PROCEDURE compute_locality();

View file

@ -1,6 +1,6 @@
------------------------------------------------------------------------------; ------------------------------------------------------------------------------;
---- ----
---- youyesyet.routes.authenticated: routes and pages for authenticated users. ---- queries.sql: manually maintained queries.
---- ----
---- 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
@ -23,322 +23,17 @@
-- This file gets slurped in and converted into simple functions by the line -- This file gets slurped in and converted into simple functions by the line
-- in youyesyet.db.core.clj: -- in youyesyet.db.core.clj:
-- (conman/bind-connection *db* "sql/queries.sql") -- (conman/bind-connection *db* "sql/queries-auto.sql" "sql/queries.sql")
-- the functions then appeare in the youyesyet.db.core namespace. -- the functions then appeare in the youyesyet.db.core namespace.
-- Note that queries generated by ADL are in the file
-- resources/sql/queries-auto.sql; they do not have to be (and should not be)
-- redefined here.
-- :name create-address! :! :n -- :name list-addresses-by-locality :? :*
-- :doc creates a new address record -- :doc lists all existing address records in a given locality
INSERT INTO addresses SELECT *
(address, postcode, district_id, latitude, longitude) FROM addresses
VALUES (:address, :postcode, :district, :latitude, :longitude) WHERE locality = :locality
RETURNING id
-- :name update-address! :! :n
-- :doc update an existing address record
UPDATE addresses
SET address = :address, postcode = :postcode, latitude = :latitude, longitude = :longitude
WHERE id = :id
-- :name get-address :? :1
-- :doc retrieve a address given the id.
SELECT * FROM addresses
WHERE id = :id
-- :name get-addresses-by-postcode
-- :name delete-address! :! :n
-- :doc delete a address given the id
DELETE FROM addresses
WHERE id = :id
-- :name create-authority! :! :n
-- :doc creates a new authority record
INSERT INTO authorities
(id)
VALUES (:id)
RETURNING id
-- :name update-authority! :! :n
-- :doc update an existing authority record
UPDATE authorities
SET id = :id
WHERE id = :id
-- :name get-authority :? :1
-- :doc retrieve a authority given the id.
SELECT * FROM authorities
WHERE id = :id
-- :name get-authorities :? :0
-- :doc retrieve all authorities
SELECT id FROM authorities
-- :name delete-authority! :! :n
-- :doc delete a authority given the id
DELETE FROM authorities
WHERE id = :id
-- :name create-canvasser! :! :n
-- :doc creates a new canvasser record
INSERT INTO canvassers
(username, fullname, elector_id, dwelling_id, phone, email, authority_id, authorised)
VALUES (:username, :fullname, :elector_id, :dwelling_id, :phone, :email, :authority_id, :authorised)
RETURNING id
-- :name update-canvasser! :! :n
-- :doc update an existing canvasser record
UPDATE canvassers
SET username = :username, fullname = :fullname, elector_id = :elector_id, dwelling_id = :dwelling_id, phone = :phone, email = :email, authority_id = :authority_id, authorised = :authorised
WHERE id = :id
-- :name get-canvasser :? :1
-- :doc retrieve a canvasser given the id.
SELECT * FROM canvassers
WHERE id = :id
-- :name get-canvasser-by-username :? :1
-- :doc rerieve a canvasser given the username.
SELECT * FROM canvassers
WHERE username = :username
-- :name get-canvasser-by-email :? :1
-- :doc rerieve a canvasser given the email address.
SELECT * FROM canvassers
WHERE email = :email
-- :name delete-canvasser! :! :n
-- :doc delete a canvasser given the id
DELETE FROM canvassers
WHERE id = :id
-- :name create-district! :! :n
-- :doc creates a new district record
INSERT INTO districts
(id, name)
VALUES (:id, :name)
RETURNING id
-- :name update-district! :! :n
-- :doc update an existing district record
UPDATE districts
SET name = :name
WHERE id = :id
-- :name get-district :? :1
-- :doc retrieve a district given the id.
SELECT * FROM districts
WHERE id = :id
-- :name delete-district! :! :n
-- :doc delete a district given the id
DELETE FROM districts
WHERE id = :id
-- :name get-dwelling :? :1
-- :doc retrieve a dwelling given the id.
SELECT * FROM dwellings
WHERE id = :id
-- :name delete-dwelling! :! :n
-- :doc delete a dwelling given the id
DELETE FROM dwellings
WHERE id = :id
-- :name create-dwelling! :! :n
-- :doc creates a new dwelling record
INSERT INTO dwellings
(id, address_id, sub_address)
VALUES (:id, :address_id, :sub_address)
RETURNING id
-- :name update-dwelling! :! :n
-- :doc update an existing dwelling record
UPDATE dwellings
SET address_id = :address_id,
sub_address = :sub_address
WHERE id = :id
-- :name get-dwelling :? :1
-- :doc retrieve a dwelling given the id.
SELECT * FROM dwellings
WHERE id = :id
-- :name delete-dwelling! :! :n
-- :doc delete a dwelling given the id
DELETE FROM dwellings
WHERE id = :id
-- :name create-elector! :! :n
-- :doc creates a new elector record
INSERT INTO electors
(name, dwelling_id, phone, email)
VALUES (:name, :dwelling_id, :phone, :email)
RETURNING id
-- :name update-elector! :! :n
-- :doc update an existing elector record
UPDATE electors
SET name = :name, dwelling_id = :dwelling_id, phone = :phone, email = :email
WHERE id = :id
-- :name get-elector :? :1
-- :doc retrieve a elector given the id.
SELECT * FROM electors
WHERE id = :id
-- :name delete-elector! :! :n
-- :doc delete a elector given the id
DELETE FROM electors
WHERE id = :id
-- :name create-followupaction! :! :n
-- :doc creates a new followupaction record
INSERT INTO followupactions
(request_id, actor, date, notes, closed)
VALUES (:request_id, :actor, :date, :notes, :closed)
RETURNING id
-- We don't update followup actions. They're permanent record.
-- :name get-followupaction :? :1
-- :doc retrieve a followupaction given the id.
SELECT * FROM followupactions
WHERE id = :id
-- We don't delete followup actions. They're permanent record.
-- followup methods are reference data, do not need to be programmatically maintained.
-- :name create-followuprequest! :! :n
-- :doc creates a new followupaction record
INSERT INTO followuprequests
(elector_id, visit_id, issue_id, method_id)
VALUES (:elector_id, :visit_id, :issue_id, :method_id)
RETURNING id
-- We don't update followup requests. They're permanent record.
-- :name get-followuprequest :? :1
-- :doc retrieve a followupaction given the id.
SELECT * FROM followuprequests
WHERE id = :id
-- We don't delete followup requests. They're permanent record.
-- :name create-issueexpertise! :! :n
-- :doc creates a new issueexpertise record
INSERT INTO issueexpertise
(canvasser_id, issue_id, method_id)
VALUES (:canvasser_id, :issue_id, :method_id)
-- issueexertise is a link table, doesn't have an id field.
-- :name update-issueexpertise! :! :n
-- :doc update an existing issueexpertise record
UPDATE issueexpertise
SET canvasser_id = :canvasser_id, issue_id = :issue_id, method_id = :method_id
WHERE id = :id
-- :name get-issueexpertise :? :1
-- :doc retrieve a issueexpertise given the canvasser_id -
-- getting it by its own id is unlikely to be interesting or useful.
SELECT * FROM issueexpertise
WHERE canvasser_id = :canvasser_id
-- :name delete-issueexpertise! :! :n
-- :doc delete a issueexpertise given the id
DELETE FROM issueexpertise
WHERE id = :id
-- :name create-issue! :! :n
-- :doc creates a new issue record
INSERT INTO issues
(id, url, content, current)
VALUES (:id, :url, :content, :current)
RETURNING id
-- :name update-issue! :! :n
-- :doc update an existing issue record
UPDATE issues
SET url = :url, content = :content, current = :current
WHERE id = :id
-- :name get-issue :? :1
-- :doc retrieve a issue given the id -
SELECT * FROM issues
WHERE id = :id
-- :name delete-issue! :! :n
-- :doc delete a issue given the id
DELETE FROM issues
WHERE id = :id
-- options is virtually reference data; it's not urgent to create a programmatic means of editing
-- :name create-visit! :! :n
-- :doc creates a new visit record
INSERT INTO visits
(dwelling_id, canvasser_id)
VALUES (:dwelling_id, :canvasser_id)
RETURNING id
-- visits is audit data; we don't update it.
-- :name get-visit :? :1
-- :doc retrieve a visit given the id.
SELECT * FROM visits
WHERE id = :id
-- visits is audit data; we don't delete it.
-- views are select only
-- :name get-roles-by-canvasser :? :*
-- :doc Get the role names for the canvasser with the specified id
select name from roles_by_canvasser
where canvasser = :canvasser
-- :name get-teams-by-canvasser :? :*
-- :doc Get details of the teams which the canvasser with the specified id is member of.
select * from teams_by_canvasser
where canvasser = :canvasser_id
-- :name get-canvassers-by-team :? :*
-- :doc Get details of all canvassers who are members of the team with the specified id
select * from canvassers_by_team
where team = :team_id
-- :name get-canvassers-by-team :? :*
-- :doc Get details of all authorised canvassers who are members of this team.
select * from canvassers_by_introducer
where introducer = :introducer_id
-- :name get-canvassers-by-search :? :*
-- :doc Get details of all authorised canvassers whose details match this search string.
select * from canvassers
where name like '%' || :search || '%'
or username like '%' || :search || '%'
or email like '%' || :search || '%'
-- :name get-teams_by_organiser :? :*
-- :doc Get details of all the teams organised by the canvasser with the specified id
select * from teams_by_organiser
where organiser = :organiser_id
-- :name get-organisers-by-team :? :*
-- :doc Get details of all organisers of the team with the specified id
select * from organisers_by_team
where team = :team_id

View file

@ -22,7 +22,7 @@
:driver-class-name "org.postgresql.Driver"}) :driver-class-name "org.postgresql.Driver"})
:stop (conman/disconnect! *db*)) :stop (conman/disconnect! *db*))
(conman/bind-connection *db* "sql/queries.auto.sql") (conman/bind-connection *db* "sql/queries.auto.sql" "sql/queries.sql")
(defn to-date [^java.sql.Date sql-date] (defn to-date [^java.sql.Date sql-date]
(-> sql-date (.getTime) (java.util.Date.))) (-> sql-date (.getTime) (java.util.Date.)))

View file

@ -13,6 +13,7 @@
[youyesyet.routes.oauth :refer [oauth-routes]] [youyesyet.routes.oauth :refer [oauth-routes]]
[youyesyet.routes.auto-json :refer [auto-rest-routes]] [youyesyet.routes.auto-json :refer [auto-rest-routes]]
[youyesyet.routes.auto :refer [auto-selmer-routes]] [youyesyet.routes.auto :refer [auto-selmer-routes]]
[youyesyet.routes.rest :refer [rest-routes]]
[youyesyet.env :refer [defaults]])) [youyesyet.env :refer [defaults]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -71,6 +72,8 @@
(-> #'auto-selmer-routes (-> #'auto-selmer-routes
(wrap-routes middleware/wrap-csrf) (wrap-routes middleware/wrap-csrf)
(wrap-routes middleware/wrap-formats)) (wrap-routes middleware/wrap-formats))
(-> #'rest-routes
(wrap-routes middleware/wrap-formats))
'oauth-routes 'oauth-routes
(route/resources "/") (route/resources "/")
(route/not-found (route/not-found

View file

@ -3,10 +3,13 @@
(:require [clojure.walk :refer [keywordize-keys]] (:require [clojure.walk :refer [keywordize-keys]]
[noir.response :as nresponse] [noir.response :as nresponse]
[noir.util.route :as route] [noir.util.route :as route]
[youyesyet.db.core :as db-core] [youyesyet.db.core :as db]
[compojure.core :refer [defroutes GET POST]] [compojure.core :refer [defroutes GET POST]]
[ring.util.http-response :as response] [ring.util.http-response :as response]
[clojure.java.io :as io])) [clojure.java.io :as io]
[youyesyet.locality :as l]
[youyesyet.utils :refer :all]
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
@ -36,14 +39,29 @@
"Get data local to the user of the canvasser app. Expects arguments `lat` and "Get data local to the user of the canvasser app. Expects arguments `lat` and
`long`. Returns a block of data for that locality" `long`. Returns a block of data for that locality"
[request] [request]
) (let
[{latitude :latitude longitude :longitude} (keywordize-keys (:params request))
neighbourhood (l/neighbouring-localities
(l/locality
(coerce-to-number latitude)
(coerce-to-number longitude)))
addresses (flatten
(map
#(db/list-addresses-by-locality db/*db* {:locality %})
neighbourhood))]
addresses
))
(defn get-issues (defn get-issues
"Get current issues. No arguments expected." "Get current issues. No arguments expected."
[request]) [request])
;; (defroutes rest-routes (defroutes rest-routes
;; (GET "/rest/get-local-data" request (route/restricted (get-local-data request))) (GET "/rest/get-local-data" request (get-local-data request))
;; (GET "/rest/get-issues" request (route/restricted (get-issues request))) ;; (GET "/rest/get-issues" request (route/restricted (get-issues request)))
;; (GET "/rest/set-intention" request (route/restricted (set-intention request))) ;; (GET "/rest/set-intention" request (route/restricted (set-intention request)))
;; (GET "/rest/request-followup" request (route/restricted (request-followup request)))) ;; (GET "/rest/request-followup" request (route/restricted (request-followup request))))
)

View file

@ -0,0 +1,54 @@
(ns youyesyet.locality)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.locality: compute localities.
;;;;
;;;; 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
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; See also resources/sql/locality-trigger.sql
(defn locality
"Compute the locality index for this `latitude`/`longitude` pair."
[latitude longitude]
(+
(* 10000 ;; left-shift the latitude component four digits
(int
(* latitude 1000)))
(- ;; invert the sign of the longitude component, since
(int ;; we're interested in localities West of Greenwich.
(* longitude 1000)))))
(defn neighbouring-localities
"Return this locality with the localities immediately
north east, north, north west, east, west, south west,
south and south east of it."
;; TODO: I'm not absolutely confident of my arithmetic here!
[locality]
(list
(- locality 9999)
(- locality 10000)
(- locality 10001)
(- locality 1)
locality
(+ locality 1)
(+ locality 9999)
(+ locality 10000)
(+ locality 10001)))

View file

@ -0,0 +1,35 @@
(ns youyesyet.utils
#?(:clj (require [clojure.tools.logging :as log]))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.locality: small utility functions.
;;;;
;;;; 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
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn coerce-to-number [v]
"If it is possible to do so, coerce `v` to a number"
(if (number? v) v
(try
(read-string (str v))
#?(:clj (catch Exception any
(log/error (str "Could not coerce '" v "' to number: " any)))
:cljs (js/console.log (str "Could not coerce '" v "' to number: " any))))))

View file

@ -134,6 +134,18 @@
(secretary/defroute "/building/:address" {address-id :address} (secretary/defroute "/building/:address" {address-id :address}
(log-and-dispatch [:set-address address-id])) (log-and-dispatch [:set-address address-id]))
(secretary/defroute "/elector" []
(log-and-dispatch [:set-active-page :elector]))
(secretary/defroute "/elector/:elector" {elector-id :elector}
(log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :elector}]))
(secretary/defroute "/elector/:elector/:consent" {elector-id :elector consent :consent}
(log-and-dispatch [:set-consent-and-page {:elector-id elector-id :consent (and true consent) :page :elector}]))
(secretary/defroute "/elector" []
(log-and-dispatch [:set-active-page :elector]))
(secretary/defroute "/followup" [] (secretary/defroute "/followup" []
(log-and-dispatch [:set-active-page :followup])) (log-and-dispatch [:set-active-page :followup]))

View file

@ -4,6 +4,7 @@
(:require [cljs.reader :refer [read-string]] (:require [cljs.reader :refer [read-string]]
[re-frame.core :refer [dispatch reg-event-db]] [re-frame.core :refer [dispatch reg-event-db]]
[youyesyet.canvasser-app.state :as db] [youyesyet.canvasser-app.state :as db]
[youyesyet.utils :refer :all]
)) ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -36,12 +37,6 @@
(merge state {:error nil :feedback nil})) (merge state {:error nil :feedback nil}))
(defn coerce-to-number [v]
(if (number? v) v
(try
(read-string (str v))
(catch js/Object any
(js/console.log (str "Could not coerce '" v "' to number: " any))))))
(defn get-elector (defn get-elector
@ -169,9 +164,10 @@
:set-consent-and-page :set-consent-and-page
(fn [db [_ args]] (fn [db [_ args]]
(let [page (:page args) (let [page (:page args)
consent (:consent args)
elector-id (coerce-to-number (:elector-id args)) elector-id (coerce-to-number (:elector-id args))
elector (get-elector elector-id db)] elector (get-elector elector-id db)]
(js/console.log (str "Setting page to " page ", consent to true for " elector)) (js/console.log (str "Setting page to " page ", consent to " consent " for " elector))
(assoc (clear-messages db) :elector (assoc elector :consent true) :page page)))) (assoc (clear-messages db) :elector (assoc elector :consent true) :page page))))

View file

@ -39,6 +39,7 @@
(defn big-link (defn big-link
[text & {:keys [target handler]}] [text & {:keys [target handler]}]
(js/console.log (str "Constructing big link; target is '" target "'; handler is '" handler "'"))
[:div.big-link-container {:key (gensym "big-link")} [:div.big-link-container {:key (gensym "big-link")}
[:a.big-link (merge [:a.big-link (merge
(if target {:href target}{}) (if target {:href target}{})

View file

@ -64,6 +64,7 @@
[:send-intention {:elector-id (:id elector) [:send-intention {:elector-id (:id elector)
:intention optid}])}]])])) :intention optid}])}]])]))
(defn issue-row (defn issue-row
"Generate a row containing an issue cell for a particular elector" "Generate a row containing an issue cell for a particular elector"
[elector] [elector]
@ -76,25 +77,17 @@
(defn panel (defn panel
"Generate the elector panel." "Generate the elector panel."
[] []
(let [address @(subscribe [:address]) (let [elector @(subscribe [:elector])
dwelling @(subscribe [:dwelling]) options @(subscribe [:options])]
elector @(subscribe [:elector]) (if elector
electors [elector]
options @(subscribe [:options])
sub-address (:sub-address dwelling)]
(if address
[:div [:div
[:h1 (if sub-address [:h1 (:name elector)]
(str sub-address ", " (:address address))
(:address address))]
[:div.container {:id "main-container"} [:div.container {:id "main-container"}
[:table [:table
[:tbody [:tbody
(gender-row elector)
(name-row elector)
(map (map
#(option-row elector %) #(option-row elector %)
options) options)
(issue-row elector)]] (issue-row elector)]]
(ui/back-link)]] (ui/back-link "#dwelling")]]
(ui/error-panel "No address selected")))) (ui/error-panel "No elector selected"))))

View file

@ -41,11 +41,11 @@
(let [issue @(subscribe [:issue]) (let [issue @(subscribe [:issue])
issues @(subscribe [:issues]) issues @(subscribe [:issues])
elector @(subscribe [:elector]) elector @(subscribe [:elector])
address @(subscribe [:address])] dwelling @(subscribe [:dwelling])]
(js/console.log (str "Issue is " issue "; elector is " elector)) (js/console.log (str "Issue is " issue "; elector is " elector))
(cond (cond
(nil? address) (nil? dwelling)
(ui/error-panel "No address selected") (ui/error-panel "No dwelling selected")
(nil? issues) (nil? issues)
(ui/error-panel "No issues loaded") (ui/error-panel "No issues loaded")
true true
@ -59,7 +59,7 @@
:on-change #(dispatch [:set-elector (.-value (.-target %))])} :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 dwelling))]]
[:p.widget [:p.widget
[:label {:for "issue"} "Issue"] [:label {:for "issue"} "Issue"]
;; #(reset! val (-> % .-target .-value)) ;; #(reset! val (-> % .-target .-value))

View file

@ -34,12 +34,10 @@
[] []
(let [elector @(subscribe [:elector])] (let [elector @(subscribe [:elector])]
[:div [:div
[:h1 "GDPR Consent"] [:h1 "I, " (:name elector)]
[:div.container {:id "main-container"} [:div.container {:id "main-container"}
[:table [:table
[:tbody [:tbody
[:tr
[:th "I," (:name elector)]]
[:tr [:tr
[:td [:td
[:p "Consent to have data about my voting intention stored by " [:p "Consent to have data about my voting intention stored by "
@ -53,13 +51,12 @@
[:canvas {:id "signature-pad"}]]]]]] [:canvas {:id "signature-pad"}]]]]]]
(ui/back-link "#dwelling") (ui/back-link "#dwelling")
(ui/big-link "I consent" (ui/big-link "I consent"
:handler #(fn [] (dispatch [:set-consent-and-page {:elector-id (:id elector) :target (str "#elector/" (:id elector) "/true")
:page :elector}]))) :handler #(fn [] (dispatch [:set-consent-and-page {:elector-id (:id elector) :page :elector}])))
;; TODO: need to save the signature ;; TODO: need to save the signature
(ui/big-link "I DO NOT consent" (ui/big-link "I DO NOT consent"
:handler :target (str "#elector/" (:id elector) "/true"))]))
#(fn [] (dispatch [:set-elector-and-page {:elector-id (:id elector) ;; :handler #(fn [] (dispatch [:set-elector-and-page {:elector-id (:id elector) :page :elector}])))]))
:page :elector}])))]))
(defn gdpr-did-mount (defn gdpr-did-mount