Merge branch 'feature/reflow-app' into develop

This commit is contained in:
Simon Brooke 2018-08-29 13:55:57 +01:00
commit 872fc2b6a8
14 changed files with 178 additions and 249 deletions

View file

@ -362,7 +362,6 @@ th {
/* content of the current page in the Wiki - editable, provided by users. Within main-container */ /* content of the current page in the Wiki - editable, provided by users. Within main-container */
#content { #content {
border: thin solid silver;
width: 80%; width: 80%;
float: right; float: right;
padding-bottom: 5em; padding-bottom: 5em;
@ -396,7 +395,6 @@ th {
/* content of the current in the Wiki - editable, provided by users. Within main-container */ /* content of the current in the Wiki - editable, provided by users. Within main-container */
#content { #content {
border: thin solid silver;
width: 100%; width: 100%;
padding-bottom: 2em; padding-bottom: 2em;
} }

View file

@ -43,7 +43,7 @@ SELECT DISTINCT request.*,
addresses.address ||', '|| addresses.postcode ||', '|| visits.date AS visit_id_expanded, addresses.address ||', '|| addresses.postcode ||', '|| visits.date AS visit_id_expanded,
request.issue_id as issue_id_expanded, request.issue_id as issue_id_expanded,
request.method_id AS method_id_expanded, request.method_id AS method_id_expanded,
visits.date visits.date AS raised
FROM followuprequests as request, FROM followuprequests as request,
ln_experts_issues_canvassers as expertise, ln_experts_issues_canvassers as expertise,
canvassers as experts, canvassers as experts,
@ -58,7 +58,7 @@ and request.visit_id = visits.id
and visits.address_id = addresses.id and visits.address_id = addresses.id
and request.issue_id = expertise.issue_id and request.issue_id = expertise.issue_id
and expertise.canvasser_id = :expert and expertise.canvasser_id = :expert
ORDER BY visits.date desc ORDER BY raised
--:name get-last-visit-by-canvasser :? :1 --:name get-last-visit-by-canvasser :? :1
--:doc returns the most recent visit record of the canvasser with the specified `:id` --:doc returns the most recent visit record of the canvasser with the specified `:id`

View file

@ -5,6 +5,7 @@
<!-- head: if you want entire custom head content, override this block. --> <!-- head: if you want entire custom head content, override this block. -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="referrer" content="same-origin">
{% style "/css/yyy-common.css" %} {% style "/css/yyy-common.css" %}
{% style "/css/yyy-site.css" %} {% style "/css/yyy-site.css" %}
{% style "/css/spinner.css" %} {% style "/css/spinner.css" %}
@ -27,9 +28,13 @@
<menu id="nav-menu" class="nav"> <menu id="nav-menu" class="nav">
<li class=""><a href="{{servlet-context}}/home">Home</a></li> <li class=""><a href="{{servlet-context}}/home">Home</a></li>
<li class=""><a href="{{servlet-context}}/library">Library</a></li> <li class=""><a href="{{servlet-context}}/library">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>
{% else %}
<li class=""><a href="{{servlet-context}}/register">Register</a></li> <li class=""><a href="{{servlet-context}}/register">Register</a></li>
<li class="">{% if user %}<a href="{{servlet-context}}/logout">Logout</a> <li class=""><a href="{{servlet-context}}/login">Login</a></li>
{% else %}<a href="{{servlet-context}}/login">Login</a>{% endif %}</li> {% endif %}
<li class=""><a href="{{servlet-context}}/about">About</a></li> <li class=""><a href="{{servlet-context}}/about">About</a></li>
{% if user %} {% if user %}
<li id="user"><a href="{{servlet-context}}/profile">Logged in as {{user.username}}</a></li> <li id="user"><a href="{{servlet-context}}/profile">Logged in as {{user.username}}</a></li>

View file

