Tactical commit while I try to understand why the app doesn't rebuild

This commit is contained in:
Simon Brooke 2018-07-02 16:22:38 +01:00
parent f5afa67eed
commit 7aac888912
45 changed files with 283 additions and 1974 deletions

View file

@ -1,4 +1,5 @@
(ns youyesyet.core
(ns ^{:doc "Devalopment launcher, entirely boilerplate from Luminus."}
youyesyet.core
(:require [youyesyet.handler :as handler]
[luminus.repl-server :as repl]
[luminus.http-server :as http]
@ -60,8 +61,8 @@
:else
(start-app args)))
(mount/stop)
(mount/start)
;; (mount/start)
;; (mount/stop)

11
package-lock.json generated Normal file
View file

@ -0,0 +1,11 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"bower": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz",
"integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo="
}
}
}

View file

@ -51,15 +51,16 @@
:main ^:skip-aot 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"]
:plugins [[lein-bower "0.5.1"]
[lein-cljsbuild "1.1.4"]
[lein-codox "0.10.3"]
[lein-uberwar "0.2.0"]
[lein-bower "0.5.1"]
[lein-cprop "1.0.1"]
[lein-less "1.7.5"]
[lein-codox "0.10.3"]]
[lein-npm "0.6.2"]
[lein-uberwar "0.2.0"]
[migratus-lein "0.4.2"]
[org.clojars.punkisdead/lein-cucumber "1.0.5"]
]
:bower-dependencies [[leaflet "0.7.3"]
[jquery "3.3.1"]
@ -73,6 +74,13 @@
:languages [:clojure :clojurescript]
:source-paths ["src/clj" "src/cljc" "src/cljs"]}
:npm {:dependencies [[datatables.net "1.10.19"]
[datatables.net-dt "1.10.19"]
[jquery "3.3.1"]
[leaflet "1.3.1"]
[signature_pad "2.3.2"]]
:root "resources/public/js/lib"}
:uberwar
{:handler youyesyet.handler/app
:init youyesyet.handler/init
@ -80,7 +88,8 @@
:name "youyesyet.war"}
: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]]
:figwheel
{:http-server-root "public"
@ -93,7 +102,8 @@
{:uberjar {:omit-source true
:prep-tasks ["compile" ["cljsbuild" "once" "min"]]
:cljsbuild
{:builds
{:prep-tasks [["npm" "install"]]
:builds
{:min
{:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
:compiler
@ -129,7 +139,8 @@
[lein-figwheel "0.5.9"]
[org.clojure/clojurescript "1.9.495"]]
:cljsbuild
{:builds
{:prep-tasks [["npm" "install"]]
:builds
{:app
{:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
:compiler
@ -140,9 +151,6 @@
:source-map true
:optimizations :none
:pretty-print true}}}}
:doo {:build "test"}
:source-paths ["env/dev/clj"]
:resource-paths ["env/dev/resources"]
@ -151,7 +159,8 @@
(pjstadig.humane-test-output/activate!)]}
:project/test {:resource-paths ["env/test/resources"]
:cljsbuild
{:builds
{:prep-tasks [["npm" "install"]]
:builds
{:test
{:source-paths ["src/cljc" "src/cljs" "test/cljs"]
:compiler

View file

@ -1,50 +0,0 @@
--------------------------------------------------------------------------------
----
---- 20161014170335-basic-setup.down.sql: database schema for youyesyet.
----
---- 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
----
--------------------------------------------------------------------------------
-- intended to reverse out the database changes made in
-- 20161014170335-basic-setup.up.sql
drop table addresses cascade;
--;;
drop table authorities cascade;
--;;
drop table canvassers cascade;
--;;
drop table districts cascade;
--;;
drop table electors cascade;
--;;
drop table followupactions cascade;
--;;
drop table followupmethods cascade;
--;;
drop table followuprequests cascade;
--;;
drop table issueexpertise cascade;
--;;
drop table issues cascade;
--;;
drop table options cascade;
--;;
drop table visits cascade;
--;;

View file

@ -1,669 +0,0 @@
--------------------------------------------------------------------------------
----
---- 20161014170335-basic-setup.up.sql: database schema for youyesyet.
----
---- 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
----
--------------------------------------------------------------------------------
----
---- NOTE
---- This file is essentially a Postgres schema dump of a database schema which was
---- created with the function initdb! in the file src/clj/youyesyet/db/schema.clj.
---- This file has then been mildly massaged to work with Migratus.
---- Either this file or src/clj/youyesyet/db/schema.clj is redundant; schema.clj
---- represents the older, Korma, way of doing things but does not readily allow
---- for migrations; this file represents the newer Migratus/HugSQL way. I'm not
---- certain which of these paths I'm going to go down.
----
--------------------------------------------------------------------------------
SET statement_timeout = 0;
--;;
SET lock_timeout = 0;
--;;
SET client_encoding = 'UTF8';
--;;
SET standard_conforming_strings = on;
--;;
SET check_function_bodies = false;
--;;
SET client_min_messages = warning;
--;;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
--
-- CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--;;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--
-- COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
--;;
SET search_path = public, pg_catalog;
--;;
SET default_tablespace = '';
--;;
SET default_with_oids = false;
--;;
--
-- Name: addresses; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS addresses (
id integer NOT NULL,
address character varying(256) NOT NULL,
postcode character varying(16),
phone character varying(16),
district_id integer,
latitude real,
longitude real
);
--;;
ALTER TABLE public.addresses OWNER TO youyesyet;
--;;
--
-- Name: addresses_id_seq; Type: SEQUENCE; Schema: public; Owner: youyesyet
--
CREATE SEQUENCE addresses_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--;;
ALTER TABLE public.addresses_id_seq OWNER TO youyesyet;
--;;
--
-- Name: addresses_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: youyesyet
--
ALTER SEQUENCE addresses_id_seq OWNED BY addresses.id;
--;;
--
-- Name: authorities; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS authorities (
id character varying(32) NOT NULL
);
--;;
ALTER TABLE public.authorities OWNER TO youyesyet;
--;;
--
-- Name: canvassers; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS canvassers (
id serial,
username character varying(32) NOT NULL,
fullname character varying(64) NOT NULL,
elector_id integer,
address_id integer NOT NULL,
phone character varying(16),
email character varying(128),
authority_id character varying(32) NOT NULL,
introduced_by int references canvassers(id),
authorised boolean
);
--;;
ALTER TABLE public.canvassers OWNER TO youyesyet;
--;;
--
-- Name: districts; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS districts (
id integer NOT NULL,
name character varying(64) NOT NULL
);
--;;
ALTER TABLE public.districts OWNER TO youyesyet;
--;;
--
-- Name: electors; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS electors (
id integer NOT NULL,
name character varying(64) NOT NULL,
address_id integer NOT NULL,
phone character varying(16),
email character varying(128)
);
--;;
ALTER TABLE public.electors OWNER TO youyesyet;
--;;
--
-- Name: followupactions; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS followupactions (
id integer NOT NULL,
request_id integer NOT NULL,
actor integer NOT NULL,
date timestamp with time zone DEFAULT now() NOT NULL,
notes text,
closed boolean
);
--;;
ALTER TABLE public.followupactions OWNER TO youyesyet;
--
-- Name: followupactions_id_seq; Type: SEQUENCE; Schema: public; Owner: youyesyet
--
CREATE SEQUENCE followupactions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--;;
ALTER TABLE public.followupactions_id_seq OWNER TO youyesyet;
--;;
--
-- Name: followupactions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: youyesyet
--
ALTER SEQUENCE followupactions_id_seq OWNED BY followupactions.id;
--;;
--
-- Name: followupmethods; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS followupmethods (
id character varying(32) NOT NULL
);
--;;
ALTER TABLE public.followupmethods OWNER TO youyesyet;
--;;
--
-- Name: followuprequests; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
insert into followupmethods values ('Telephone');
--;;
insert into followupmethods values ('eMail');
--;;
insert into followupmethods values ('Post');
--;;
CREATE TABLE IF NOT EXISTS followuprequests (
id integer NOT NULL,
elector_id integer NOT NULL,
visit_id integer NOT NULL,
issue_id character varying(32) NOT NULL,
method_id character varying(32) NOT NULL
);
--;;
ALTER TABLE public.followuprequests OWNER TO youyesyet;
--;;
--
-- Name: followuprequests_id_seq; Type: SEQUENCE; Schema: public; Owner: youyesyet
--
CREATE SEQUENCE followuprequests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--;;
ALTER TABLE public.followuprequests_id_seq OWNER TO youyesyet;
--;;
--
-- Name: followuprequests_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: youyesyet
--
ALTER SEQUENCE followuprequests_id_seq OWNED BY followuprequests.id;
--;;
--
-- Name: issueexpertise; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS issueexpertise (
canvasser_id integer NOT NULL,
issue_id character varying(32) NOT NULL,
method_id character varying(32) NOT NULL
);
--;;
ALTER TABLE public.issueexpertise OWNER TO youyesyet;
--;;
--
-- Name: issues; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS issues (
id character varying(32) NOT NULL,
url character varying(256)
);
--;;
ALTER TABLE public.issues OWNER TO youyesyet;
--;;
--
-- Name: options; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS options (
id character varying(32) NOT NULL
);
--;;
ALTER TABLE public.options OWNER TO youyesyet;
--;;
--
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS schema_migrations (
id bigint NOT NULL
);
--;;
ALTER TABLE public.schema_migrations OWNER TO youyesyet;
--;;
--
-- Name: visits; Type: TABLE; Schema: public; Owner: youyesyet; Tablespace:
--
CREATE TABLE IF NOT EXISTS visits (
id integer NOT NULL,
address_id integer NOT NULL,
canvasser_id integer NOT NULL,
date timestamp with time zone DEFAULT now() NOT NULL
);
--;;
ALTER TABLE public.visits OWNER TO youyesyet;
--;;
--
-- Name: visits_id_seq; Type: SEQUENCE; Schema: public; Owner: youyesyet
--
CREATE SEQUENCE visits_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--;;
ALTER TABLE public.visits_id_seq OWNER TO youyesyet;
--;;
--
-- Name: visits_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: youyesyet
--
ALTER SEQUENCE visits_id_seq OWNED BY visits.id;
--;;
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY addresses ALTER COLUMN id SET DEFAULT nextval('addresses_id_seq'::regclass);
--;;
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followupactions ALTER COLUMN id SET DEFAULT nextval('followupactions_id_seq'::regclass);
--;;
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followuprequests ALTER COLUMN id SET DEFAULT nextval('followuprequests_id_seq'::regclass);
--;;
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY visits ALTER COLUMN id SET DEFAULT nextval('visits_id_seq'::regclass);
--;;
--
-- Name: addresses_address_key; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY addresses
ADD CONSTRAINT addresses_address_key UNIQUE (address);
--;;
--
-- Name: addresses_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY addresses
ADD CONSTRAINT addresses_pkey PRIMARY KEY (id);
--;;
--
-- Name: authorities_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY authorities
ADD CONSTRAINT authorities_pkey PRIMARY KEY (id);
--;;
--
-- Name: canvassers_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY canvassers
ADD CONSTRAINT canvassers_pkey PRIMARY KEY (id);
--;;
--
-- Name: districts_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY districts
ADD CONSTRAINT districts_pkey PRIMARY KEY (id);
--;;
--
-- Name: electors_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY electors
ADD CONSTRAINT electors_pkey PRIMARY KEY (id);
--;;
--
-- Name: followupactions_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY followupactions
ADD CONSTRAINT followupactions_pkey PRIMARY KEY (id);
--;;
--
-- Name: followupmethods_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY followupmethods
ADD CONSTRAINT followupmethods_pkey PRIMARY KEY (id);
--;;
--
-- Name: followuprequests_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY followuprequests
ADD CONSTRAINT followuprequests_pkey PRIMARY KEY (id);
--;;
--
-- Name: issues_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY issues
ADD CONSTRAINT issues_pkey PRIMARY KEY (id);
--;;
--
-- Name: options_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY options
ADD CONSTRAINT options_pkey PRIMARY KEY (id);
--;;
--
-- Name: schema_migrations_id_key; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
--ALTER TABLE ONLY schema_migrations
-- ADD CONSTRAINT schema_migrations_id_key UNIQUE (id);
--;;
--
-- Name: visits_pkey; Type: CONSTRAINT; Schema: public; Owner: youyesyet; Tablespace:
--
ALTER TABLE ONLY visits
ADD CONSTRAINT visits_pkey PRIMARY KEY (id);
--;;
--
-- Name: addresses_district_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY addresses
ADD CONSTRAINT addresses_district_id_fkey FOREIGN KEY (district_id) REFERENCES districts(id);
--;;
--
-- Name: canvassers_address_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY canvassers
ADD CONSTRAINT canvassers_address_id_fkey FOREIGN KEY (address_id) REFERENCES addresses(id);
--;;
--
-- Name: canvassers_authority_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY canvassers
ADD CONSTRAINT canvassers_authority_id_fkey FOREIGN KEY (authority_id) REFERENCES authorities(id);
--;;
--
-- Name: canvassers_elector_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY canvassers
ADD CONSTRAINT canvassers_elector_id_fkey FOREIGN KEY (elector_id) REFERENCES electors(id);
--;;
create unique index canvassers_username_ix on canvassers (username);
create unique index canvassers_email_ix on canvassers(email);
--
-- Name: electors_address_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY electors
ADD CONSTRAINT electors_address_id_fkey FOREIGN KEY (address_id) REFERENCES addresses(id);
--;;
--
-- Name: followupactions_actor_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followupactions
ADD CONSTRAINT followupactions_actor_fkey FOREIGN KEY (actor) REFERENCES canvassers(id);
--;;
--
-- Name: followupactions_request_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followupactions
ADD CONSTRAINT followupactions_request_id_fkey FOREIGN KEY (request_id) REFERENCES followuprequests(id);
--;;
--
-- Name: followuprequests_elector_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followuprequests
ADD CONSTRAINT followuprequests_elector_id_fkey FOREIGN KEY (elector_id) REFERENCES electors(id);
--;;
--
-- Name: followuprequests_issue_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followuprequests
ADD CONSTRAINT followuprequests_issue_id_fkey FOREIGN KEY (issue_id) REFERENCES issues(id);
--;;
--
-- Name: followuprequests_method_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followuprequests
ADD CONSTRAINT followuprequests_method_id_fkey FOREIGN KEY (method_id) REFERENCES followupmethods(id);
--;;
--
-- Name: followuprequests_visit_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY followuprequests
ADD CONSTRAINT followuprequests_visit_id_fkey FOREIGN KEY (visit_id) REFERENCES visits(id);
--;;
--
-- Name: issueexpertise_canvasser_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY issueexpertise
ADD CONSTRAINT issueexpertise_canvasser_id_fkey FOREIGN KEY (canvasser_id) REFERENCES canvassers(id);
--;;
--
-- Name: issueexpertise_issue_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY issueexpertise
ADD CONSTRAINT issueexpertise_issue_id_fkey FOREIGN KEY (issue_id) REFERENCES issues(id);
--;;
--
-- Name: issueexpertise_method_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY issueexpertise
ADD CONSTRAINT issueexpertise_method_id_fkey FOREIGN KEY (method_id) REFERENCES followupmethods(id);
--;;
--
-- Name: visits_address_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY visits
ADD CONSTRAINT visits_address_id_fkey FOREIGN KEY (address_id) REFERENCES addresses(id);
--;;
--
-- Name: visits_canvasser_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: youyesyet
--
ALTER TABLE ONLY visits
ADD CONSTRAINT visits_canvasser_id_fkey FOREIGN KEY (canvasser_id) REFERENCES canvassers(id);
--;;
--
-- Name: public; Type: ACL; Schema: -; Owner: postgres
--
REVOKE ALL ON SCHEMA public FROM PUBLIC;
--;;
REVOKE ALL ON SCHEMA public FROM postgres;
--;;
GRANT ALL ON SCHEMA public TO postgres;
--;;
GRANT ALL ON SCHEMA public TO PUBLIC;
--;;
--
-- PostgreSQL database dump complete
--

View file

@ -1,13 +0,0 @@
drop table teammemberships;
drop table teamorganiserships;
drop index ix_teams_name;
drop table teams;
drop table rolememberships;
drop index ix_roles_name;
drop table roles;

View file

@ -1,39 +0,0 @@
create table if not exists roles (
id serial primary key,
name varchar(64) not null
);
create unique index ix_roles_name on roles(name);
create table if not exists rolememberships (
role_id integer not null references roles(id),
canvasser_id integer not null references canvassers(id)
);
create table if not exists teams (
id serial primary key,
name varchar(64) not null,
district_id integer not null references districts(id),
latitude real,
longitude real
);
create unique index ix_teams_name on teams(name);
create table if not exists teammemberships (
team_id integer not null references teams(id),
canvasser_id integer not null references canvassers(id)
);
create table if not exists teamorganiserships (
team_id integer not null references teams(id),
canvasser_id integer not null references canvassers(id)
);
alter table roles owner to youyesyet;
alter table rolememberships owner to youyesyet;
alter table teams owner to youyesyet;
alter table teammemberships owner to youyesyet;

View file

@ -1,17 +0,0 @@
-- this is just a teardown of everything set up in the corresponding .up.sql file
delete from roles where name = 'Expert';
delete from roles where name = 'Administrator';
delete from roles where name = 'Recruiter';
delete from roles where name = 'Organiser';
delete from roles where name = 'Editor';
alter table issues drop column content;
alter table issues drop column current;
delete from issues where id = 'Currency';
delete from issues where id = 'Monarchy';
delete from issues where id = 'Defence';
delete from options where id = 'Yes';
delete from options where id = 'No';

View file

@ -1,58 +0,0 @@
-- We don't explicitly instantiate the 'Canvasser' role since every user is
-- deemed to be a canvasser.
-- an 'Expert' is someone with expertise in one or more issues, who is
-- trusted to discuss those issues in detail with electors.
insert into roles (name) values ('Expert');
-- an 'Administrator' is someone entitled to broadly alter reference data
-- throughout the system.
insert into roles (name) values ('Administrator');
-- a 'Recruiter' is someone entitled to invite other people to become users
-- ('Canvassers'). A Recruiter is entitled to lock the account of anyone they
-- have recruited, recursively.
insert into roles (name) values ('Recruiter');
-- an 'Organiser' is someone who organises one or more local teams. An Organiser
-- is entitled to exclude any Canvasser from any team they organise.
insert into roles (name) values ('Organiser');
-- an 'Editor' is someone entitled to add and edit issues.
insert into roles (name) values ('Editor');
-- issue text is local; there may still in addition be a further link to more
-- information, but the basic issue text should be part of the issue record.
-- The text should fit on a phone screen without scrolling, so is reasonably
-- short.
alter table issues add column content varchar(1024);
-- an issue may be current or not current; when not current it is not deleted
-- from the system but kept because it may become current again later. Only
-- current issues are shown in the app. Typically not fewer than three and not
-- more than about seven issues should be current at any time.
alter table issues add column current boolean default false;
insert into issues (id, content, current) values ('Currency',
'Scotland could keep the Pound, or use the Euro. But we could also set up a new currency of our own.',
true);
insert into issues (id, content, current) values ('Monarchy',
'Scotland could keep the Queen. This is an issue to be decided after independence.',
true);
insert into issues (id, content, current) values ('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.',
true);
insert into options (id) values ('Yes');
insert into options (id) values ('No');

View file

@ -1,11 +0,0 @@
drop view if exists roles_by_canvasser;
drop view if exists teams_by_canvasser;
drop view if exists canvassers_by_team;
drop view if exists canvassers_by_introducer;
drop view if exists teams_by_organiser;
drop view if exists organisers_by_team;

View file

@ -1,59 +0,0 @@
create view roles_by_canvasser as
select canvassers.id as canvasser, roles.name
from roles, rolememberships, canvassers
where roles.id = rolememberships.role_id
and canvassers.id = rolememberships.canvasser_id
and canvassers.authorised = true;
create view teams_by_canvasser as
select canvassers.id as canvasser, teams.id, teams.name, teams.latitude, teams.longitude
from teams, teammemberships, canvassers
where teams.id = teammemberships.team_id
and canvassers.id = teammemberships.canvasser_id;
create view canvassers_by_team as
select teams.id as team,
canvassers.id,
canvassers.username,
canvassers.fullname,
canvassers.email,
canvassers.phone
from teams, teammemberships, canvassers
where teams.id = teammemberships.team_id
and canvassers.id = teammemberships.canvasser_id
and canvassers.authorised = true;
create view canvassers_by_introducer as
select introducers.id as introducer,
canvassers.id as canvasser,
canvassers.username,
canvassers.fullname,
canvassers.email,
canvassers.phone,
canvassers.authorised
from canvassers, canvassers as introducers
where introducers.id = canvassers.introduced_by;
create view teams_by_organiser as
select canvassers.id as organiser,
teams.id,
teams.name,
teams.latitude,
teams.longitude
from teams, teamorganiserships, canvassers
where teams.id = teamorganiserships.team_id
and canvassers.id = teamorganiserships.canvasser_id
and canvassers.authorised = true;
create view organisers_by_team as
select teams.id as team,
canvassers.id,
canvassers.username,
canvassers.fullname,
canvassers.email,
canvassers.phone
from teams, teamorganiserships, canvassers
where teams.id = teamorganiserships.team_id
and canvassers.id = teamorganiserships.canvasser_id
and canvassers.authorised = true;

View file

@ -1,69 +0,0 @@
--------------------------------------------------------------------------------
----
---- 20170721084900.up.sql: add dwellings table, to deal with flatted 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) 2017 Simon Brooke for Radical Independence Campaign
----
--------------------------------------------------------------------------------
----
---- NOTE
---- This file is essentially a Postgres schema dump of a database schema which was
---- created with the function initdb! in the file src/clj/youyesyet/db/schema.clj.
---- This file has then been mildly massaged to work with Migratus.
---- Either this file or src/clj/youyesyet/db/schema.clj is redundant; schema.clj
---- represents the older, Korma, way of doing things but does not readily allow
---- for migrations; this file represents the newer Migratus/HugSQL way. I'm not
---- certain which of these paths I'm going to go down.
----
--------------------------------------------------------------------------------
alter table canvassers add column address_id integer references addresses(id);
--;;
alter table electors add column address_id integer references addresses(id);
--;;
alter table visits add column address_id integer references addresses(id);
--;;
update canvassers set address_id =
(select address_id from dwellings where id = canvassers.dwelling_id);
--;;
update electors set address_id =
(select address_id from dwellings where id = electors.dwelling_id);
--;;
update visits set address_id =
(select address_id from dwellings where id = visits.dwelling_id);
--;;
alter table canvassers alter column address_id set not null;
--;;
alter table electors alter column address_id set not null;
--;;
alter table visits alter column address_id set not null;
--;;
alter table canvassers drop column dwelling_id;
--;;
alter table electors drop column dwelling_id;
--;;
alter table visits drop column dwelling_id;
--;;
drop table if exists dwellings;
--;;

View file

@ -1,87 +0,0 @@
--------------------------------------------------------------------------------
----
---- 20170721084900.up.sql: add dwellings table, to deal with flatted 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) 2017 Simon Brooke for Radical Independence Campaign
----
--------------------------------------------------------------------------------
----
---- NOTE
---- This file is essentially a Postgres schema dump of a database schema which was
---- created with the function initdb! in the file src/clj/youyesyet/db/schema.clj.
---- This file has then been mildly massaged to work with Migratus.
---- Either this file or src/clj/youyesyet/db/schema.clj is redundant; schema.clj
---- represents the older, Korma, way of doing things but does not readily allow
---- for migrations; this file represents the newer Migratus/HugSQL way. I'm not
---- certain which of these paths I'm going to go down.
----
--------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS dwellings (
id serial NOT NULL primary key,
address_id integer NOT NULL references addresses(id),
sub_address varchar(16)
);
--;;
ALTER TABLE public.dwellings OWNER TO youyesyet;
--;;
INSERT INTO dwellings (address_id, sub_address)
SELECT DISTINCT id, '' FROM addresses;
--;;
alter table canvassers add column dwelling_id integer references dwellings(id);
--;;
alter table electors add column dwelling_id integer references dwellings(id);
--;;
alter table visits add column dwelling_id integer references dwellings(id);
--;;
update canvassers set dwelling_id =
(select id from dwellings where address_id = canvassers.address_id);
--;;
update electors set dwelling_id =
(select id from dwellings where address_id = electors.address_id);
--;;
update visits set dwelling_id =
(select id from dwellings where address_id = visits.address_id);
--;;
alter table canvassers alter column dwelling_id set not null;
--;;
alter table electors alter column dwelling_id set not null;
--;;
alter table visits alter column dwelling_id set not null;
--;;
alter table canvassers drop constraint canvassers_address_id_fkey;
--;;
alter table electors drop constraint electors_address_id_fkey;
--;;
alter table visits drop constraint visits_address_id_fkey;
--;;
alter table canvassers drop column address_id;
--;;
alter table electors drop column address_id;
--;;
alter table visits drop column address_id;
--;;

View file

@ -1,24 +0,0 @@
--------------------------------------------------------------------------------
----
---- 20180316110100intentions-and-options.down.sql: remove intentions and options
----
---- 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
----
--------------------------------------------------------------------------------
drop table intentions;

View file

@ -1,30 +0,0 @@
--------------------------------------------------------------------------------
----
---- 20180316110100intentions-and-options.up.sql: add intentions and options
----
---- 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
----
--------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS intentions (
visit_id int not null references visits(id) on delete no action,
elector_id int not null references electors(id) on delete no action,
option_id varchar(32) not null references options(id) on delete no action
);
ALTER TABLE intentions owner to youyesyet;

View file

@ -1,3 +0,0 @@
alter table electors drop column gender;
drop table genders;

View file

@ -1,11 +0,0 @@
create table genders (
id varchar(32) not null primary key
);
-- genders is reference data
insert into genders values ('Female');
insert into genders values ('Male');
insert into genders values ('Non-binary');
insert into genders values ('Unknown');
alter table electors add column gender varchar(32) references genders(id) default 'Unknown';

View file

@ -1,10 +0,0 @@
delete from options where id = 'Yes';
delete from options where id = 'No';
delete from issues where id = 'Currency';
delete from issues where id = 'Monarchy';
delete from issues where id = 'Defence';

View file

@ -1,18 +0,0 @@
insert into options values ('Yes');
insert into options values ('No');
insert into issues (id, url) values ('Currency', 'https://www.yyy.scot/wiki/issues/Currency');
insert into issues (id, url) values ('Monarchy', 'https://www.yyy.scot/wiki/issues/Monarchy');
insert into issues (id, url) values ('Defence', 'https://www.yyy.scot/wiki/issues/Defence');
insert into genders (id ) values ('Female');
insert into genders (id ) values ('Male');
insert into genders (id ) values ('Non-binary');
insert into genders (id ) values ('Unknown');

View file

@ -1,3 +0,0 @@
delete from addresses where id < = 4;
delete from electors where id <= 10;

View file

@ -1,41 +0,0 @@
insert into addresses (id, address, postcode, latitude, longitude)
values (1, '13 Imaginary Terrace, IM1 3TE', 'IM1 3TE', 55.8253043, -4.2569057);
insert into addresses (id, address, postcode, latitude, longitude)
values (2, '15 Imaginary Terrace, IM1 3TE', 'IM1 3TE', 55.8252354, -4.2572778);
insert into addresses (id, address, postcode, latitude, longitude)
values (3, '17 Imaginary Terrace, IM1 3TE', 'IM1 3TE', 55.825166, -4.257026);
insert into addresses (id, address, postcode, latitude, longitude)
values (4, '19 Imaginary Terrace, IM1 3TE', 'IM1 3TE', 55.8250695, -4.2570239);
insert into electors (id, name, address_id, gender)
values (1, 'Alan Anderson', 1, 'Male');
insert into electors (id, name, address_id, gender)
values (2, 'Ann Anderson', 1, 'Female');
insert into electors (id, name, address_id, gender)
values (3, 'Alex Anderson', 1, 'Non-binary');
insert into electors (id, name, address_id)
values (4, 'Andy Anderson', 1);
insert into electors (id, name, address_id, gender)
values (5, 'Beryl Brown', 2, 'Female');
insert into electors (id, name, address_id, gender)
values (6, 'Betty Black', 2, 'Female');
insert into electors (id, name, address_id, gender)
values (7, 'Catriona Crathie', 3, 'Female');
insert into electors (id, name, address_id, gender)
values (8, 'Colin Caruthers', 3, 'Male');
insert into electors (id, name, address_id, gender)
values (9, 'Calum Crathie', 3, 'Unknown');
insert into electors (id, name, address_id, gender)
values (10, 'David Dewar', 4, 'Male');

View file

@ -1 +0,0 @@
alter table issues drop column current;

View file

@ -1,2 +0,0 @@
alter table issues add column current boolean default true;

View file

@ -1,8 +0,0 @@
alter table electors
add column address_id references addresses on delete no action;
update electors
set address_id =
(select address_id
from dwellings
where dwellings.id electors.dwelling_id);

View file

@ -1,11 +0,0 @@
CREATE TABLE dwellings
(
id INT NOT NULL PRIMARY KEY,
address_id INT NOT NULL references addresses on delete no action,
sub_address VARCHAR( 32)
);
alter table electors
add column dwelling_id int references dwellings on delete no action;
alter table electors drop column address_id;

View file

@ -1,15 +0,0 @@
-- enough data to get the system working and real logins
insert into addresses (address, postcode, latitude, longitude)
values ('West Croft, Standingstone, Auchencairn', 'DG7 1RF', 54.822389, -3.920265);
insert into dwellings (id, address_id, sub_address)
values (5, 5, '');
insert into electors (name, dwelling_id, gender)
values ('Simon Brooke', 1, 'Male');
insert into authorities (id) values ('GitHub');
insert into canvassers (username, fullname, elector_id, address_id, authority_id, authorised)
values ('simon_brooke', 'Simon Brooke', 2, 2, 'GitHub', true);

View file

@ -23,13 +23,22 @@
</p>
</div>
{% endblock %}
{% block extra-script %}
var user = {
"username": "{{user.username}}",
"fullname": "{{user.fullname}}",
"id": {{user.id|default:-1}},
"authorised": {{user.authorised|default:false}}
};
{% endblock %}
{% block extra-tail %}
<!-- scripts and styles -->
<!-- ATTENTION \/ -->
<!-- ATTENTION /\ -->
<!-- Leaflet -->
<link rel="stylesheet" href="js/lib/leaflet/dist/leaflet.css" />
{% script "js/lib/leaflet/dist/leaflet.js" %}
<link rel="stylesheet" href="js/lib/node_modules/leaflet/dist/leaflet.css" />
{% script "js/lib/node_modules/signature_pad/dist/signature_pad.min.js" %}
{% script "js/lib/node_modules/leaflet/dist/leaflet.js" %}
{% script "/js/app.js" %}
{% endblock %}

View file

@ -10,7 +10,6 @@
<link rel="stylesheet" type="text/css" href="css/spinner.css" />
<link href="https://fonts.googleapis.com/css?family=Archivo+Black|Archivo+Narrow" rel="stylesheet"/>
<title>{{site-title}}: {{title}}</title>
{% script "js/lib/jquery/dist/jquery.min.js" %}
{% endblock %}
{% block extra-head %}
<!-- extra-head: put any additional markup to go into the head of your document into this block -->
@ -76,10 +75,6 @@
</footer>
{% endblock %}
{% endblock %}
{% block extra-tail %}
<!-- extra-tail: put markup here which needs to be at the very end of the body -->
<!-- e.g. some javascript script tags, some link tags -->
{% endblock %}
<script type="text/javascript">
var context = "{{servlet-context}}";
var csrfToken = "{{csrf-token}}";
@ -87,6 +82,10 @@
/* extra-script: put any actual javascript source text you need into this block */
{% endblock %}
</script>
{% block extra-tail %}
<!-- extra-tail: put markup here which needs to be at the very end of the body -->
<!-- e.g. some javascript script tags, some link tags -->
{% endblock %}
</body>
</html>

View file

@ -1,60 +0,0 @@
{% extends "base.html" %}
{% block title %}
{% endblock %}
{% block content %}
<form action="edit-canvasser" method="post">
{% if canvasser %}
<input type="hidden" name="id" id="id" value="{{canvasser.id}}"/>
{% endif %}
<p class="widget">
<label for="fullname">Full name</label>
<input type="text" name="fullname" id="fullname" value="{{canvasser.fullname}}"/>
</p>
<p class="widget">
(TODO: Not absolutely sure what I'm going to do for an elector id widget yet.)
</p>
<p class="widget">
<label for="address">Address</label>
{% if address.id %}
<!-- if we already have an address, just show it with a link to edit it -->
<span class="pseudo-widget" id="address">
{{address.address}}
</span>
{% else %}
(TODO: Some sort of address lookup widget goes here.)
{% endif %}
</p>
<p class="widget">
<label for="phone">Phone number</label>
<input type="tel" name="phone" id="phone" value="{{canvasser.phone}}"/>
</p>
<p class="widget">
<label for="email">Email address</label>
<input type="email" name="email" id="email" value="{{canvasser.email}}"/>
</p>
<p class="widget">
<label for="authority_id">Authorised by</label>
<select name="authority_id" id="authority_id">
{% for authority in authorities %}
<option value="{{authority.id}}"
{% ifequal authority.id canvasser.authority_id %}selected {% endifequal %}>
{{authority.id}}
</option>
</select>
</p>
</p>
id serial,
username character varying(32) NOT NULL,
fullname character varying(64) NOT NULL,
elector_id integer,
address_id integer NOT NULL,
phone character varying(16),
email character varying(128),
authority_id character varying(32) NOT NULL,
introduced_by int references canvassers(id),
authorised boolean
</form>
{% endblock %}

View file

@ -1,484 +0,0 @@
(ns ^{:doc "Korma-flavour database setup, now obsolete but retained for documentation."
:author "Simon Brooke"} youyesyet.db.schema
(:require [clojure.java.jdbc :as sql]
[korma.core :as kc]
[youyesyet.db.core :as yyydb]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.db.schema: database schema for youyesyet.
;;;;
;;;; 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
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Note that this is the (old) Korma way of doing things;
;;; it may not play well with migrations, nor with the HugSQL way of doing things recommended
;;; in Web Development with Clojure, Second Ed. So this may be temporary 'get us started' code,
;;; which later gets thrown away. The 'create-x-table!' functions in this file may be
;;; redundant, and if they are the namespace probably needs to be renamed to 'entities'.
;;; See also resources/migrations/20161014170335-basic-setup.up.sql
(defn create-districts-table!
"Create a table to hold the electoral districts in which electors are registered.
Note that, as this app is being developed for the independence referendum in which
polling is across the whole of Scotland, this part of the design isn't fully thought
through; if later adapted to general or local elections, some breakdown or hierarchy
of polling districts into constituencies will be required."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:districts
;; it may be necessary to have a serial abstract primary key but I suspect
;; polling districts already have numbers assigned by the Electoral Commission and
;; it would be sensible to use those. TODO: check.
[:id "integer not null primary key"]
[:name "varchar(64) not null"]
;; TODO: it would make sense to hold polygon data for polling districts so we can reflect
;; them on the map, but I haven't thought through how to do that yet.
)))
(kc/defentity district
(kc/pk :id)
(kc/table :districts)
(kc/database yyydb/*db*)
(kc/entity-fields :id :name))
(defn create-addresses-table!
"Create a table to hold the addresses at which electors are registered."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:addresses
[:id "serial not null primary key"]
;; we do NOT want to hold multiple address records for the same household. When we receive
;; the electoral roll data the addresses are likely to be text fields inlined in the elector
;; record; in digesting the roll data we need to split these out and resolve them against existing
;; addresses in the table, creating a new address record only if there's no match.
[:address "varchar(256) not null unique"]
[:postcode "varchar(16)"]
[:phone "varchar(16)"]
;; the electoral district within which this address exists
[:district_id "integer references districts(id)"]
[:latitude :real]
[:longitude :real])))
(kc/defentity address
(kc/pk :id)
(kc/table :addresses)
(kc/database yyydb/*db*)
(kc/entity-fields :id :address :postcode :phone :latitude :longitude)
(kc/has-one district))
(defn create-authorities-table!
"Create a table to hold the oauth authorities against which we with authenticate canvassers."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:authorities
[:id "varchar(32) not null primary key"]
;; more stuff here when I understand more
)))
(kc/defentity authority
(kc/pk :id)
(kc/table :authorities)
(kc/database yyydb/*db*)
(kc/entity-fields :id))
(defn create-electors-table!
"Create a table to hold electors data."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:electors
;; id should be the roll number on the electoral roll, I think, but only if this is unique
;; across Scotland. Otherwise we need a separate id field. TODO: check.
[:id "integer primary key"]
[:name "varchar(64) not null"]
[:address_id "integer not null references addresses(id)" ]
[:phone "varchar(16)"]
;; we'll probably only capture email data on electors if they request a followup
;; on a particular issue by email.
[:email "varchar(128)"])))
(kc/defentity elector
(kc/pk :id)
(kc/table :electors)
(kc/database yyydb/*db*)
(kc/entity-fields :id :name :phone :email)
(kc/has-one address))
;;; Lifecycle of the canvasser record goes like this, I think:
;;; A canvasser record is created when an existing canvasser issues an invitation to a friend.
;;; The invitation takes the form of an automatically generated email with a magic token in it.
;;; At this point the record has only an email address, the introduced_by and the magic token,
;;; which is itself probably a hash of the email address. Therefore, having the username as the
;;; primary key won't work.
;;;
;;; The invited person clicks on the link in the email and completes the sign-up form, adding
;;; their full name, and their phone number. If the username they have chosen is unique, they
;;; are then sent a second email with a new magic token, possibly a hash of email address +
;;; full name. When they click on the link in this second email, their 'authorised' flag is
;;; set to 'true'.
;;;
;;; Administrators can also create canvasser records directly.aw
;;; TODO: Do we actually need a username at all? Wouldn't the email address do?
(defn create-canvassers-table!
"Create a table to hold data on canvassers (including authentication data)."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:canvassers
;; id is the username the canvasser logs in as.
[:id "serial primary key"]
[:username "varchar(32) unique"]
[:fullname "varchar(64) not null"]
;; most canvassers will be electors, we should link them:
[:elector_id "integer references electors(id) on delete no action"]
;; but some canvassers may not be electors, so we need contact details separately:
[:address_id "integer not null references addresses(id)" ]
[:phone "varchar(16)"]
[:email "varchar(128)"]
;; with which authority do we authenticate this canvasser? I do not want to hold even
;; encrypted passwords locally
[:authority_id "varchar(32) not null references authorities(id) on delete no action"]
[:introduced_by "integer references canvassers(id)"]
[:is_admin :boolean]
;; true if the canvasser is authorised to use the app; else false. This allows us to
;; block canvassers we suspect of misbehaving.
[:authorised :boolean])))
(kc/defentity canvasser
(kc/pk :id)
(kc/table :canvassers)
(kc/database yyydb/*db*)
(kc/entity-fields :id :fullname :phone :email :is_admin :authorised)
(kc/has-one elector)
(kc/has-one address)
;; (kc/has-one canvasser {:fk :introduced_by})
(kc/has-one authority))
(defn create-visits-table!
"Create a table to record visits by canvassers to addresses (including virtual visits by telephone)."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:visits
[:id "serial not null primary key"]
[:address_id "integer not null references addresses(id)"]
[:canvasser_id "integer not null references canvassers(id)"]
[:date "timestamp with time zone not null default now()"])))
(kc/defentity visit
(kc/pk :id)
(kc/table :visits)
(kc/database yyydb/*db*)
(kc/entity-fields :id :date)
(kc/has-one address)
(kc/has-one canvasser))
(defn create-options-table!
"Create a table to record options in the vote. This app is being created for the Independence
referendum, which will have just two options, 'Yes' and 'No', but it might later be adapted
for more general political canvassing."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:options
;; id is also the text of the option; e.g. 'Yes', 'No'.
[:id "varchar(32) not null primary key"]
;; To do elections you probably need party and candidate and stuff here, but
;; for the referendum it's unnecessary.
)))
(kc/defentity option
(kc/pk :id)
(kc/table :options)
(kc/database yyydb/*db*)
(kc/entity-fields :id))
(defn create-option-district-table!
"Create a table to link options to the districts in which they are relevant. This is extremely
simple for the referendum: both options are relevant to all districts. This table is essentially
'for later expansion'."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:optionsdistricts
[:option_id "varchar(32) not null references options(option)"]
[:district_id "integer not null references districts(id)"])))
;; I think we don't need an entity for optionsdistricts, because it's just a link table.
(defn create-intention-table!
"Create a table to record the intention of an elector as solicited by a canvasser during a visit.
TODO: decide whether to insert a record in this table for 'don't knows'."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:intentions
[:id "serial primary key"]
;; the elector who gave this intention
[:elector_id "integer not null references electors(id)"]
;; the option the elector said they were planning to vote for
[:option_id "varchar(32) not null references options(option)"]
[:visit_id "integer not null references visits(id)"])))
(kc/defentity intention
(kc/pk :id)
(kc/table :intentions)
(kc/database yyydb/*db*)
(kc/entity-fields :id)
(kc/has-one elector)
(kc/has-one option)
(kc/has-one visit))
(defn create-issues-table!
"A table for issues we predict electors may raise on the doorstep, for which we may be
able to provide extra information or arrange for issue-specialists to phone and talk
to the elector."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:issues
;; short name of this issue, e.g. 'currency', 'defence', 'pensions'
[:id "varchar(32) not null primary key"]
;; URL of some brief material the canvasser can use on the doorstap
[:url "varchar(256)"])))
(kc/defentity issue
(kc/pk :id)
(kc/table :issues)
(kc/database yyydb/*db*)
(kc/entity-fields :id :url))
(defn create-followup-methods-table!
"Create a table to hold reference data on followup methods."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:followupmethods
[;; the method, e.g. 'telephone', 'email', 'post'
:id "varchar(32) not null primary key"])))
(kc/defentity followup-method
(kc/pk :id)
(kc/table :followupmethods)
(kc/database yyydb/*db*)
(kc/entity-fields :id))
(defn create-issue-expertise-table!
"A table to record which canvassers have expertise in which issues, so that followup
requests can be directed to the right canvassers."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:issueexpertise
;; the expert canvasser
[:canvasser_id "integer not null references canvassers(id)"]
;; the issue they have expertise in
[:issue_id "varchar(32) not null references issues(id)"]
;; the method by which this expert can respond to electors on this issue
[:method_id "varchar(32) not null references followupmethods(id)"])))
(kc/defentity issue-expertise
(kc/table :issueexpertise)
(kc/database yyydb/*db*)
(kc/entity-fields :id)
(kc/has-one canvasser)
(kc/has-one issue)
(kc/has-one followup-method))
(defn create-followup-requests-table!
"Create a table to record requests for followup contacts on particular issues."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:followuprequests
[:id "serial primary key"]
[:elector_id "integer not null references electors(id)"]
[:visit_id "integer not null references visits(id)"]
[:issue_id "varchar(32) not null references issues(id)"]
;; We probably need a followupmethod (telephone, email, postal) and, for telephone,
;; convenient times but I haven't thought through how to represent this or how
;; the user interface will work.
[:method_id "varchar(32) not null references followupmethods(id)"])))
(kc/defentity followup-request
(kc/table :followuprequests)
(kc/database yyydb/*db*)
(kc/entity-fields :id)
(kc/has-one elector)
(kc/has-one visit)
(kc/has-one issue)
(kc/has-one followup-method))
(defn create-followup-actions-table!
"Create a table to record actions on followup requests. Record in this table are almost
certainly created through a desktop-style interface rather than through te app, so it's
reasonable that there should be narrative fields."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:followupactions
[:id "serial primary key"]
[:request_id "integer not null references followuprequests(id)"]
[:actor "integer not null references canvassers(id)"]
[:date "timestamp with time zone not null default now()"]
[:notes "text"]
;; true if this action closes the request
[:closed :boolean])))
(kc/defentity followup-action
(kc/table :followupactions)
(kc/database yyydb/*db*)
(kc/entity-fields :id :notes :date :closed)
(kc/has-one followup-request)
(kc/has-one canvasser {:fk :actor}))
(defn create-role-table!
"Create a table to record roles. I'm not even yet certain that this is strictly necessary,
but it allows us to record the fact that different users (canvassers) have different roles
in the system."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:roles
[:id "serial primary key"]
[:name "varchar(64) not null"])))
(defn create-role-membership-table!
"Create a link table to record membership of roles."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:rolememberships
[:role_id "integer not null references role(id)"]
[:canvasser_id "integer not null references canvasser(id)"])))
(kc/defentity role
(kc/table :roles)
(kc/database yyydb/*db*)
(kc/entity-fields :id :name)
(kc/many-to-many canvasser :rolememberships))
(defn create-team-table!
"Create a table to record teams."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:teams
[:id "serial primary key"]
[:name "varchar(64) not null"]
;; the electoral district within which this address exists
[:district_id "integer references districts(id)"]
;; nominal home location of this team
[:latitude :real]
[:longitude :real])))
(defn create-team-membership-table!
"Create a link table to record membership of team."
[]
(sql/db-do-commands
yyydb/*db*
(sql/create-table-ddl
:teammemberships
[:team_id "integer not null references team(id)"]
[:canvasser_id "integer not null references canvasser(id)"])))
(kc/defentity team
(kc/table :teams)
(kc/database yyydb/*db*)
(kc/entity-fields :id :name :latitude :longitude)
(kc/has-one district)
(kc/many-to-many canvasser :teammemberships))
(defn init-db! []
"Initialised the whole database."
(create-districts-table!)
(create-addresses-table!)
(create-authorities-table!)
(create-electors-table!)
(create-canvassers-table!)
(create-visits-table!)
(create-options-table!)
(create-issues-table!)
(create-followup-methods-table!)
(create-issue-expertise-table!)
(create-followup-requests-table!)
(create-followup-actions-table!)
(create-role-table!)
(create-role-membership-table!)
(create-team-table!)
(create-team-membership-table!)
)

View file

@ -9,7 +9,6 @@
[youyesyet.config :refer [env]]
[youyesyet.layout :refer [error-page]]
[youyesyet.middleware :as middleware]
[youyesyet.routes.authenticated :refer [authenticated-routes]]
[youyesyet.routes.home :refer [home-routes]]
[youyesyet.routes.oauth :refer [oauth-routes]]
[youyesyet.routes.auto-json :refer [auto-rest-routes]]
@ -73,7 +72,7 @@
(wrap-routes middleware/wrap-csrf)
(wrap-routes middleware/wrap-formats))
'oauth-routes
#'authenticated-routes
(route/resources "/")
(route/not-found
(:body
(error-page {:status 404

View file

@ -66,21 +66,18 @@
[template session & [params]]
(let [user (:user session)]
(log/debug (str "layout/render: template: '" template "'; user: '" user "'."))
(assoc
(content-type
(ok
(content-type
(ok
(parser/render-file
template
(assoc params
:page template
:csrf-token *anti-forgery-token*
:version (System/getProperty "youyesyet.version"))))
"text/html; charset=utf-8")
:user user
:user-roles (get-user-roles user)
:site-title (:site-title env)
:site-logo (:site-logo env)
:session session)))
template
(assoc params
:page template
:csrf-token *anti-forgery-token*
:user user
:user-roles (get-user-roles user)
:site-title (:site-title env)
:version (System/getProperty "youyesyet.version"))))
"text/html; charset=utf-8")))
(defn error-page

View file

@ -1,76 +0,0 @@
(ns ^{:doc "Routes/pages available to all authenticated users."
:author "Simon Brooke"}
youyesyet.routes.authenticated
(:require [clojure.java.io :as io]
[clojure.walk :refer [keywordize-keys]]
[compojure.core :refer [defroutes GET POST]]
[noir.response :as nresponse]
[noir.util.route :as route]
[ring.util.http-response :as response]
[youyesyet.layout :as layout]
[youyesyet.db.core :as db]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.routes.authenticated: routes and pages for authenticated users.
;;;;
;;;; 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
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; This code adapted from http://www.luminusweb.net/docs#accessing_the_database
(defn post?
"Return true if the argument is a ring request which is a post request"
[request]
true)
(defn canvasser-page
"Process this canvasser request, and render the canvasser page"
[request]
(let [canvasser (if
(:params request)
(let [params (:params request)]
(if (:id params)
(if (post? request)
(db/update-canvasser! params)
(db/create-canvasser! params))
(db/get-canvasser (:id params)))
))]
(layout/render
"canvasser.html"
(:session request)
{:title (if canvasser
(str
"Edit canvasser "
(:fullname canvasser)
" "
(:email canvasser))
"Add new canvasser")
:canvasser canvasser
:address (if (:address_id canvasser) (db/get-address (:address_id canvasser)))})))
(defn routing-page
"Render the routing page, which offers routes according to the user's roles"
[request]
(layout/render "routing.html" (:session request)))
(defroutes authenticated-routes
(GET "/edit-canvasser" request (canvasser-page request))
(POST "/edit-canvasser" request (canvasser-page request))
(GET "/routing" [request] (routing-page request)))

View file

@ -36,12 +36,14 @@
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn app-page []
(layout/render "app.html" {}))
(defn app-page [request]
(layout/render "app.html" {:title "Canvasser app"
:user (:user (:session request))}))
(defn about-page []
(layout/render "about.html" {} {:title (str "About " (:site-title env))}))
(layout/render "about.html" {} {:title
(str "About " (:site-title env))}))
(defn call-me-page [request]
@ -129,8 +131,7 @@
(GET "/home" [] (home-page))
(GET "/about" [] (about-page))
(GET "/roles" request (route/restricted (roles-page request)))
(GET "/canvassers" [] (route/restricted (app-page)))
(GET "/app" [] (route/restricted (app-page)))
(GET "/canvassers" [request] (route/restricted (app-page request)))
(GET "/call-me" [] (call-me-page nil))
(POST "/call-me" request (call-me-page request))
(GET "/auth" request (login-page request))

View file

@ -224,3 +224,17 @@
(if (integer? zoom)
(assoc db :zoom zoom)
db)))
(defn get-current-location []
"Get the current location from the device."
(try
(if (.-geolocation js/navigator)
(.getCurrentPosition
(.-geolocation js/navigator)
(fn [position]
(dispatch [:set-latitude (.-latitude (.-coords position))])
(dispatch [:set-longitude (.-longitude (.-coords position))])))
(js/console.log "Geolocation not available"))
(catch js/Object any
(js/console.log "Exception while trying to access location: " + any))))

View file

@ -27,9 +27,6 @@
;;; 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.
;;;
;;; not wonderfully happy with 'db' as a name for this namespace; will probably change to
;;; 'client-state'.
(def default-db
{;;; the currently selected address, if any.
@ -87,3 +84,4 @@
:latitude 55.82
:longitude -4.25
:zoom 12})

View file

@ -28,15 +28,22 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn back-link []
[:div.back-link-container {:id "back-link-container"}
[:a {:href "javascript:history.back()" :id "back-link"} "Back"]])
(defn back-link
"Generate a back link to the preceding page, or, if `target` is specified,
to a particular page."
([]
(back-link "javascript:history.back()"))
([target]
[:div.back-link-container {:id "back-link-container"}
[:a {:href target :id "back-link"} "Back"]]))
(defn big-link [text target]
(defn big-link
[text & {:keys [target intention]}]
[:div.big-link-container {:key target}
[:a.big-link {:href target} text]])
[:a.big-link (merge
(if target {:href target}{})
(if intention {:on-click intention}))
text]])
(defn nav-link [uri title page collapsed?]
(let [selected-page (rf/subscribe [:page])]

View file

@ -48,7 +48,7 @@
[dwelling]
(ui/big-link
(:sub-address dwelling)
(str "#/electors/" (:id dwelling))) )
:target (str "#/electors/" (:id dwelling))) )
(sort
#(< (:sub-address %1) (:sub-address %2))
(:dwellings address)))]]]))

View file

@ -0,0 +1,104 @@
(ns ^{:doc "Canvasser app single elector panel."
:author "Simon Brooke"}
youyesyet.canvasser-app.views.electors
(:require [reagent.core :refer [atom]]
[re-frame.core :refer [reg-sub subscribe dispatch]]
[youyesyet.canvasser-app.ui-utils :as ui]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.canvasser-app.views.elector: elector view for youyesyet.
;;;;
;;;; 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 gender-row
"Generate a row containing a cell showing the gender of this `elector`."
[elector]
(let [gender (:gender elector)
image (if gender (name gender) "unknown")]
[:tr
[:td {:key (:id elector)}
[:img {:src (str "img/gender/" image ".png") :alt image}]]]))
(defn name-row
"Generate a row containing a cell showing the name of this `elector`."
[elector]
[:tr
[:td {:key (:id elector)}
(:name elector)]])
(defn option-row
"Generate a row showing this `option` for this elector."
[elector option]
(let [optid (:id option)
optname (name optid)]
[:tr {:key (str "options-" optname)}
(let [selected (= optid (:intention elector))
image (if selected (str "img/option/" optname "-selected.png")
(str "img/option/" optname "-unselected.png"))]
[:td {:key (str "option-" optid "-" (:id elector))}
[:img
{:src image
:alt optname
:on-click #(dispatch
[:send-intention {:elector-id (:id elector)
:intention optid}])}]])]))
(defn issue-row
"Generate a row containing an issue cell for a particular elector"
[elector]
[:tr
[:td {:key (:id elector)}
[:a {:href (str "#/issues/" (:id elector))}
[:img {:src "img/issues.png" :alt "Issues"}]]]])
(defn panel
"Generate the elector panel."
[]
(let [address @(subscribe [:address])
dwelling @(subscribe [:dwelling])
elector @(subscribe [:elector])
electors [elector]
options @(subscribe [:options])
sub-address (:sub-address dwelling)]
(if address
[:div
[:h1 (if sub-address
(str sub-address ", " (:address address))
(:address address))]
[:div.container {:id "main-container"}
[:table
[:tbody
;; genders row
(gender-row elector)
;; names row
(name-row elector)
;; options rows
(map
#(option-row elector %)
options)
;; issues row
(issues-row elector)]]
(ui/back-link)]]
(ui/error-panel "No address selected"))))

View file

@ -40,15 +40,17 @@
;;; Each column contains
;;; 1. a stick figure identifying gender (for recognition);
;;; 2. the elector's name;
;;; 3. one icon for each option on the ballot;
;;; 4. an 'issues' icon.
;;; The mechanics of how this panel is laid out don't matter.
(defn gender-cell
[elector]
(let [gender (:gender elector)
image (if gender (name gender) "unknown")]
[:td {:key (:id elector)} [:img {:src (str "img/gender/" image ".png") :alt image}]]))
[:td {:key (str "gender-" (:id elector))}
[:img {:src (str "img/gender/" image ".png") :alt image
:on-click #(dispatch
[:set-elector-and-page {:elector-id (:id elector)
:page "gdpr"}])}]]))
(defn genders-row
@ -60,7 +62,12 @@
(defn name-cell
[elector]
[:td {:key (str "name-" (:id elector))} (:name elector)])
[:td {:key (str "name-" (:id elector))
:on-click #(dispatch
[:set-elector-and-page {:elector-id (:id elector)
:page "gdpr"}])}
(:name elector)])
(defn names-row
[electors]
@ -69,41 +76,6 @@
#(name-cell %) electors)])
(defn options-row
[electors option]
(let [optid (:id option)
optname (name optid)]
[:tr {:key (str "options-" optname)}
(map
(fn [elector] (let [selected (= optid (:intention elector))
image (if selected (str "img/option/" optname "-selected.png")
(str "img/option/" optname "-unselected.png"))]
[:td {:key (str "option-" optid "-" (:id elector))}
[:img
{: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)]))
(defn issue-cell
"Create an issue cell for a particular elector"
[elector]
[:td {:key (:id elector)}
[:a {:href (str "#/issues/" (:id elector))}
[:img {:src "img/issues.png" :alt "Issues"}]]])
(defn issues-row
[electors]
[:tr
(map
#(issue-cell %)
electors)])
(defn panel
"Generate the electors panel."
[]
@ -123,13 +95,7 @@
;; genders row
(genders-row electors)
;; names row
(names-row electors)
;; options rows
(map
#(options-row electors %)
options)
;; issues row
(issues-row electors)]]
(names-row electors)]]
(ui/back-link)]]
(ui/error-panel "No address selected"))))

View file

@ -0,0 +1,60 @@
(ns ^{:doc "Canvasser app electors in household panel."
:author "Simon Brooke"}
youyesyet.canvasser-app.views.gdpr
(:require [reagent.core :refer [atom]]
[re-frame.core :refer [reg-sub subscribe dispatch]]
[youyesyet.canvasser-app.ui-utils :as ui]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.canvasser-app.views.gdpr: consent form.
;;;;
;;;; 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
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OK, the idea here is a GDPR consent form to be signed by the elector
(defn gdpr-panel-render
[]
(let [elector @(subscribe [:elector])]
[:div
[:h1 "GDPR Consent"]
[:div.container {:id "main-container"}
(ui/back-link "#electors")
[:table
[:tbody
[:tr
[:th "I," (:name elector)]]
[:tr
[:td
[:p "Consent to have data about my voting intention stored by "
[:b "Project Hope"]
" for use in the current referendum campaign, after which
it will be anonymised or deleted."]
[:p [:i "If you do not consent, we will store your voting intention
only against your electoral district, and not link it to you"]]]]
[:tr
[:td {:id "signature-pad"}
[:canvas]]]]]]
(ui/big-link "I consent" :target "#elector") ;; TODO: need to save the signature
(ui/big-link "I DO NOT consent" :target "#elector")]))

View file

@ -47,5 +47,5 @@
[:div {:id "issue-text"
:dangerouslySetInnerHTML
{:__html (md->html (issues issue))}}]]
(ui/big-link "Request call" "#/followup")
(ui/big-link "Request call" :target "#/followup")
(ui/back-link)]]))

View file

@ -46,5 +46,5 @@
[:div.container {:id "main-container"}
(ui/back-link)
[:div {:id "issue-list"}
(map (fn [k] (ui/big-link k (str "#/issue/" k))) (keys issues))]]]
(map (fn [k] (ui/big-link k :target (str "#/issue/" k))) (keys issues))]]]
(ui/error-panel "No issues loaded"))))

View file

@ -2,7 +2,8 @@
:author "Simon Brooke"}
youyesyet.canvasser-app.views.map
(:require [re-frame.core :refer [reg-sub subscribe dispatch]]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[youyesyet.canvasser-app.handlers :refer [get-current-location]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
@ -115,6 +116,7 @@
(defn map-did-mount-mapbox
"Did-mount function loading map tile data from MapBox (proprietary)."
[]
(get-current-location)
(let [view (.setView (.map js/L "map" (clj->js {:zoomControl "false"})) #js [55.82 -4.25] 40)]
;; NEED TO REPLACE FIXME with your mapID!
(.addTo (.tileLayer js/L "http://{s}.tiles.mapbox.com/v3/FIXME/{z}/{x}/{y}.png"
@ -126,6 +128,7 @@
(defn map-did-mount-osm
"Did-mount function loading map tile data from Open Street Map."
[]
(get-current-location)
(let [view (.setView
(.map js/L "map" (clj->js {:zoomControl false}))
#js [@(subscribe [:latitude]) @(subscribe [:longitude])]