#41 Updated client to cope with dwelling changs

This commit is contained in:
simon 2017-07-21 14:18:22 +01:00
parent 88c5c74c52
commit 2e81c7b664
9 changed files with 165 additions and 72 deletions

View file

@ -83,14 +83,14 @@ WHERE id = :id
-- :name create-canvasser! :! :n -- :name create-canvasser! :! :n
-- :doc creates a new canvasser record -- :doc creates a new canvasser record
INSERT INTO canvassers INSERT INTO canvassers
(username, fullname, elector_id, address_id, phone, email, authority_id, authorised) (username, fullname, elector_id, dwelling_id, phone, email, authority_id, authorised)
VALUES (:username, :fullname, :elector_id, :address_id, :phone, :email, :authority_id, :authorised) VALUES (:username, :fullname, :elector_id, :dwelling_id, :phone, :email, :authority_id, :authorised)
RETURNING id RETURNING id
-- :name update-canvasser! :! :n -- :name update-canvasser! :! :n
-- :doc update an existing canvasser record -- :doc update an existing canvasser record
UPDATE canvassers UPDATE canvassers
SET username = :username, fullname = :fullname, elector_id = :elector_id, address_id = :address_id, phone = :phone, email = :email, authority_id = :authority_id, authorised = :authorised 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 WHERE id = :id
-- :name get-canvasser :? :1 -- :name get-canvasser :? :1
@ -138,17 +138,52 @@ DELETE FROM districts
WHERE id = :id 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 -- :name create-elector! :! :n
-- :doc creates a new elector record -- :doc creates a new elector record
INSERT INTO electors INSERT INTO electors
(name, address_id, phone, email) (name, dwelling_id, phone, email)
VALUES (:name, :address_id, :phone, :email) VALUES (:name, :dwelling_id, :phone, :email)
RETURNING id RETURNING id
-- :name update-elector! :! :n -- :name update-elector! :! :n
-- :doc update an existing elector record -- :doc update an existing elector record
UPDATE electors UPDATE electors
SET name = :name, address_id = :address_id, phone = :phone, email = :email SET name = :name, dwelling_id = :dwelling_id, phone = :phone, email = :email
WHERE id = :id WHERE id = :id
-- :name get-elector :? :1 -- :name get-elector :? :1
@ -254,8 +289,8 @@ WHERE id = :id
-- :name create-visit! :! :n -- :name create-visit! :! :n
-- :doc creates a new visit record -- :doc creates a new visit record
INSERT INTO visits INSERT INTO visits
(address_id, canvasser_id) (dwelling_id, canvasser_id)
VALUES (:address_id, :canvasser_id) VALUES (:dwelling_id, :canvasser_id)
RETURNING id RETURNING id
-- visits is audit data; we don't update it. -- visits is audit data; we don't update it.

View file