@ -36,19 +36,16 @@ Add a new Followuprequest
<thead> <thead>
<tr> <tr>
<th> <th>
Id Elector
</th> </th>
<th> <th>
Elector_id Raised
</th> </th>
<th> <th>
Visit_id Issue
</th> </th>
<th> <th>
Issue_id Method
</th>
<th>
Method_id
</th> </th>
<th> <th>
&nbsp; &nbsp;
@ -56,13 +53,10 @@ Method_id
</tr> </tr>
<tr> <tr>
<th> <th>
<input id='id' type='text' name='id' value='{{ params.id }}'/>
</th>
<th>
<input id='elector_id' type='text' name='elector_id' value='{{ params.elector_id }}'/> <input id='elector_id' type='text' name='elector_id' value='{{ params.elector_id }}'/>
</th> </th>
<th> <th>
<input id='visit_id' type='text' name='visit_id' value='{{ params.visit_id }}'/> <input id='raised' type='text' name='raised' value='{{ params.raised }}'/>
</th> </th>
<th> <th>
<input id='issue_id' type='text' name='issue_id' value='{{ params.issue_id }}'/> <input id='issue_id' type='text' name='issue_id' value='{{ params.issue_id }}'/>
@ -79,17 +73,12 @@ Method_id
{% for record in records %} {% for record in records %}
<tr> <tr>
<td> <td>
{{ record.id }}
</td>
<td>
<a href='{{servlet-context}}/form-electors-Elector?id={{ record.elector_id }}'> <a href='{{servlet-context}}/form-electors-Elector?id={{ record.elector_id }}'>
{{ record.elector_id_expanded }} {{ record.elector_id_expanded }}
</a> </a>
</td> </td>
<td> <td>
<a href='{{servlet-context}}/form-visits-Visit?id={{ record.visit_id }}'> {{ record.raised}}
{{ record.visit_id_expanded }}
</a>
</td> </td>
<td> <td>
<a href='{{servlet-context}}/form-issues-Issue?id={{ record.issue_id }}'> <a href='{{servlet-context}}/form-issues-Issue?id={{ record.issue_id }}'>

View file

