Considerable progress on the issue experts workflow, not perfect yet.
This commit is contained in:
parent
3df314ecfc
commit
54ad57349c
|
@ -67,6 +67,13 @@ WHERE canvasser_id = :id
|
|||
ORDER BY date desc
|
||||
LIMIT 1
|
||||
|
||||
--:name get-locality-for-visit :? :1
|
||||
--:doc returns the locality of the address of this visit
|
||||
SELECT addresses.locality
|
||||
FROM addresses, visits
|
||||
WHERE visits.address_id = addresses.id
|
||||
AND visits.id = :id
|
||||
|
||||
-- I don't know why this next one isn't autogenerating, but it isn't and it's critical.
|
||||
|
||||
-- :name list-roles-by-canvasser :? :*
|
||||
|
|
25
resources/sql/youyesyet.postgres.overrides.sql
Normal file
25
resources/sql/youyesyet.postgres.overrides.sql
Normal file
|
@ -0,0 +1,25 @@
|
|||
------------------------------------------------------------------------
|
||||
-- convenience view lv_followupactions of entity followupactions for
|
||||
-- lists, et cetera
|
||||
-- ADL is not yet correctly chaining tables when generating convenience
|
||||
-- views, so the auto-generated convenience view is a horrible
|
||||
-- cross-product join
|
||||
------------------------------------------------------------------------
|
||||
DROP VIEW lv_followupactions;
|
||||
CREATE VIEW lv_followupactions AS
|
||||
SELECT electors.name ||', '|| addresses.address ||', '|| addresses.postcode ||', '|| visits.date ||', '|| issues.id AS request_id_expanded,
|
||||
followupactions.request_id,
|
||||
canvassers.username ||', '|| canvassers.fullname ||', '|| addresses.address ||', '|| addresses.postcode ||', '|| canvassers.phone ||', '|| canvassers.email AS actor_expanded,
|
||||
followupactions.actor,
|
||||
followupactions.date,
|
||||
followupactions.notes,
|
||||
followupactions.closed,
|
||||
followupactions.id
|
||||
FROM followuprequests, visits, canvassers, addresses, followupactions, issues, electors
|
||||
WHERE followupactions.request_id = followuprequests.id
|
||||
AND followuprequests.elector_id = electors.id
|
||||
AND followuprequests.visit_id = visits.id
|
||||
AND followuprequests.issue_id = issues.id
|
||||
AND visits.address_id = addresses.id
|
||||
AND followupactions.actor = canvassers.id
|
||||
;
|
|
@ -13,16 +13,19 @@
|
|||
<form action='{{servlet-context}}/issue-expert/followup-action' method='POST'>
|
||||
{% csrf-field %}
|
||||
<input id='id' name='id' type='hidden' value='{{record.id}}'/>
|
||||
<input id='request_id' name='request_id' type='hidden' value='{{record.id}}'/>
|
||||
<input id='elector_id' name='elector_id' type='hidden' value='{{record.elector_id}}'/>
|
||||
<input id='visit_id' name='visit_id' type='hidden' value='{{record.visit_id}}'/>
|
||||
<p class='widget'>
|
||||
<label for='elector_id'>
|
||||
Elector
|
||||
</label>
|
||||
{% ifmemberof canvassers teamorganisers issueexperts analysts issueeditors admin %}
|
||||
<span id='elector_id' name='elector_id' class='pseudo-widget disabled'>
|
||||
<span id='elector' name='elector' class='pseudo-widget disabled'>
|
||||
{{elector.name}} ({{elector.gender}})
|
||||
</span>
|
||||
{% else %}
|
||||
<span id='elector_id' name='elector_id' class='pseudo-widget not-authorised'>
|
||||
<span id='elector' name='elector' class='pseudo-widget not-authorised'>
|
||||
You are not permitted to view elector of followuprequests
|
||||
</span>
|
||||
{% endifmemberof %}
|
||||
|
@ -121,7 +124,21 @@
|
|||
<input id='closed' name='closed' type='checkbox' maxlength='' size='16'/>
|
||||
{% endifmemberof %}
|
||||
</p>
|
||||
|
||||
<p class='widget'>
|
||||
<label for='intention'>
|
||||
What is the elector's voting intention now?
|
||||
</label>
|
||||
{% ifmemberof admin issueexperts %}
|
||||
<select id='option_id' name='option_id'>
|
||||
<option value="">Not stated</option>
|
||||
{% for option in options %}
|
||||
<img src="{{servlet-context}}/img/option/{{option.id}}-{% ifequal record.option_id option.id %}selected{% else %}unselected{% endifequal %}.png" alt="{{option.id}}"/>
|
||||
<option value='{{option.id}}' {% ifequal record.option_id option.id%}selected='selected'{% endifequal %} style="background-image: url('{{servlet-context}}/img/option/{{option.id}}-{% ifequal record.option_id option.id %}selected{% else %}unselected{% endifequal %}.png')">
|
||||
{{option.id}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endifmemberof %}
|
||||
</p>
|
||||
{% ifmemberof admin issueexperts %}
|
||||
<p class='widget action-safe'>
|
||||
<label for='save-button' class='action-safe'>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[clojure.string :as s]
|
||||
[clojure.tools.logging :as log]
|
||||
[clojure.walk :refer [keywordize-keys]]
|
||||
[java-time :as jt]
|
||||
[markdown.core :refer [md-to-html-string]]
|
||||
[noir.util.route :as route]
|
||||
[ring.util.http-response :as response]
|
||||
|
@ -39,6 +40,11 @@
|
|||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; TODO: Must lock record to expert when taking it from the list, unlock after
|
||||
;;; thirty minutes or when the action is posted, whichever is sooner. If
|
||||
;;; an expert opens a locked record, it must show up as locked. Also, expert should
|
||||
;;; not be able to open a closed request.
|
||||
|
||||
(defn list-page [request]
|
||||
(layout/render
|
||||
"issue-expert/list.html"
|
||||
|
@ -48,10 +54,10 @@
|
|||
:records (db/list-open-requests db/*db* {:expert (:id user)})})))
|
||||
|
||||
|
||||
(defn followup-request-page [request]
|
||||
(defn get-followup-request-page [request]
|
||||
(let
|
||||
[params (support/massage-params request)
|
||||
id (:id (keywordize-keys params))
|
||||
id (:id params)
|
||||
record (db/get-followuprequest db/*db* {:id id})
|
||||
elector (if
|
||||
record
|
||||
|
@ -65,15 +71,11 @@
|
|||
db/*db* {:id (:visit_id record)})))]
|
||||
(layout/render
|
||||
"issue-expert/request.html"
|
||||
{:title (str "Request from " (:name elector) " at " (:date visit))
|
||||
:user (:user (:session request))
|
||||
:visit visit
|
||||
:actions (map
|
||||
{:actions (map
|
||||
;; HTML-ise the notes in each action record
|
||||
#(merge % {:notes (md-to-html-string (:notes %))})
|
||||
(db/list-followupactions-by-followuprequest
|
||||
db/*db* {:id id}))
|
||||
:record record
|
||||
:elector elector
|
||||
:issue (let
|
||||
[raw-issue (if
|
||||
|
@ -82,13 +84,48 @@
|
|||
(if raw-issue
|
||||
(merge
|
||||
raw-issue
|
||||
{:brief (md-to-html-string (:brief raw-issue))})))})))
|
||||
{:brief (md-to-html-string (:brief raw-issue))})))
|
||||
:options (db/list-options db/*db* params)
|
||||
:record record
|
||||
:title (str "Request from " (:name elector) " at " (:date visit))
|
||||
:user (:user (:session request))
|
||||
:visit visit})))
|
||||
|
||||
|
||||
(defn post-followup-action
|
||||
"From this `request`, create a `followupaction` record, and, if an
|
||||
`option_id` is present in the params, an `intention` record; show
|
||||
the request list on success, to the request form on failure."
|
||||
[request]
|
||||
(support/do-or-log-error
|
||||
(let
|
||||
[params (support/massage-params request)
|
||||
locality (:locality (db/get-locality-for-visit db/*db* {:id (:visit_id params)}))]
|
||||
(log/debug "post-followup-request-page with request " request)
|
||||
(db/create-followupaction!
|
||||
db/*db*
|
||||
(assoc
|
||||
params
|
||||
:actor (:id (:user (:session request)))
|
||||
:date (jt/to-sql-timestamp (jt/local-date-time))
|
||||
:closed (= (:closed params) "on")))
|
||||
(if-not
|
||||
(zero? (count (:option_id params)))
|
||||
(if
|
||||
(zero? (count (:signature (db/get-elector db/*db* {:id (:elector_id params)}))))
|
||||
;; the elector has NOT recorded GDPR consent: explicitly bind elector_id to nil
|
||||
(db/create-intention! db/*db* (assoc params :locality locality :elector_id nil))
|
||||
;; else the elector HAS recorded GDPR consent
|
||||
(db/create-intention! db/*db* (assoc params :locality locality))))
|
||||
(list-page request))
|
||||
:error-return
|
||||
(get-followup-request-page request)))
|
||||
|
||||
|
||||
(defroutes issue-expert-routes
|
||||
(GET "/issue-expert/list" request
|
||||
(route/restricted (list-page request)))
|
||||
(GET "/issue-expert/followup-request" request
|
||||
(route/restricted (followup-request-page request)))
|
||||
(POST "/issue-expert/followup-request" request
|
||||
(route/restricted (followup-request-page request))))
|
||||
(route/restricted (get-followup-request-page request)))
|
||||
(POST "/issue-expert/followup-action" request
|
||||
(route/restricted (post-followup-action request))))
|
||||
|
|
Loading…
Reference in a new issue