@ -14,6 +14,7 @@
[youyesyet.canvasser-app.subscriptions] [youyesyet.canvasser-app.subscriptions]
[youyesyet.canvasser-app.ui-utils :as ui] [youyesyet.canvasser-app.ui-utils :as ui]
[youyesyet.canvasser-app.views.about :as about] [youyesyet.canvasser-app.views.about :as about]
[youyesyet.canvasser-app.views.building :as building]
[youyesyet.canvasser-app.views.electors :as electors] [youyesyet.canvasser-app.views.electors :as electors]
[youyesyet.canvasser-app.views.followup :as followup] [youyesyet.canvasser-app.views.followup :as followup]
[youyesyet.canvasser-app.views.issue :as issue] [youyesyet.canvasser-app.views.issue :as issue]
@ -50,6 +51,9 @@
(defn about-page [] (defn about-page []
(about/panel)) (about/panel))
(defn building-page []
(building/panel))
(defn electors-page [] (defn electors-page []
(electors/panel)) (electors/panel))
@ -67,6 +71,7 @@
(def pages (def pages
{:about #'about-page {:about #'about-page
:building #'building-page
:electors #'electors-page :electors #'electors-page
:followup #'followup-page :followup #'followup-page
:issues #'issues-page :issues #'issues-page
@ -105,10 +110,10 @@
(secretary/defroute "/about" [] (secretary/defroute "/about" []
(rf/dispatch [:set-active-page :about])) (rf/dispatch [:set-active-page :about]))
(secretary/defroute "/electors" [] (secretary/defroute "/electors/:dwelling" {dwelling-id :dwelling}
(rf/dispatch [:set-active-page :electors])) (rf/dispatch [:set-dwelling dwelling-id]))
(secretary/defroute "/electors/:address" {address-id :address} (secretary/defroute "/building/:address" {address-id :address}
(rf/dispatch [:set-address address-id])) (rf/dispatch [:set-address address-id]))
(secretary/defroute "/followup" [] (secretary/defroute "/followup" []

View file

@ -112,7 +112,29 @@
(fn [db [_ address-id]] (fn [db [_ address-id]]
(let [id (read-string address-id) (let [id (read-string address-id)
address (first (remove nil? (map #(if (= id (:id %)) %) (:addresses db))))] address (first (remove nil? (map #(if (= id (:id %)) %) (:addresses db))))]
(assoc (clear-messages db) :address address :page :electors)))) (if
(= (count (:dwellings address)) 1)
(assoc (clear-messages db)
:address address
:dwelling (first (:dwellings address))
:page :electors)
(assoc (clear-messages db)
:address address
:dwelling nil
:page :building)))))
(reg-event-db
:set-dwelling
(fn [db [_ dwelling-id]]
(let [id (read-string dwelling-id)
dwelling (first
(remove
nil?
(map
#(if (= id (:id %)) %)
(mapcat :dwellings (:addresses db)))))]
(assoc (clear-messages db) :dwelling dwelling :page :electors))))
(reg-event-db (reg-event-db

View file

@ -33,49 +33,53 @@
(def default-db (def default-db
{;;; the currently selected address, if any. {;;; the currently selected address, if any.
:address {:id 1 :address "13 Imaginary Terrace, IM1 3TE" :latitude 55.8253043 :longitude -4.2569057 :address {:id 1 :address "13 Imaginary Terrace, IM1 3TE" :latitude 55.8253043 :longitude -4.2569057
:electors [{:id 1 :name "Alan Anderson" :gender :male :intention :no} :dwellings [{:id 1
{:id 2 :name "Ann Anderson" :gender :female} :electors [{:id 1 :name "Alan Anderson" :gender :male :intention :no}
{:id 3 :name "Alex Anderson" :gender :fluid :intention :yes} {:id 2 :name "Ann Anderson" :gender :female}
{:id 4 :name "Andy Anderson" :intention :yes}]} {:id 3 :name "Alex Anderson" :gender :fluid :intention :yes}
;;; a list of the addresses in the current location at which there {:id 4 :name "Andy Anderson" :intention :yes}]}]}
;;; are electors registered. ;;; a list of the addresses in the current location at which there
:addresses [{:id 1 :address "13 Imaginary Terrace, IM1 3TE" :latitude 55.8253043 :longitude -4.2570944 ;;; are electors registered.
:electors [{:id 1 :name "Alan Anderson" :gender :male :intention :no} :addresses [{:id 1 :address "13 Imaginary Terrace, IM1 3TE" :latitude 55.8253043 :longitude -4.2570944
{:id 2 :name "Ann Anderson" :gender :female} :dwellings [{:id 1
{:id 3 :name "Alex Anderson" :gender :fluid :intention :yes} :electors [{:id 1 :name "Alan Anderson" :gender :male :intention :no}
{:id 4 :name "Andy Anderson" :intention :yes}]} {:id 2 :name "Ann Anderson" :gender :female}
{:id 2 :address "15 Imaginary Terrace, IM1 3TE" :latitude 55.8252354 :longitude -4.2572778 {:id 3 :name "Alex Anderson" :gender :fluid :intention :yes}
:electors [{:id 1 :name "Beryl Brown" :gender :female} {:id 4 :name "Andy Anderson" :intention :yes}]}]}
{:id 2 :name "Betty Black" :gender :female}]} {:id 2 :address "15 Imaginary Terrace, IM1 3TE" :latitude 55.8252354 :longitude -4.2572778
{:id 3 :address "17 Imaginary Terrace, IM1 3TE" :latitude 55.825166 :longitude -4.257026 :dwellings [{:id 2
:electors [{:id 1 :name "Catriona Crathie" :gender :female :intention :yes} :electors [{:id 1 :name "Beryl Brown" :gender :female}
{:id 2 :name "Colin Caruthers" :gender :male :intention :yes} {:id 2 :name "Betty Black" :gender :female}]}]}
{:id 3 :name "Calum Crathie" :intention :yes}]}
{:id 4 :address "19 Imaginary Terrace, IM1 3TE" :latitude 55.82506950000001 :longitude -4.2570239 {:id 3 :address "17 Imaginary Terrace, IM1 3TE" :latitude 55.825166 :longitude -4.257026
:electors [{:id 1 :name "David Dewar" :gender :male :intention :no}]}] :dwellings [{:id 3 :sub-address "Flat 1"
;;; electors at the currently selected address :electors [{:id 1 :name "Catriona Crathie" :gender :female :intention :yes}
:electors [{:id 1 :name "Alan Anderson" :gender :male :intention :no} {:id 2 :name "Colin Caruthers" :gender :male :intention :yes}
{:id 2 :name "Ann Anderson" :gender :female} {:id 3 :name "Calum Crathie" :intention :yes}]}
{:id 3 :name "Alex Anderson" :gender :fluid :intention :yes} {:id 4 :sub-address "Flat 2"
{:id 4 :name "Andy Anderson" :intention :yes}] :electors [{:id 1 :name "David Dewar" :gender :male :intention :no}]}]}]
;;; any error to display ;;; electors at the currently selected dwelling
:error nil :electors [{:id 1 :name "Alan Anderson" :gender :male :intention :no}
;;; the issue from among the issues which is currently selected. {:id 2 :name "Ann Anderson" :gender :female}
;;; any confirmation message to display {:id 3 :name "Alex Anderson" :gender :fluid :intention :yes}
:feedback nil {:id 4 :name "Andy Anderson" :intention :yes}]
;;; the currently selected issue ;;; any error to display
:issue "Currency" :error nil
;;; the issues selected for the issues page on this day. ;;; the issue from among the issues which is currently selected.
: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" ;;; any confirmation message to display
"Monarchy" "Scotland could keep the Queen. This is an issue to be decided after independence. Yada yada yada" :feedback nil
"Defence" "Scotland will not have nuclear weapons, and will probably not choose to engage in far-off wars. But we could remain members of NATO"} ;;; the currently selected issue
;;; message of the day :issue "Currency"
:motd "This is a test version only. There is no real data." ;;; the issues selected for the issues page on this day.
;;; the options from among which electors can select. :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"
:options [{:id :yes :description "Yes"} {:id :no :description "No"}] "Monarchy" "Scotland could keep the Queen. This is an issue to be decided after independence. Yada yada yada"
;;; the queue of items waiting to be transmitted. "Defence" "Scotland will not have nuclear weapons, and will probably not choose to engage in far-off wars. But we could remain members of NATO"}
:outqueue () ;;; message of the day
;;; the currently displayed page within the app. :motd "This is a test version only. There is no real data."
:page :home ;;; the options from among which electors can select.
}) :options [{:id :yes :description "Yes"} {:id :no :description "No"}]
;;; the queue of items waiting to be transmitted.
:outqueue ()
;;; the currently displayed page within the app.
:page :home})

View file

@ -46,6 +46,11 @@
(fn [db _] (fn [db _]
(:changes db))) (:changes db)))
(reg-sub
:dwelling
(fn [db _]
(:dwelling db)))
(reg-sub (reg-sub
:elector :elector
(fn [db _] (fn [db _]

View file

@ -1,7 +1,8 @@
(ns ^{:doc "Canvasser app households in building panel." (ns ^{:doc "Canvasser app households in building panel."
:author "Simon Brooke"} :author "Simon Brooke"}
youyesyet.canvasser-app.views.building youyesyet.canvasser-app.views.building
(:require [re-frame.core :refer [reg-sub]])) (:require [re-frame.core :refer [reg-sub subscribe]]
[youyesyet.canvasser-app.ui-utils :as ui]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
@ -30,10 +31,22 @@
;;; The pattern from the re-com demo (https://github.com/Day8/re-com) is to have ;;; The pattern from the re-com demo (https://github.com/Day8/re-com) is to have
;;; one source file/namespace per view. Each namespace contains a function 'panel' ;;; one source file/namespace per view. Each namespace contains a function 'panel'
;;; whose output is an enlive-style specification of the view to be redered. ;;; whose output is an enlive-style specification of the view to be redered.
;;; I propose to follow this pattern. This file will (eventually) provide the building view. ;;; I propose to follow this pattern. This file will provide the building view.
(defn panel (defn panel
"Generate the building panel." "Generate the building panel."
[] []
[]) (let [address @(subscribe [:address])
dwellings (:dwellings address)]
[:div
[:h1 (str "Flats at " (:address address))]
[:div.container {:id "main-container"}
(ui/back-link)
[:div {:id "dwelling-list"}
(map
(fn
[dwelling]
(ui/big-link
(:sub-address dwelling)
(str "#/electors/" (:id dwelling))) )
(:dwellings address))]]]))

View file

@ -32,7 +32,7 @@
;;; The pattern from the re-com demo (https://github.com/Day8/re-com) is to have ;;; The pattern from the re-com demo (https://github.com/Day8/re-com) is to have
;;; one source file/namespace per view. Each namespace contains a function 'panel' ;;; one source file/namespace per view. Each namespace contains a function 'panel'
;;; whose output is an enlive-style specification of the view to be redered. ;;; whose output is an enlive-style specification of the view to be redered.
;;; I propose to follow this pattern. This file will (eventually) provide the electors view. ;;; I propose to follow this pattern. This file will provide the electors view.
;;; See https://github.com/simon-brooke/youyesyet/blob/master/doc/specification/userspec.md#electors-view ;;; See https://github.com/simon-brooke/youyesyet/blob/master/doc/specification/userspec.md#electors-view
@ -107,14 +107,16 @@
(defn panel (defn panel
"Generate the electors panel." "Generate the electors panel."
[] []
(let [address @(subscribe [:address]) (let [dwelling @(subscribe [:dwelling])
addresses @(subscribe [:addresses]) address @(subscribe [:address])
electors (sort-by :id (:electors address)) sub-address (:sub-address dwelling)
options @(subscribe [:options]) electors (sort-by :id (:electors dwelling))
changes @(subscribe [:changes])] options @(subscribe [:options])]
(if address (if address
[:div [:div
[:h1 (:address address)] [:h1 (if sub-address
(str sub-address ", " (:address address))
(:address address))]
[:div.container {:id "main-container"} [:div.container {:id "main-container"}
[:table [:table
[:tbody [:tbody

View file

@ -31,7 +31,7 @@
;;; The pattern from the re-com demo (https://github.com/Day8/re-com) is to have ;;; The pattern from the re-com demo (https://github.com/Day8/re-com) is to have
;;; one source file/namespace per view. Each namespace contains a function 'panel' ;;; one source file/namespace per view. Each namespace contains a function 'panel'
;;; whose output is an enlive-style specification of the view to be redered. ;;; whose output is an enlive-style specification of the view to be redered.
;;; I propose to follow this pattern. This file will (eventually) provide the issues view. ;;; I propose to follow this pattern. This file will provide the issues view.
;;; See https://github.com/simon-brooke/youyesyet/blob/master/doc/specification/userspec.md#issues-view ;;; See https://github.com/simon-brooke/youyesyet/blob/master/doc/specification/userspec.md#issues-view

View file

@ -57,7 +57,14 @@
(defn pin-image (defn pin-image
"select the name of a suitable pin image for this address" "select the name of a suitable pin image for this address"
[address] [address]
(let [intentions (set (remove nil? (map #(:intention %) (:electors address))))] (let [intentions
(set
(remove
nil?
(map
#(:intention %)
(map :electors
(:dwellings address)))))]
(case (count intentions) (case (count intentions)
0 "unknown-pin" 0 "unknown-pin"
1 (str (name (first intentions)) "-pin") 1 (str (name (first intentions)) "-pin")
@ -70,7 +77,7 @@
so back links work." so back links work."
[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 "#building/" id)))
;; This way is probably more idiomatic React, but history doesn'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]