@ -140,7 +140,8 @@
params :visit_id (current-visit-id request))) params :visit_id (current-visit-id request)))
201) 201)
{:status 400 {:status 400
:body (json/write-str "create-intention requires params: `option_id` :body (json/write-str
"create-intention requires params: `option_id`
and either `locality` or both `address_id` and `elector_id`.")}) and either `locality` or both `address_id` and `elector_id`.")})
request))) request)))
@ -164,7 +165,28 @@
request))) request)))
(defn update-elector-signature!
"Set the `signature` in the params of this `request` as the signature for
the elector whose `id` is in the params of this `request`."
[request]
(let [params (massage-params request)]
(log/debug "Update elector signature with params: " params)
(valid-user-or-forbid
(with-params-or-error
(do-or-server-fail
(db/update-elector! db/*db* params)
201)
params
#{:id :signature})
request)))
(defroutes rest-routes (defroutes rest-routes
(GET "/rest/get-local-data" request (route/restricted (get-local-data request))) (GET "/rest/get-local-data"
(GET "/rest/create-intention" request (route/restricted (create-intention-and-visit! request))) request (route/restricted (get-local-data request)))
(GET "/rest/create-request" request (route/restricted (create-request-and-visit! request)))) (GET "/rest/create-intention"
request (route/restricted (create-intention-and-visit! request)))
(GET "/rest/create-request"
request (route/restricted (create-request-and-visit! request)))
(GET "/rest/update-elector-signature"
request (route/restricted (update-elector-signature! request))))

View file

@ -118,61 +118,57 @@
;; Routes ;; Routes
(secretary/set-config! :prefix "#") (secretary/set-config! :prefix "#")
(defn log-and-dispatch [arg]
(js/console.log (str "Dispatching " arg))
(rf/dispatch arg))
(secretary/defroute "/" [] (secretary/defroute "/" []
(log-and-dispatch [:set-active-page :map])) (ui/log-and-dispatch [:set-active-page :map]))
(secretary/defroute "/about" [] (secretary/defroute "/about" []
(log-and-dispatch [:set-active-page :about])) (ui/log-and-dispatch [:set-active-page :about]))
(secretary/defroute "/dwelling" [] (secretary/defroute "/dwelling" []
(log-and-dispatch [:set-active-page :dwelling])) (ui/log-and-dispatch [:set-active-page :dwelling]))
(secretary/defroute "/dwelling/:dwelling" {dwelling-id :dwelling} (secretary/defroute "/dwelling/:dwelling" {dwelling-id :dwelling}
(log-and-dispatch [:set-dwelling dwelling-id]) (ui/log-and-dispatch [:set-dwelling dwelling-id])
(log-and-dispatch [:set-active-page :dwelling])) (ui/log-and-dispatch [:set-active-page :dwelling]))
(secretary/defroute "/building/:address" {address-id :address} (secretary/defroute "/building/:address" {address-id :address}
(log-and-dispatch [:set-address address-id])) (ui/log-and-dispatch [:set-address address-id]))
(secretary/defroute "/elector" [] (secretary/defroute "/elector" []
(log-and-dispatch [:set-active-page :elector])) (ui/log-and-dispatch [:set-active-page :elector]))
(secretary/defroute "/elector/:elector" {elector-id :elector} (secretary/defroute "/elector/:elector/:consent" {elector-id :elector}
(log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :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} (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}])) (ui/log-and-dispatch [:set-active-page {:page :elector}]))
(secretary/defroute "/elector" [] (secretary/defroute "/elector" []
(log-and-dispatch [:set-active-page :elector])) (ui/log-and-dispatch [:set-active-page :elector]))
(secretary/defroute "/followup" [] (secretary/defroute "/followup" []
(log-and-dispatch [:set-active-page :followup])) (ui/log-and-dispatch [:set-active-page :followup]))
(secretary/defroute "/gdpr" [] (secretary/defroute "/gdpr" []
(log-and-dispatch [:set-active-page :gdpr])) (ui/log-and-dispatch [:set-active-page :gdpr]))
(secretary/defroute "/gdpr/:elector" {elector-id :elector} (secretary/defroute "/gdpr/:elector" {elector-id :elector}
(log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :gdpr}])) (ui/log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :gdpr}]))
(secretary/defroute "/issues" [] (secretary/defroute "/issues" []
(log-and-dispatch [:set-active-page :issues])) (ui/log-and-dispatch [:set-active-page :issues]))
(secretary/defroute "/issues/:elector" {elector-id :elector} (secretary/defroute "/issues/:elector" {elector-id :elector}
(log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :issues}])) (ui/log-and-dispatch [:set-elector-and-page {:elector-id elector-id :page :issues}]))
(secretary/defroute "/issue/:issue" {issue :issue} (secretary/defroute "/issue/:issue" {issue :issue}
(log-and-dispatch [:set-and-go-to-issue issue])) (ui/log-and-dispatch [:set-and-go-to-issue issue]))
(secretary/defroute "/map" [] (secretary/defroute "/map" []
(log-and-dispatch [:set-active-page :map])) (ui/log-and-dispatch [:set-active-page :map]))
(secretary/defroute "/set-intention/:elector/:intention" {elector-id :elector intention :intention} (secretary/defroute "/set-intention/:elector/:intention" {elector-id :elector intention :intention}
(log-and-dispatch [:set-intention {:elector-id elector-id :intention intention}])) (ui/log-and-dispatch [:set-intention {:elector-id elector-id :intention intention}]))
;; ------------------------- ;; -------------------------
;; History ;; History
@ -193,7 +189,7 @@
(defn init! [] (defn init! []
(rf/dispatch-sync [:initialize-db]) (rf/dispatch-sync [:initialize-db])
(rf/dispatch-sync [:get-current-location]) (rf/dispatch [:get-current-location])
(rf/dispatch [:fetch-locality]) (rf/dispatch [:fetch-locality])
(rf/dispatch [:fetch-options]) (rf/dispatch [:fetch-options])
(rf/dispatch [:fetch-issues]) (rf/dispatch [:fetch-issues])

View file

@ -7,7 +7,6 @@
[re-frame.core :refer [dispatch reg-event-db reg-event-fx subscribe]] [re-frame.core :refer [dispatch reg-event-db reg-event-fx subscribe]]
[ajax.core :refer [GET]] [ajax.core :refer [GET]]
[ajax.json :refer [json-request-format json-response-format]] [ajax.json :refer [json-request-format json-response-format]]
[youyesyet.canvasser-app.state :as db]
[youyesyet.locality :refer [locality]] [youyesyet.locality :refer [locality]]
)) ))
@ -45,13 +44,14 @@
(.getCurrentPosition (.getCurrentPosition
(.-geolocation js/navigator) (.-geolocation js/navigator)
(fn [position] (fn [position]
(js/console.log (str "Current location is: " (let [lat (.-latitude (.-coords position))
(.-latitude (.-coords position)) ", " lng (.-longitude (.-coords position))]
(.-longitude (.-coords position)))) (js/console.log (str "Current location is: " lat ", " lng))
(dispatch [:set-latitude (.-latitude (.-coords position))]) (dispatch [:set-latitude lat])
(dispatch [:set-longitude (.-longitude (.-coords position))]) (dispatch [:set-longitude lng])
(locality (.-latitude (.-coords position)) (.-longitude (.-coords position)))))) ;; (.panTo @(subscribe [:view]) (.latLng js/L lat lng))
(js/console.log "Geolocation not available") (locality lat lng))))
(js/console.log "Geolocation not available"))
(catch js/Object any (catch js/Object any
(js/console.log "Exception while trying to access location: " + any) (js/console.log "Exception while trying to access location: " + any)
0))) 0)))

View file

@ -140,34 +140,6 @@
db/default-db)) db/default-db))
;; (reg-event-fx
;; :feedback
;; (fn [x y]
;; (js/console.log (str "Feedback event called with x = " x "; y = " y))
;; (:db x)))
;; (reg-event-fx
;; :issues
;; (fn [x y]
;; (js/console.log (str "Issues event called with x = " x "; y = " y))
;; (:db x)))
;; (reg-event-fx
;; :options
;; (fn [x y]
;; (js/console.log (str "Options event called with x = " x "; y = " y))
;; (:db x)))
;; (reg-event-fx
;; :event
;; (fn [x y]
;; (js/console.log (str "Event event called with x = " x "; y = " y))
;; (:db x)))
(reg-event-fx (reg-event-fx
:fetch-locality :fetch-locality
(fn [{db :db} _] (fn [{db :db} _]
@ -205,35 +177,28 @@
(reg-event-fx (reg-event-fx
:process-locality :process-locality
;; TODO: why is this an `-fx`? Does it need to be?
(fn (fn
[{db :db} [_ response]] [{db :db} [_ response]]
(js/console.log (str "Updating locality data: " (count response) " addresses " )) (js/console.log (str "Updating locality data: " (count response) " addresses " ))
(refresh-map-pins) (refresh-map-pins)
{:dispatch-later [{:ms 60000 :dispatch [:fetch-locality]} {:db (assoc
{:ms 1000 :dispatch [:get-current-location]}]
:db (assoc
(remove-from-feedback db :fetch-locality) (remove-from-feedback db :fetch-locality)
:addresses (js->clj response))})) :addresses (js->clj response))}))
(reg-event-fx (reg-event-fx
:bad-locality :bad-locality
;; TODO: why is this an `-fx`? Does it need to be?
(fn (fn
[{db :db} [_ response]] [{db :db} [_ response]]
;; TODO: signal something has failed? It doesn't matter very much, unless it keeps failing. ;; TODO: signal something has failed? It doesn't matter very much, unless it keeps failing.
(js/console.log "Failed to fetch locality data") (js/console.log "Failed to fetch locality data")
;; loop to do it again ;; loop to do it again
(dispatch [:dispatch-later [{:ms 60000 :dispatch [:fetch-locality]}]]) (dispatch [:dispatch-later [{:ms 60000 :dispatch [:fetch-locality]}]])
(assoc {:db (assoc
(remove-from-feedback db :fetch-locality) (remove-from-feedback db :fetch-locality)
:error (cons :fetch-locality (:error db))))) :error (cons :fetch-locality (:error db)))}))
;; (reg-event-fx
;; :process-outqueue
;; (fn [{db :db} _]
;; (if
;; (empty? (:outqueue db))
(reg-event-fx (reg-event-fx
@ -262,12 +227,12 @@
(reg-event-db (reg-event-db
;; TODO: should try again
:bad-options :bad-options
(fn [db [_ response]] (fn [db [_ response]]
(js/console.log "Failed to fetch options") (js/console.log "Failed to fetch options")
(dispatch [:dispatch-later [{:ms 60000 :dispatch [:fetch-options]}]])
(assoc (assoc
(remove-from-feedback db :fetch-options) db
:error (:response response)))) :error (:response response))))
@ -301,12 +266,12 @@
(reg-event-db (reg-event-db
;; TODO: should try again
:bad-issues :bad-issues
(fn [db [_ response]] (fn [db [_ response]]
(js/console.log "Failed to fetch issues") (js/console.log "Failed to fetch issues")
(dispatch [:dispatch-later [{:ms 60000 :dispatch [:fetch-issues]}]])
(assoc (assoc
(remove-from-feedback db :fetch-issues) db
:error (:response response)))) :error (:response response))))
@ -347,7 +312,7 @@
:method_detail (-> db :method_detail) :method_detail (-> db :method_detail)
:action :create-request}) :action :create-request})
:send-request)) :send-request))
(assoc db :error "Please supply a telephone number to call")))) (assoc db :error "Please supply a telephone number/email address for elector"))))
(reg-event-db (reg-event-db
@ -380,15 +345,34 @@
:page :building)))))) :page :building))))))
(defn do-update-elector
[db elector]
(if-not
;; if the signature has changed
(= (:signature elector) (:signature (:elector db)))
(assoc
(add-to-outqueue
(clear-messages db)
(assoc elector
:action :update-elector-signature))
:elector elector)
(assoc db
:elector elector)))
(reg-event-db
:update-elector
(fn [db [_ elector]]
(js/console.log (str "Elector is " elector))
(do-update-elector db elector)))
(reg-event-db (reg-event-db
:set-consent-and-page :set-consent-and-page
(fn [db [_ args]] (fn [db [_ args]]
(let [page (:page args) (assoc
consent (:consent args) (do-update-elector db (:elector args))
elector-id (coerce-to-number (:elector-id args)) :page (:page args))))
elector (get-elector elector-id db)]
(js/console.log (str "Setting page to " page ", consent to " consent " for " (:name elector)))
(assoc (clear-messages db) :elector (assoc elector :consent true) :page page))))
(reg-event-db (reg-event-db

View file

@ -1,6 +1,7 @@
(ns ^{:doc "Canvasser app client state." (ns ^{:doc "Canvasser app client state."
:author "Simon Brooke"} :author "Simon Brooke"}
youyesyet.canvasser-app.state) youyesyet.canvasser-app.state
(:require [youyesyet.canvasser-app.gis :as gis]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
@ -28,129 +29,21 @@
;;; This is the constructor for the atom in which the state of the user interface is held. ;;; This is the constructor for the atom in which the state of the user interface is held.
;;; The atom gets updated by 'events' registered in handler.cljs, q.v. ;;; The atom gets updated by 'events' registered in handler.cljs, q.v.
(def default-db
{
:addresses
[{:locality 548223905,
:address
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF",
:phone nil,
:postcode "DG7 1RF",
:longitude -3.905045374625994,
:district_id 1,
:dwellings
[{:address_id_expanded
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF, DG7 1RF",
:address_id 18,
:sub_address "",
:id 17,
:id_2 17,
:address_id_2 18,
:sub_address_2 "",
:electors
[{:email nil,
:dwelling_id_2 17,
:dwelling_id_expanded
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF, DG7 1RF, ",
:intentions
[{:locality 548223905,
:visit_id_expanded
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF, DG7 1RF, 2018-06-14 20:29:34.721522",
:option_id_expanded "Yes",
:option_id "Yes",
:option_id_2 "Yes",
:visit_id_2 1,
:elector_id_2 61,
:visit_id 1,
:elector_id 61,
:id 1,
:elector_id_expanded nil,
:id_2 1}],
:phone nil,
:phone_2 nil,
:gender_expanded "Female",
:name "Alice Sutherland",
:dwelling_id 17,
:id 61,
:gender "Female",
:gender_2 "Female",
:name_2 "Alice Sutherland",
:email_2 nil,
:id_2 61}
{:email nil,
:dwelling_id_2 17,
:dwelling_id_expanded
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF, DG7 1RF, ",
:intentions [],
:phone nil,
:phone_2 nil,
:gender_expanded "Female",
:name "Charlie Sutherland",
:dwelling_id 17,
:id 62,
:gender "Female",
:gender_2 "Female",
:name_2 "Charlie Sutherland",
:email_2 nil,
:id_2 62}
{:email nil,
:dwelling_id_2 17,
:dwelling_id_expanded
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF, DG7 1RF, ",
:intentions [],
:phone nil,
:phone_2 nil,
:gender_expanded "Male",
:name "Keith Sutherland",
:dwelling_id 17,
:id 64,
:gender "Male",
:gender_2 "Male",
:name_2 "Keith Sutherland",
:email_2 nil,
:id_2 64}
{:email nil,
:dwelling_id_2 17,
:dwelling_id_expanded
"HAZELFIELD HOUSE, CASTLE DOUGLAS, DG7 1RF, DG7 1RF, ",
:intentions [],
:phone nil,
:phone_2 nil,
:gender_expanded "Female",
:name "Lucy Sutherland",
:dwelling_id 17,
:id 63,
:gender "Female",
:gender_2 "Female",
:name_2 "Lucy Sutherland",
:email_2 nil,
:id_2 63}]}],
:id 18,
:latitude 54.8222716877376}]
;;; the currently selected address, if any. (def default-db
:address nil { ;;; any confirmation message to display
;;; electors at the currently selected dwelling :feedback '("Welcome to the canvasser app!")
:electors nil
;;; any error to display
:error nil
;;; the issue from among the issues which is currently selected.
;;; any confirmation message to display
:feedback '()
;;; the currently selected issue
:issue nil
;;; the issues selected for the issues page on this day.
:issues nil
;;; message of the day ;;; message of the day
:motd "This is a test version only. There is no real data." :motd "This is a test version only. There is no real data."
;;; the options from among which electors can select. ;;; the options from among which electors can select.
:options nil :outqueue '()
;;; the queue of items waiting to be transmitted. ;;; the view of the map we display
:outqueue () :view nil
;;; the currently displayed page within the app. ;;; the currently displayed page within the app.
:page :home :page :home
:view nil ;;; initial starting coords in the centre of Scotland.
:latitude 54.82 :latitude 56
:longitude -3.92 :longitude -4
:zoom 12}) :zoom 12})

View file

@ -28,6 +28,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn log-and-dispatch [arg]
(js/console.log (str "Dispatching " arg))
(rf/dispatch arg))
(defn back-link (defn back-link
"Generate a back link to the preceding page, or, if `target` is specified, "Generate a back link to the preceding page, or, if `target` is specified,
to a particular page." to a particular page."
@ -41,7 +46,7 @@
(defn big-link (defn big-link
[text & {:keys [target handler]}] [text & {:keys [target 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}{})
(if handler {:on-click handler}{})) (if handler {:on-click handler}{}))
text]]) text]])
@ -75,4 +80,5 @@
(nav-link "#/map" "Map" :map collapsed?) (nav-link "#/map" "Map" :map collapsed?)
(nav-link "#/dwelling" "Electors" :dwelling collapsed?) (nav-link "#/dwelling" "Electors" :dwelling collapsed?)
(nav-link "#/issues" "Issues" :issues collapsed?) (nav-link "#/issues" "Issues" :issues collapsed?)
(nav-link "#/about" "About" :about collapsed?)]])) (nav-link "#/about" "About" :about collapsed?)
(nav-link "/logout" "Logout" :logout collapsed?)]]))

View file

@ -41,7 +41,7 @@
[:div [:div
[:h1 (str "Flats at " (:address address))] [:h1 (str "Flats at " (:address address))]
[:div.container {:id "main-container"} [:div.container {:id "main-container"}
(ui/back-link) (ui/back-link "#map")
[:div {:id "dwelling-list"} [:div {:id "dwelling-list"}
(map (map
(fn (fn

View file

@ -80,11 +80,16 @@
(defn panel (defn panel
"Generate the electors panel." "Generate the electors panel."
[] []
(js/console.log "dwelling.panel")
(let [dwelling @(subscribe [:dwelling]) (let [dwelling @(subscribe [:dwelling])
address @(subscribe [:address]) address @(subscribe [:address])
sub-address (:sub-address dwelling) sub-address (:sub-address dwelling)
electors (sort-by :id (:electors dwelling)) electors (sort-by :id (:electors dwelling))
options @(subscribe [:options])] options @(subscribe [:options])
back (if
(> (count (:dwellings address)) 1)
"#building"
"#map")]
(if address (if address
[:div [:div
[:h1 (if sub-address [:h1 (if sub-address
@ -95,7 +100,7 @@
[:tbody [:tbody
(genders-row electors) (genders-row electors)
(names-row electors)]] (names-row electors)]]
(ui/back-link)]] (ui/back-link back)]]
(ui/error-panel "No address selected")))) (ui/error-panel "No address selected"))))

View file

@ -30,6 +30,27 @@
;; OK, the idea here is a GDPR consent form to be signed by the elector ;; OK, the idea here is a GDPR consent form to be signed by the elector
(def sig-pad
;; something the signature pad will be bound to
(atom nil))
(defn send-consent
"Extract the signature from the signature pad, encode it, add it to this
`elector`, and dispatch the `elector`; move on to the page `elector`."
[elector]
(dispatch
[:set-consent-and-page
{:elector-id (:id elector)
:page :elector
:elector (assoc
elector
:signature
(.toDataURL
@sig-pad
"image/svg+xml"))}])
nil)
(defn gdpr-render (defn gdpr-render
[] []
(let [elector @(subscribe [:elector])] (let [elector @(subscribe [:elector])]
@ -48,24 +69,23 @@
only against your electoral district, and not link it to you"]]]] only against your electoral district, and not link it to you"]]]]
[:tr [:tr
[:td [:td
[:canvas {:id "signature-pad"}]]]]]] [:canvas {:id "signature-pad" :on-mouse-out #(send-consent elector)}]]]]]]
(ui/back-link "#dwelling") (ui/back-link "#dwelling")
(ui/big-link "I consent" (ui/big-link "I consent"
:target (str "#elector/" (:id elector) "/true") :target (str "#elector")
:handler #(fn [] (dispatch [:set-consent-and-page {:elector-id (:id elector) :page :elector}]))) :handler #(send-consent elector))
;; TODO: need to save the signature
(ui/big-link "I DO NOT consent" (ui/big-link "I DO NOT consent"
:target (str "#elector/" (:id elector) "/true"))])) :target (str "#elector/" (:id elector) "/false"))]))
;; :handler #(fn [] (dispatch [:set-elector-and-page {:elector-id (:id elector) :page :elector}])))]))
(defn gdpr-did-mount (defn gdpr-did-mount
[] []
(js/SignaturePad. (.getElementById js/document "signature-pad"))) (reset! sig-pad (js/SignaturePad. (.getElementById js/document "signature-pad"))))
(defn panel (defn panel
"A reagent class for the GDPR consent form" "A reagent class for the GDPR consent form"
[] []
(js/console.log "gdpr.panel")
(reagent/create-class {:reagent-render gdpr-render (reagent/create-class {:reagent-render gdpr-render
:component-did-mount gdpr-did-mount})) :component-did-mount gdpr-did-mount}))

View file

@ -0,0 +1,11 @@
(ns youyesyet.canvasser-app.ui-utils-test
(:require [cljs.test :refer-macros [is are deftest testing use-fixtures]]
[reagent.core :as reagent :refer [atom]]
[youyesyet.canvasser-app.ui-utils :refer :all]))
(deftest big-link-tests
(testing "big-link"
(is (= [:div.big-link-container {:key (gensym "big-link")}
[:a.big-link {}
"Test"]]
(big-link "Test" nil nil)))))