From 1f18be5771c914d795054a13c24785207ca89001 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Thu, 16 Mar 2017 06:02:11 +0000 Subject: [PATCH 001/180] Added 'profiles.clj' to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7ff653c..99b78ef 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ pom.xml.asc .nrepl-port /node_modules/ .DS_Store -*-init.clj \ No newline at end of file +*-init.clj +profiles\.clj From 9540ae05751d21a31532fdffec9509f4eaa785a3 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Thu, 16 Mar 2017 09:00:39 +0000 Subject: [PATCH 002/180] Added collaboration stuff to README --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5900935..82cece5 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,6 @@ You'll also need to create your own local copy of *profiles.clj*, which should c Where *username* is the username required to access the database, and *thisisnotsecure* is the password which authenticates that username. -## Further Reading - -If you're thinking of joining in development on this I'd strongly recommend you get hold of a copy of [Dmitry Sotnikov](https://github.com/yogthos)'s [Web Development with Clojure, Second Edition](https://pragprog.com/book/dswdcloj2/web-development-with-clojure-second-edition). - -You should also read the [User-Oriented Specification](doc/specification/userspec.md) and any other documentation which appears under the *doc/specification* hierarchy. - ## Running To start a web server for the application, run: @@ -58,6 +52,51 @@ as above; in the other, run lein figwheel +## Working on this project + +You should get the [ZenHub](https://github.com/integrations/zenhub) plug-in for your favourite browser; I use ZenHub for project management, and you (and I) will find collaborating much easier if you do. To join in + +1. Clone the project from [my repository](https://github.com/simon-brooke/youyesyet); +2. Visit the [kanban board](https://github.com/simon-brooke/youyesyet#boards?repos=70809242) and choose an issue you'd like to work on; +3. Assign that issue to yourself and move it into the 'in progress' column; +4. Use gitflow: start a new feature; +5. Work on the issue; +6. When you are satisfied with your work, commit it to your repository in your feature branch; +7. Submit a pull request and move the issue to the 'QA/Review' column on the kanban board; +8. If your work works, I'll integrate it into the develop branch, which you can then pull; +9. Rinse and repeat! + +Obviously I'd appreciate it if you'd [mail me](mailto:simon@journeyman.cc) to introduce yourself, but there's no need to do so. + +Finally, if you take a ticket and are not able to finish it, please + +1. mail me to say so; +2. move the issue back to the 'backlog' column on the kanban board. + +And *many thanks*! + +## More about tooling + +Note that all tools recommended in this document are free for non-commercial use; not all are open source. + +### Editors/IDEs + +I (Simon) use, like and recommend [LightTable](http://lighttable.com/) as my editor; I used to use Emacs, and there is excellent Clojure tooling for Emacs, but these days Emacs ways of working seem just too far from everything else to be comfortable to me. [NightCode](https://sekao.net/nightcode/) is a lighter-weight Clojure IDE which you may like. There's also [Cursive](https://cursive-ide.com/) but it isn't free and I haven't tried it. + +### Git + +I'm currently using [GitKraken](https://www.gitkraken.com/), on Linux, Windows, and Mac. Like so many things it works best on Linux, but it's good on both other platforms. However, I confess that although I like the ability to easily view the whole structure of the git repository, I tend to drop back to the command line if I'm doing anything tricky with Git. + +### Database + +The database is [Postgres](https://www.postgresql.org/). I have no plans even to support anything else; I don't feel we have time to mess about. However, if someone wants to fork the code and implement a different database, that's up to them. I'm afraid I do all database stuff from the command line; [there are graphical tools for Postgres](https://wiki.postgresql.org/wiki/Community_Guide_to_PostgreSQL_GUI_Tools) but personally I've never found graphical tools for databases much use. + +## Further Reading + +If you're thinking of joining in development on this I'd strongly recommend you get hold of a copy of [Dmitry Sotnikov](https://github.com/yogthos)'s [Web Development with Clojure, Second Edition](https://pragprog.com/book/dswdcloj2/web-development-with-clojure-second-edition). + +You should also read the [User-Oriented Specification](doc/specification/userspec.md) and any other documentation which appears under the *doc/specification* hierarchy. + ## License Copyright © 2016 Simon Brooke for the Radical Independence Campaign. From 933e5ac2a4d310f959c3244b11ed84e2835035b3 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Fri, 17 Mar 2017 21:45:11 +0000 Subject: [PATCH 003/180] #9: Woot woot woot! Map now working with OSM tiles --- resources/templates/home.html | 5 +++++ src/cljs/youyesyet/core.cljs | 1 + src/cljs/youyesyet/views/map.cljs | 10 +++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/resources/templates/home.html b/resources/templates/home.html index c0b6d43..5c334b5 100644 --- a/resources/templates/home.html +++ b/resources/templates/home.html @@ -34,6 +34,11 @@ + + + + + + + + + {% script "/js/app.js" %} + + + + + + diff --git a/resources/templates/base-authenticated.html b/resources/templates/base-authenticated.html new file mode 100644 index 0000000..7b2d418 --- /dev/null +++ b/resources/templates/base-authenticated.html @@ -0,0 +1,42 @@ + + + + + + + + + {{title}} + + +
+ + +

+ {{title}} +

+
+ +
+ +
+ {{content}} +
+
+ + + + + + diff --git a/resources/templates/base-unauthenticated.html b/resources/templates/base-unauthenticated.html new file mode 100644 index 0000000..d1382fc --- /dev/null +++ b/resources/templates/base-unauthenticated.html @@ -0,0 +1,40 @@ + + + + + + + + + {{title}} + + +
+ + +

+ {{title}} +

+
+ +
+ +
+ {% block content %} + {% endblock %} +
+
+ + diff --git a/resources/templates/home.html b/resources/templates/home.html index 5c334b5..f89b6ae 100644 --- a/resources/templates/home.html +++ b/resources/templates/home.html @@ -1,53 +1,12 @@ - - - - - - - - - You Yes Yet? - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+{% extends "base-unauthenticated.html" %} +{% block big-links %} + - -
- - - - - - - - - - {% script "/js/app.js" %} - - - - - - + +{% endblock %} +{% block content %} +froboz +{% endblock %} diff --git a/src/clj/youyesyet/routes/home.clj b/src/clj/youyesyet/routes/home.clj index 7fbf9f7..e2bffa7 100644 --- a/src/clj/youyesyet/routes/home.clj +++ b/src/clj/youyesyet/routes/home.clj @@ -5,11 +5,14 @@ [ring.util.http-response :as response] [clojure.java.io :as io])) +(defn app-page [] + (layout/render "app.html")) + (defn home-page [] - (layout/render "home.html")) + (layout/render "home.html" {:title "You Yes Yet?"})) (defroutes home-routes (GET "/" [] (home-page)) + (GET "/app" [] (app-page)) (GET "/docs" [] (-> (response/ok (-> "docs/docs.md" io/resource slurp)) (response/header "Content-Type" "text/plain; charset=utf-8")))) - diff --git a/src/cljc/youyesyet/ui_utils.cljc b/src/cljc/youyesyet/ui_utils.cljc new file mode 100644 index 0000000..3139020 --- /dev/null +++ b/src/cljc/youyesyet/ui_utils.cljc @@ -0,0 +1 @@ +;; Ultimately it's the goal to use the same UI utils for both main site and single page app. From e5d399b86d91c420c605abf67cf101683f0d09a6 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Sun, 19 Mar 2017 23:28:27 +0000 Subject: [PATCH 011/180] Significant progress, but a long way from finished. --- resources/public/css/screen.css | 68 ------- resources/public/css/yyy-app.css | 173 ++++++++++++++++++ .../css/{yyy-static.css => yyy-common.css} | 157 +--------------- resources/public/css/yyy-site.css | 170 +++++++++++++++++ resources/templates/app.html | 3 +- resources/templates/base-unauthenticated.html | 19 +- resources/templates/call-me-accepted.html | 41 +++++ resources/templates/call-me.html | 37 ++++ resources/templates/home.html | 7 +- resources/templates/notyet.html | 12 ++ resources/templates/supporter.html | 12 ++ src/clj/youyesyet/layout.clj | 3 +- src/clj/youyesyet/routes/home.clj | 18 +- src/cljs/youyesyet/views/about.cljs | 10 +- 14 files changed, 496 insertions(+), 234 deletions(-) delete mode 100644 resources/public/css/screen.css create mode 100644 resources/public/css/yyy-app.css rename resources/public/css/{yyy-static.css => yyy-common.css} (73%) create mode 100644 resources/public/css/yyy-site.css create mode 100644 resources/templates/call-me-accepted.html create mode 100644 resources/templates/call-me.html create mode 100644 resources/templates/notyet.html create mode 100644 resources/templates/supporter.html diff --git a/resources/public/css/screen.css b/resources/public/css/screen.css deleted file mode 100644 index 534309c..0000000 --- a/resources/public/css/screen.css +++ /dev/null @@ -1,68 +0,0 @@ -html, -body { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - height: 100%; -} -.navbar { - margin-bottom: 10px; -} -.navbar-brand { - float: none; -} -.navbar-nav .nav-item { - float: none; -} -.navbar-divider, -.navbar-nav .nav-item+.nav-item, -.navbar-nav .nav-link + .nav-link { - margin-left: 0; -} -@media (min-width: 34em) { - .navbar-brand { - float: left; - } - .navbar-nav .nav-item { - float: left; - } - .navbar-divider, - .navbar-nav .nav-item+.nav-item, - .navbar-nav .nav-link + .nav-link { - margin-left: 1rem; - } -} - -@-moz-keyframes three-quarters-loader { - 0% { - -moz-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -moz-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@-webkit-keyframes three-quarters-loader { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@keyframes three-quarters-loader { - 0% { - -moz-transform: rotate(0deg); - -ms-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -moz-transform: rotate(360deg); - -ms-transform: rotate(360deg); - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - diff --git a/resources/public/css/yyy-app.css b/resources/public/css/yyy-app.css new file mode 100644 index 0000000..8a46cd2 --- /dev/null +++ b/resources/public/css/yyy-app.css @@ -0,0 +1,173 @@ +/** + * Additional CSS for the main site. Navigation works differently between + * app and the main site; in the app it's driven by React, while in + * the main site it's CSS. + * + * 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. + */ + + +/* desktops and laptops, primarily. Adapted to mouse; targets may be small */ +@media all and (min-device-width: 1025px) { + /* top-of-page navigation, not editable, provided by Smeagol */ + #nav{ + margin: 0; + padding: 0; + top: 0; + width: 100%; + _position: absolute; + _top: expression(document.documentElement.scrollTop); + z-index: 149; + background:rgba(7,27,51,0.8); + } + + /* only needed for fly-out menu effect on tablet and phone stylesheets */ + #nav-icon { + display: none; + } + + #nav-menu { + margin: 0; + padding: 0; + } + + #nav menu li { + padding: 0; + margin: 0; + display: inline; + } + + #nav menu li a { + color: white; + text-decoration: none; + font-weight: bold; + padding: 0.1em 0.75em; + margin: 0; + } + + #nav menu li.active a { background: gray;} + li.nav-item a:hover { background: rgb( 240, 240, 240) } + li.nav-item a:active { background: gray; color: white; } + + #nav menu li#user { + padding: 0 1em; + float: right; + } +} + +/* tablets, primarily. Adapted to touch; targets are larger */ +@media all and (min-device-width: 769px) and (max-device-width: 1024px) { + #nav{ + margin: 0; + padding: 0; + position: fixed; + z-index: 149; + color: silver; + background:rgba(40,40,40,0.9); + } + + #nav a { + color: white; + text-decoration: none; + font-weight: bold; + } + + #nav:hover #nav-menu { + display: block; + list-style-type: none; + width: 100%; + } + + #nav-icon { + padding: 0; + } + + #nav-menu { + display: none; + } + + #nav menu li { + padding: 0.5em 2em 0.5em 0.5em; + margin: 0.5 em; + font-size: 150%; + } + + #nav menu li a { + } + + #nav ul li.active a { background: silver;} + li.nav-item a:hover { background: rgb( 240, 240, 240) } + li.nav-item a:active { background: gray; color: white; } + + #nav menu #user { + text-decoration: none; + font-weight: bold; + margin: 0; + } +} + +/* phones, and, indeed, smaller phones. Adapted to touch; display radically + * decluttered */ +@media all and (max-device-width: 768px) { + #nav{ + margin: 0; + padding: 0; + position: fixed; + z-index: 149; + color: silver; + background:rgba(40,40,40,0.9); + } + + #nav:hover #nav-menu { + display: block; + list-style-type: none; + width: 100%; + } + + #nav a { + color: white; + text-decoration: none; + font-weight: bold; + } + + #nav-icon { + padding: 0; + } + + #nav-menu { + list-style-type: none; + display: none; + } + + #nav menu li { + padding: 0.5em 2em 0.5em 0.5em; + margin: 0.5 em; + font-size: 150%; + } + + #nav menu li a { + } + + #nav ul li.active a { background: silver;} + li.nav-item a:hover { background: rgb( 240, 240, 240) } + li.nav-item a:active { background: gray; color: white; } + + #nav menu #user { + text-decoration: none; + font-weight: bold; + margin: 0; + } +} diff --git a/resources/public/css/yyy-static.css b/resources/public/css/yyy-common.css similarity index 73% rename from resources/public/css/yyy-static.css rename to resources/public/css/yyy-common.css index 515088f..383b77e 100644 --- a/resources/public/css/yyy-static.css +++ b/resources/public/css/yyy-common.css @@ -201,11 +201,13 @@ th { } -/* left bar for all pages in the Wiki - editable, provided by users. Within main-container */ -#side-bar { - width: 17%; - height: 100%; - float: left; +#big-links { + width: 100%; + min-height: 3.5em; +} + +#content { + clear: both; } /* cookies information box, fixed, in right margin, just above footer */ @@ -337,62 +339,11 @@ th { /* desktops and laptops, primarily. Adapted to mouse; targets may be small */ @media all and (min-device-width: 1025px) { - /* content of the current page in the Wiki - editable, provided by users. Within main-container */ #content { - border: thin solid silver; width: 80%; float: right; padding-bottom: 5em; } - - #phone-side-bar, #phone-credits { - display: none; - } - - /* top-of-page navigation, not editable, provided by Smeagol */ - #nav{ - margin: 0; - padding: 0; - top: 0; - width: 100%; - _position: absolute; - _top: expression(document.documentElement.scrollTop); - z-index: 149; - background:rgba(7,27,51,0.8); - } - - /* only needed for fly-out menu effect on tablet and phone stylesheets */ - #nav-icon { - display: none; - } - - #nav-menu { - margin: 0; - padding: 0; - } - - #nav menu li { - padding: 0; - margin: 0; - display: inline; - } - - #nav menu li a { - color: white; - text-decoration: none; - font-weight: bold; - padding: 0.1em 0.75em; - margin: 0; - } - - #nav menu li.active a { background: gray;} - li.nav-item a:hover { background: rgb( 240, 240, 240) } - li.nav-item a:active { background: gray; color: white; } - - #nav menu li#user { - padding: 0 1em; - float: right; - } } /* tablets, primarily. Adapted to touch; targets are larger */ @@ -410,54 +361,6 @@ th { float: right; padding-bottom: 5em; } - - #nav{ - margin: 0; - padding: 0; - position: fixed; - z-index: 149; - color: silver; - background:rgba(40,40,40,0.9); - } - - #nav a { - color: white; - text-decoration: none; - font-weight: bold; - } - - #nav:hover #nav-menu { - display: block; - list-style-type: none; - width: 100%; - } - - #nav-icon { - padding: 0; - } - - #nav-menu, #phone-side-bar { - display: none; - } - - #nav menu li { - padding: 0.5em 2em 0.5em 0.5em; - margin: 0.5 em; - font-size: 150%; - } - - #nav menu li a { - } - - #nav ul li.active a { background: silver;} - li.nav-item a:hover { background: rgb( 240, 240, 240) } - li.nav-item a:active { background: gray; color: white; } - - #nav menu #user { - text-decoration: none; - font-weight: bold; - margin: 0; - } } /* phones, and, indeed, smaller phones. Adapted to touch; display radically @@ -499,50 +402,4 @@ th { #cookies { display: none; } - - #nav{ - margin: 0; - padding: 0; - position: fixed; - z-index: 149; - color: silver; - background:rgba(40,40,40,0.9); - } - - #nav a { - color: white; - text-decoration: none; - font-weight: bold; - } - - #nav-icon { - padding: 0; - } - - #nav-menu { - list-style-type: none; - } - - #nav menu li { - padding: 0.5em 2em 0.5em 0.5em; - margin: 0.5 em; - font-size: 150%; - } - - #nav menu li a { - } - - #nav ul li.active a { background: silver;} - li.nav-item a:hover { background: rgb( 240, 240, 240) } - li.nav-item a:active { background: gray; color: white; } - - #nav menu #user { - text-decoration: none; - font-weight: bold; - margin: 0; - } - - #side-bar { - display: none; - } } diff --git a/resources/public/css/yyy-site.css b/resources/public/css/yyy-site.css new file mode 100644 index 0000000..0f25301 --- /dev/null +++ b/resources/public/css/yyy-site.css @@ -0,0 +1,170 @@ +/** + * Additional CSS for the app. Navigation works differently between + * app and the main site; in the app it's driven by React, while in + * the main site it's CSS. + * + * 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. + * + * # The Stylesheet + * + * ## html elements generally in alphabetic order + */ + + +/* desktops and laptops, primarily. Adapted to mouse; targets may be small */ +@media all and (min-device-width: 1025px) { + /* top-of-page navigation, not editable, provided by Smeagol */ + #nav{ + margin: 0; + padding: 0; + top: 0; + width: 100%; + _position: absolute; + _top: expression(document.documentElement.scrollTop); + z-index: 149; + background:rgba(7,27,51,0.8); + } + + /* only needed for fly-out menu effect on tablet and phone stylesheets */ + #nav-icon { + display: none; + } + + #nav-menu { + margin: 0; + padding: 0; + } + + #nav menu li { + padding: 0; + margin: 0; + display: inline; + } + + #nav menu li a { + color: white; + text-decoration: none; + font-weight: bold; + padding: 0.1em 0.75em; + margin: 0; + } + + #nav menu li.active a { background: gray;} + li.nav-item a:hover { background: rgb( 240, 240, 240) } + li.nav-item a:active { background: gray; color: white; } + + #nav menu li#user { + padding: 0 1em; + float: right; + } +} + +/* tablets, primarily. Adapted to touch; targets are larger */ +@media all and (min-device-width: 769px) and (max-device-width: 1024px) { + #nav{ + margin: 0; + padding: 0; + position: fixed; + z-index: 149; + color: silver; + background:rgba(40,40,40,0.9); + } + + #nav a { + color: white; + text-decoration: none; + font-weight: bold; + } + + #nav:hover #nav-menu { + display: block; + list-style-type: none; + width: 100%; + } + + #nav-icon { + padding: 0; + } + + #nav-menu, #phone-side-bar { + display: none; + } + + #nav menu li { + padding: 0.5em 2em 0.5em 0.5em; + margin: 0.5 em; + font-size: 150%; + } + + #nav menu li a { + } + + #nav ul li.active a { background: silver;} + li.nav-item a:hover { background: rgb( 240, 240, 240) } + li.nav-item a:active { background: gray; color: white; } + + #nav menu #user { + text-decoration: none; + font-weight: bold; + margin: 0; + } +} + +/* phones, and, indeed, smaller phones. Adapted to touch; display radically + * decluttered */ +@media all and (max-device-width: 768px) { + #nav{ + margin: 0; + padding: 0; + position: fixed; + z-index: 149; + color: silver; + background:rgba(40,40,40,0.9); + } + + #nav a { + color: white; + text-decoration: none; + font-weight: bold; + } + + #nav-icon { + padding: 0; + } + + #nav-menu { + list-style-type: none; + } + + #nav menu li { + padding: 0.5em 2em 0.5em 0.5em; + margin: 0.5 em; + font-size: 150%; + } + + #nav menu li a { + } + + #nav ul li.active a { background: silver;} + li.nav-item a:hover { background: rgb( 240, 240, 240) } + li.nav-item a:active { background: gray; color: white; } + + #nav menu #user { + text-decoration: none; + font-weight: bold; + margin: 0; + } +} diff --git a/resources/templates/app.html b/resources/templates/app.html index 5c334b5..f313066 100644 --- a/resources/templates/app.html +++ b/resources/templates/app.html @@ -3,7 +3,8 @@ - + + You Yes Yet? diff --git a/resources/templates/base-unauthenticated.html b/resources/templates/base-unauthenticated.html index d1382fc..c243d01 100644 --- a/resources/templates/base-unauthenticated.html +++ b/resources/templates/base-unauthenticated.html @@ -3,8 +3,8 @@ - - + + {{title}} @@ -36,5 +36,20 @@ {% endblock %}
+ -{% endblock %} \ No newline at end of file +{% endblock %} +{% block extra-script %} +var form = document.getElementById("content"); + +document.getElementById("next-selector").addEventListener("click", function () { + form.submit(); +}); +{% endblock %} diff --git a/resources/templates/base.html b/resources/templates/base.html index 227b668..a219f55 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -1,6 +1,8 @@ + {% block head %} + @@ -8,10 +10,12 @@ {{site-title}}: {{title}} + {% script "js/lib/jquery/dist/jquery.min.js" %} {% block extra-head %} {% endblock %} + {% endblock %} {% block whole-page %} @@ -32,7 +36,7 @@ {% endif %} - +

{{title}}

{% endblock %} diff --git a/youyesyet.adl.xml b/youyesyet.adl.xml index a9ab863..d542d6f 100644 --- a/youyesyet.adl.xml +++ b/youyesyet.adl.xml @@ -14,15 +14,16 @@ - - - - - - - {{site-title}}: {{title}} - - + + + + + + + {{site-title}}: {{title}} + + +
From f5afa67eedec8ec38a240de911294426f2652287 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 2 Jul 2018 10:51:42 +0100 Subject: [PATCH 081/180] More work on UI, but this commit has a regression The user is no longer correctly stored in the session, and I'm not sure why not. --- env/dev/clj/youyesyet/core.clj | 11 +- project.clj | 4 +- resources/sql/queries.auto.sql | 2 +- resources/sql/youyesyet.postgres.sql | 4 +- .../templates/auto/application-index.html | 66 +- .../auto/form-addresses-Address.html | 66 +- .../auto/form-authorities-Authority.html | 66 +- .../auto/form-canvassers-Canvasser.html | 66 +- .../auto/form-districts-District.html | 66 +- .../auto/form-dwellings-Dwelling.html | 66 +- .../templates/auto/form-electors-Elector.html | 66 +- .../form-followupactions-Followupaction.html | 66 +- .../form-followupmethods-Followupmethod.html | 66 +- ...form-followuprequests-Followuprequest.html | 66 +- .../templates/auto/form-genders-Gender.html | 66 +- .../auto/form-intentions-Intention.html | 66 +- .../templates/auto/form-issues-Issue.html | 66 +- .../templates/auto/form-options-Option.html | 66 +- resources/templates/auto/form-roles-Role.html | 66 +- resources/templates/auto/form-teams-Team.html | 66 +- .../templates/auto/form-visits-Visit.html | 66 +- .../auto/list-addresses-Addresses.html | 133 +- .../auto/list-authorities-Authorities.html | 126 +- .../auto/list-canvassers-Canvassers.html | 126 +- .../auto/list-districts-Districts.html | 126 +- .../auto/list-dwellings-Dwellings.html | 126 +- .../auto/list-electors-Electors.html | 126 +- .../list-followupactions-Followupactions.html | 126 +- .../list-followupmethods-Followupmethods.html | 126 +- ...ist-followuprequests-Followuprequests.html | 126 +- .../templates/auto/list-genders-Genders.html | 126 +- .../auto/list-intentions-Intentions.html | 126 +- .../templates/auto/list-issues-Issues.html | 126 +- .../templates/auto/list-options-Options.html | 126 +- .../templates/auto/list-roles-Roles.html | 126 +- .../templates/auto/list-teams-Teams.html | 126 +- .../templates/auto/list-visits-Visits.html | 126 +- resources/templates/base.html | 6 +- src/clj/youyesyet/db/core.clj | 3 +- src/clj/youyesyet/layout.clj | 35 +- src/clj/youyesyet/middleware.clj | 17 +- src/clj/youyesyet/routes/auto.clj | 1088 +++++++++---- src/clj/youyesyet/routes/auto_json.clj | 1407 +++++++++++++++-- src/clj/youyesyet/routes/home.clj | 84 +- youyesyet.adl.xml | 31 - youyesyet.canonical.adl.xml | 38 +- 46 files changed, 3054 insertions(+), 2821 deletions(-) diff --git a/env/dev/clj/youyesyet/core.clj b/env/dev/clj/youyesyet/core.clj index 1b703a4..c64c2e7 100644 --- a/env/dev/clj/youyesyet/core.clj +++ b/env/dev/clj/youyesyet/core.clj @@ -46,7 +46,9 @@ mount/start-with-args :started)] (log/info component "started")) - (.addShutdownHook (Runtime/getRuntime) (Thread. handler/destroy))) + (.addShutdownHook (Runtime/getRuntime) + (Thread. handler/destroy))) + (defn -main [& args] (cond @@ -57,4 +59,9 @@ (System/exit 0)) :else (start-app args))) - + +(mount/stop) + +(mount/start) + + diff --git a/project.clj b/project.clj index 61956c8..303e26e 100644 --- a/project.clj +++ b/project.clj @@ -62,7 +62,9 @@ [lein-codox "0.10.3"]] :bower-dependencies [[leaflet "0.7.3"] - [jquery "3.3.1"]] + [jquery "3.3.1"] + [datatables.net "1.10.19"] + [datatables.net-dt "1.10.19"]] :bower {:directory "resources/public/js/lib"} :cucumber-feature-paths ["test/clj/features"] diff --git a/resources/sql/queries.auto.sql b/resources/sql/queries.auto.sql index e08aa23..27bdde1 100644 --- a/resources/sql/queries.auto.sql +++ b/resources/sql/queries.auto.sql @@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- File queries.sql -- --- autogenerated by adl.to-hugsql-queries at 2018-06-30T11:35:59.388Z +-- autogenerated by adl.to-hugsql-queries at 2018-07-01T22:15:28.111Z -- -- See [Application Description -- Language](https://github.com/simon-brooke/adl). diff --git a/resources/sql/youyesyet.postgres.sql b/resources/sql/youyesyet.postgres.sql index e787f6f..a8aab30 100644 --- a/resources/sql/youyesyet.postgres.sql +++ b/resources/sql/youyesyet.postgres.sql @@ -5,7 +5,7 @@ -- -- auto-generated by [Application Description Language framework] -- --- (https://github.com/simon-brooke/adl) at 20180630T113600.308Z +-- (https://github.com/simon-brooke/adl) at 20180701T221532.672Z -- -- -- A web-app intended to be used by canvassers campaigning for a @@ -75,7 +75,7 @@ CREATE TABLE addresses ( id SERIAL NOT NULL PRIMARY KEY, address VARCHAR(256) NOT NULL, - postcode VARCHAR(16) CONSTRAINT pattern_1 CHECK (postcode ~* '^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$'), + postcode VARCHAR(16) CONSTRAINT pattern_14 CHECK (postcode ~* '^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$'), phone VARCHAR(16), district_id INTEGER, latitude DOUBLE PRECISION, diff --git a/resources/templates/auto/application-index.html b/resources/templates/auto/application-index.html index c379eea..27f6615 100644 --- a/resources/templates/auto/application-index.html +++ b/resources/templates/auto/application-index.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -184,50 +167,3 @@ All visits made by canvassers to dwellings in which opinions were recorded.
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-addresses-Address.html b/resources/templates/auto/form-addresses-Address.html index ee7c8ba..6fbbbc4 100644 --- a/resources/templates/auto/form-addresses-Address.html +++ b/resources/templates/auto/form-addresses-Address.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -171,50 +154,3 @@ To delete this addresses record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-authorities-Authority.html b/resources/templates/auto/form-authorities-Authority.html index fa47abe..02749f0 100644 --- a/resources/templates/auto/form-authorities-Authority.html +++ b/resources/templates/auto/form-authorities-Authority.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -148,50 +131,3 @@ To delete this authorities record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-canvassers-Canvasser.html b/resources/templates/auto/form-canvassers-Canvasser.html index ba56e4a..7e94c21 100644 --- a/resources/templates/auto/form-canvassers-Canvasser.html +++ b/resources/templates/auto/form-canvassers-Canvasser.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -239,50 +222,3 @@ To delete this canvassers record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-districts-District.html b/resources/templates/auto/form-districts-District.html index 851e38f..733f6f2 100644 --- a/resources/templates/auto/form-districts-District.html +++ b/resources/templates/auto/form-districts-District.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -76,50 +59,3 @@ To delete this districts record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-dwellings-Dwelling.html b/resources/templates/auto/form-dwellings-Dwelling.html index 4a164ab..692539f 100644 --- a/resources/templates/auto/form-dwellings-Dwelling.html +++ b/resources/templates/auto/form-dwellings-Dwelling.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -99,50 +82,3 @@ To delete this dwellings record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-electors-Elector.html b/resources/templates/auto/form-electors-Elector.html index d2ceff2..6ad712a 100644 --- a/resources/templates/auto/form-electors-Elector.html +++ b/resources/templates/auto/form-electors-Elector.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -157,50 +140,3 @@ To delete this electors record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-followupactions-Followupaction.html b/resources/templates/auto/form-followupactions-Followupaction.html index 9486e73..ac42a80 100644 --- a/resources/templates/auto/form-followupactions-Followupaction.html +++ b/resources/templates/auto/form-followupactions-Followupaction.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -158,50 +141,3 @@ To delete this followupactions record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-followupmethods-Followupmethod.html b/resources/templates/auto/form-followupmethods-Followupmethod.html index 0ebe89e..b1810ab 100644 --- a/resources/templates/auto/form-followupmethods-Followupmethod.html +++ b/resources/templates/auto/form-followupmethods-Followupmethod.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -58,50 +41,3 @@ To delete this followupmethods record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-followuprequests-Followuprequest.html b/resources/templates/auto/form-followuprequests-Followuprequest.html index 810e20a..fc30435 100644 --- a/resources/templates/auto/form-followuprequests-Followuprequest.html +++ b/resources/templates/auto/form-followuprequests-Followuprequest.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -148,50 +131,3 @@ To delete this followuprequests record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-genders-Gender.html b/resources/templates/auto/form-genders-Gender.html index 33c1930..9beaae3 100644 --- a/resources/templates/auto/form-genders-Gender.html +++ b/resources/templates/auto/form-genders-Gender.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -58,50 +41,3 @@ To delete this genders record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-intentions-Intention.html b/resources/templates/auto/form-intentions-Intention.html index b2287ec..d04e85a 100644 --- a/resources/templates/auto/form-intentions-Intention.html +++ b/resources/templates/auto/form-intentions-Intention.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -126,50 +109,3 @@ To delete this intentions record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-issues-Issue.html b/resources/templates/auto/form-issues-Issue.html index cd89da2..e2e6ebc 100644 --- a/resources/templates/auto/form-issues-Issue.html +++ b/resources/templates/auto/form-issues-Issue.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -94,50 +77,3 @@ To delete this issues record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-options-Option.html b/resources/templates/auto/form-options-Option.html index 5e4524b..01647cf 100644 --- a/resources/templates/auto/form-options-Option.html +++ b/resources/templates/auto/form-options-Option.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -58,50 +41,3 @@ To delete this options record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-roles-Role.html b/resources/templates/auto/form-roles-Role.html index ed2f57a..6a6986a 100644 --- a/resources/templates/auto/form-roles-Role.html +++ b/resources/templates/auto/form-roles-Role.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -99,50 +82,3 @@ To delete this roles record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-teams-Team.html b/resources/templates/auto/form-teams-Team.html index 6f4bc0d..da15535 100644 --- a/resources/templates/auto/form-teams-Team.html +++ b/resources/templates/auto/form-teams-Team.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -181,50 +164,3 @@ To delete this teams record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/form-visits-Visit.html b/resources/templates/auto/form-visits-Visit.html index 9482227..0607158 100644 --- a/resources/templates/auto/form-visits-Visit.html +++ b/resources/templates/auto/form-visits-Visit.html @@ -1,24 +1,7 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - - -{{site-title}}: {{title}} - - -{% endblock %} {% block content %}
@@ -122,50 +105,3 @@ To delete this visits record
{% endblock %} -{% block foot %} - - -{% endblock %} \ No newline at end of file diff --git a/resources/templates/auto/list-addresses-Addresses.html b/resources/templates/auto/list-addresses-Addresses.html index 7ad3988..532526f 100644 --- a/resources/templates/auto/list-addresses-Addresses.html +++ b/resources/templates/auto/list-addresses-Addresses.html @@ -1,48 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} {% block big-links %} + + {% endblock %} {% block content %} -
+ {% csrf-field %} - - - - + + @@ -91,7 +87,7 @@ longitude @@ -129,63 +125,30 @@ View {% endfor %} - -
- +
-{% endblock %} -{% block foot %} - - {% endblock %} {% block extra-script %} -var form = document.getElementById("content"); -document.getElementById("next-selector").addEventListener("click", function () { - form.submit(); -}); + var form = document.getElementById('list-addresses-Addresses'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); + + {% ifunequal offset \"0\" %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); {% endblock %} diff --git a/resources/templates/auto/list-authorities-Authorities.html b/resources/templates/auto/list-authorities-Authorities.html index d479410..6692a65 100644 --- a/resources/templates/auto/list-authorities-Authorities.html +++ b/resources/templates/auto/list-authorities-Authorities.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -57,7 +69,7 @@ authorize-uri @@ -84,62 +96,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-authorities-Authorities'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-canvassers-Canvassers.html b/resources/templates/auto/list-canvassers-Canvassers.html index 2e2daf8..b1a546f 100644 --- a/resources/templates/auto/list-canvassers-Canvassers.html +++ b/resources/templates/auto/list-canvassers-Canvassers.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -87,7 +99,7 @@ authorised @@ -135,62 +147,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-canvassers-Canvassers'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-districts-Districts.html b/resources/templates/auto/list-districts-Districts.html index 5aa04b4..75c7410 100644 --- a/resources/templates/auto/list-districts-Districts.html +++ b/resources/templates/auto/list-districts-Districts.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -45,7 +57,7 @@ name @@ -66,62 +78,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-districts-Districts'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-dwellings-Dwellings.html b/resources/templates/auto/list-dwellings-Dwellings.html index d4a5468..e71d566 100644 --- a/resources/templates/auto/list-dwellings-Dwellings.html +++ b/resources/templates/auto/list-dwellings-Dwellings.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -51,7 +63,7 @@ sub-address @@ -77,62 +89,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-dwellings-Dwellings'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-electors-Electors.html b/resources/templates/auto/list-electors-Electors.html index 78da6fe..7250f3c 100644 --- a/resources/templates/auto/list-electors-Electors.html +++ b/resources/templates/auto/list-electors-Electors.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -69,7 +81,7 @@ gender @@ -106,62 +118,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-electors-Electors'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-followupactions-Followupactions.html b/resources/templates/auto/list-followupactions-Followupactions.html index c0c7c29..43967c2 100644 --- a/resources/templates/auto/list-followupactions-Followupactions.html +++ b/resources/templates/auto/list-followupactions-Followupactions.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -69,7 +81,7 @@ closed @@ -106,62 +118,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-followupactions-Followupactions'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-followupmethods-Followupmethods.html b/resources/templates/auto/list-followupmethods-Followupmethods.html index fba6c0f..7a2f684 100644 --- a/resources/templates/auto/list-followupmethods-Followupmethods.html +++ b/resources/templates/auto/list-followupmethods-Followupmethods.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -39,7 +51,7 @@ id @@ -57,62 +69,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-followupmethods-Followupmethods'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-followuprequests-Followuprequests.html b/resources/templates/auto/list-followuprequests-Followuprequests.html index 1a92655..20146d0 100644 --- a/resources/templates/auto/list-followuprequests-Followuprequests.html +++ b/resources/templates/auto/list-followuprequests-Followuprequests.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -63,7 +75,7 @@ method_id @@ -101,62 +113,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-followuprequests-Followuprequests'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-genders-Genders.html b/resources/templates/auto/list-genders-Genders.html index d421968..cd81ff6 100644 --- a/resources/templates/auto/list-genders-Genders.html +++ b/resources/templates/auto/list-genders-Genders.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -39,7 +51,7 @@ id @@ -57,62 +69,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-genders-Genders'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-intentions-Intentions.html b/resources/templates/auto/list-intentions-Intentions.html index de75da8..5d2e535 100644 --- a/resources/templates/auto/list-intentions-Intentions.html +++ b/resources/templates/auto/list-intentions-Intentions.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -57,7 +69,7 @@ locality @@ -90,62 +102,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-intentions-Intentions'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-issues-Issues.html b/resources/templates/auto/list-issues-Issues.html index af0eb2c..1cbe0bb 100644 --- a/resources/templates/auto/list-issues-Issues.html +++ b/resources/templates/auto/list-issues-Issues.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -51,7 +63,7 @@ current @@ -75,62 +87,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-issues-Issues'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-options-Options.html b/resources/templates/auto/list-options-Options.html index 3479834..65821ec 100644 --- a/resources/templates/auto/list-options-Options.html +++ b/resources/templates/auto/list-options-Options.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -39,7 +51,7 @@ id @@ -57,62 +69,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-options-Options'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-roles-Roles.html b/resources/templates/auto/list-roles-Roles.html index 8a2a73f..276d38a 100644 --- a/resources/templates/auto/list-roles-Roles.html +++ b/resources/templates/auto/list-roles-Roles.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -45,7 +57,7 @@ name @@ -66,62 +78,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-roles-Roles'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-teams-Teams.html b/resources/templates/auto/list-teams-Teams.html index bbc027c..a353d40 100644 --- a/resources/templates/auto/list-teams-Teams.html +++ b/resources/templates/auto/list-teams-Teams.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -63,7 +75,7 @@ longitude @@ -95,62 +107,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-teams-Teams'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/auto/list-visits-Visits.html b/resources/templates/auto/list-visits-Visits.html index bdcfddb..70a4964 100644 --- a/resources/templates/auto/list-visits-Visits.html +++ b/resources/templates/auto/list-visits-Visits.html @@ -1,32 +1,44 @@ {% extends "base.html" %} - -{% block head %} - - - - - - - - - - - -{{site-title}}: {{title}} - +{% block back-links %} +
+ +
{% endblock %} - -{% block content %} -
+{% block big-links %} + + +{% endblock %} +{% block content %} + +{% csrf-field %} + + @@ -57,7 +69,7 @@ date @@ -88,62 +100,30 @@ View {% endfor %} - - - -
- +
{% endblock %} -{% block foot %} - + var form = document.getElementById('list-visits-Visits'); + var ow = document.getElementById('offset'); + var lw = document.getElementById('limit'); + form.addEventListener('submit', function() { + ow.value='0'; + }); -{% endblock %} \ No newline at end of file + {% ifunequal offset 0 %} + document.getElementById('prev-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)-parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); + {% endifunequal %} + + document.getElementById('next-selector').addEventListener('click', function () { + ow.value=(parseInt(ow.value)+parseInt(lw.value)); + console.log('Updated offset to ' + ow.value); + form.submit(); + }); +{% endblock %} diff --git a/resources/templates/base.html b/resources/templates/base.html index a219f55..93c779c 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -11,11 +11,11 @@ {{site-title}}: {{title}} {% script "js/lib/jquery/dist/jquery.min.js" %} + {% endblock %} {% block extra-head %} {% endblock %} - {% endblock %} {% block whole-page %} @@ -48,7 +48,7 @@ {% block big-links %} {% endblock %} -
+
{% block content %} @@ -81,13 +81,11 @@ {% endblock %} diff --git a/src/clj/youyesyet/db/core.clj b/src/clj/youyesyet/db/core.clj index 2158558..ccbb495 100644 --- a/src/clj/youyesyet/db/core.clj +++ b/src/clj/youyesyet/db/core.clj @@ -1,5 +1,4 @@ -(ns ^{:doc "Database access functions." - :author "Simon Brooke"} +(ns ^{:doc "Database access functions, mostly from Luminus template."} youyesyet.db.core (:require [cheshire.core :refer [generate-string parse-string]] diff --git a/src/clj/youyesyet/layout.clj b/src/clj/youyesyet/layout.clj index 060082a..2033ecf 100644 --- a/src/clj/youyesyet/layout.clj +++ b/src/clj/youyesyet/layout.clj @@ -50,7 +50,10 @@ user (do (log/debug (str "seeking roles for user " user)) - (set (map #(lower-case (:name %)) (db/list-roles-by-canvasser db/*db* user)))))) + (let [roles + (set (map #(lower-case (:name %)) (db/list-roles-by-canvasser db/*db* user)))] + (log/debug (str "found roles " roles " for user " user)) + roles)))) ;; role assignments change only rarely. @@ -58,22 +61,26 @@ (defn render - "renders the HTML template located relative to resources/templates" + "renders the HTML `template` located relative to resources/templates in + the context of this session and with these parameters." [template session & [params]] (let [user (:user session)] - (content-type - (ok + (log/debug (str "layout/render: template: '" template "'; user: '" user "'.")) + (assoc + (content-type + (ok (parser/render-file - template - (assoc params - :page template - :csrf-token *anti-forgery-token* - :user user - :user-roles (get-user-roles user) - :site-title (:site-title env) - :site-logo (:site-logo env) - :version (System/getProperty "youyesyet.version")))) - "text/html; charset=utf-8"))) + 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))) (defn error-page diff --git a/src/clj/youyesyet/middleware.clj b/src/clj/youyesyet/middleware.clj index 96414ac..fe581a2 100644 --- a/src/clj/youyesyet/middleware.clj +++ b/src/clj/youyesyet/middleware.clj @@ -1,16 +1,17 @@ (ns ^{:doc "Plumbing, mainly boilerplate from Luminus."} youyesyet.middleware - (:require [youyesyet.env :refer [defaults]] - [clojure.tools.logging :as log] - [youyesyet.layout :refer [*app-context* error-page]] + (:require [clojure.tools.logging :as log] [ring.middleware.anti-forgery :refer [wrap-anti-forgery]] - [ring.middleware.webjars :refer [wrap-webjars]] + [ring.middleware.defaults :refer [site-defaults wrap-defaults]] [ring.middleware.format :refer [wrap-restful-format]] - [youyesyet.config :refer [env]] + [ring.middleware.webjars :refer [wrap-webjars]] [ring-ttl-session.core :refer [ttl-memory-store]] - [ring.middleware.defaults :refer [site-defaults wrap-defaults]]) + [youyesyet.env :refer [defaults]] + [youyesyet.config :refer [env]] + [youyesyet.layout :refer [*app-context* error-page]]) (:import [javax.servlet ServletContext])) + (defn wrap-context [handler] (fn [request] (binding [*app-context* @@ -26,6 +27,7 @@ (:app-context env))] (handler request)))) + (defn wrap-internal-error [handler] (fn [req] (try @@ -36,6 +38,7 @@ :title "Something very bad has happened!" :message "We've dispatched a team of highly trained gnomes to take care of the problem."}))))) + (defn wrap-csrf [handler] (wrap-anti-forgery handler @@ -44,6 +47,7 @@ {:status 403 :title "Invalid anti-forgery token"})})) + (defn wrap-formats [handler] (let [wrapped (wrap-restful-format handler @@ -53,6 +57,7 @@ ;; since they're not compatible with this middleware ((if (:websocket? request) handler wrapped) request)))) + (defn wrap-base [handler] (-> ((:middleware defaults) handler) wrap-webjars diff --git a/src/clj/youyesyet/routes/auto.clj b/src/clj/youyesyet/routes/auto.clj index 4e02a3a..63860d0 100644 --- a/src/clj/youyesyet/routes/auto.clj +++ b/src/clj/youyesyet/routes/auto.clj @@ -1,9 +1,11 @@ (ns youyesyet.routes.auto - "User interface routes for Youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180630T113600.562Z" + "User interface routes for Youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180701T221533.599Z" (:require [adl-support.core :as support] [clojure.java.io :as io] + [clojure.set :refer [subset?]] + [clojure.tools.logging :as log] [compojure.core :refer [defroutes GET POST]] [hugsql.core :as hugsql] [noir.response :as nresponse] @@ -25,523 +27,1023 @@ list-addresses-Addresses [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"district_id" "postcode" "longitude" "id" "latitude" "address" + "locality" "phone"} + (keys p)) + (support/do-or-log-error + (db/search-strings-address db/*db* p) + :message + "Error while searching address records" + :error-return + {:warnings ["Error while searching address records"]}) + (support/do-or-log-error + (db/list-addresses db/*db* {}) + :message + "Error while fetching address records" + :error-return + {:warnings ["Error while fetching address records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-addresses-Addresses.html") - (:session r) - {:title "Addresses", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-address db/*db* p) - (db/list-addresses db/*db* {}))}))) + (:session 'r) + (merge {:title "Addresses", :params p} c)))) (defn form-addresses-Address [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-address db/*db* p)) + :message + "Error while fetching address record" + :error-return + {:warnings ["Error while fetching address record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :districts + (support/do-or-log-error + (db/list-districts db/*db*) + :message + "Error while fetching district record")})] (l/render (support/resolve-template "form-addresses-Address.html") - (:session r) - {:title "Address", - :params p, - :record - (if (empty? (remove nil? (vals p))) [] (db/get-address db/*db* p)), - :districts (db/list-districts db/*db*)}))) + (:session 'r) + (merge {:title "Address", :params p} c)))) (defn list-authorities-Authorities [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"authorize-uri" "request-token-uri" "access-token-uri" + "consumer-key" "id" "consumer-secret"} + (keys p)) + (support/do-or-log-error + (db/search-strings-authority db/*db* p) + :message + "Error while searching authority records" + :error-return + {:warnings ["Error while searching authority records"]}) + (support/do-or-log-error + (db/list-authorities db/*db* {}) + :message + "Error while fetching authority records" + :error-return + {:warnings ["Error while fetching authority records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-authorities-Authorities.html") - (:session r) - {:title "Authorities", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-authority db/*db* p) - (db/list-authorities db/*db* {}))}))) + (:session 'r) + (merge {:title "Authorities", :params p} c)))) (defn form-authorities-Authority [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-authority db/*db* p)) + :message + "Error while fetching authority record" + :error-return + {:warnings ["Error while fetching authority record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil)})] (l/render (support/resolve-template "form-authorities-Authority.html") - (:session r) - {:title "Authority", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-authority db/*db* p))}))) + (:session 'r) + (merge {:title "Authority", :params p} c)))) (defn list-canvassers-Canvassers [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"username" "address_id" "elector_id" "id" "email" + "authority_id" "authorised" "phone" "fullname" "roles"} + (keys p)) + (support/do-or-log-error + (db/search-strings-canvasser db/*db* p) + :message + "Error while searching canvasser records" + :error-return + {:warnings ["Error while searching canvasser records"]}) + (support/do-or-log-error + (db/list-canvassers db/*db* {}) + :message + "Error while fetching canvasser records" + :error-return + {:warnings ["Error while fetching canvasser records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-canvassers-Canvassers.html") - (:session r) - {:title "Canvassers", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-canvasser db/*db* p) - (db/list-canvassers db/*db* {}))}))) + (:session 'r) + (merge {:title "Canvassers", :params p} c)))) (defn form-canvassers-Canvasser [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-canvasser db/*db* p)) + :message + "Error while fetching canvasser record" + :error-return + {:warnings ["Error while fetching canvasser record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :electors + (support/do-or-log-error + (db/list-electors db/*db*) + :message + "Error while fetching elector record"), + :addresses + (support/do-or-log-error + (db/list-addresses db/*db*) + :message + "Error while fetching address record"), + :authorities + (support/do-or-log-error + (db/list-authorities db/*db*) + :message + "Error while fetching authority record"), + :roles + (support/do-or-log-error + (db/list-roles db/*db*) + :message + "Error while fetching role record")})] (l/render (support/resolve-template "form-canvassers-Canvasser.html") - (:session r) - {:title "Canvasser", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-canvasser db/*db* p)), - :electors (db/list-electors db/*db*), - :addresses (db/list-addresses db/*db*), - :authorities (db/list-authorities db/*db*), - :roles (db/list-roles db/*db*)}))) + (:session 'r) + (merge {:title "Canvasser", :params p} c)))) (defn list-districts-Districts [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"id" "name"} (keys p)) + (support/do-or-log-error + (db/search-strings-district db/*db* p) + :message + "Error while searching district records" + :error-return + {:warnings ["Error while searching district records"]}) + (support/do-or-log-error + (db/list-districts db/*db* {}) + :message + "Error while fetching district records" + :error-return + {:warnings ["Error while fetching district records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-districts-Districts.html") - (:session r) - {:title "Districts", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-district db/*db* p) - (db/list-districts db/*db* {}))}))) + (:session 'r) + (merge {:title "Districts", :params p} c)))) (defn form-districts-District [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-district db/*db* p)) + :message + "Error while fetching district record" + :error-return + {:warnings ["Error while fetching district record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil)})] (l/render (support/resolve-template "form-districts-District.html") - (:session r) - {:title "District", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-district db/*db* p))}))) + (:session 'r) + (merge {:title "District", :params p} c)))) (defn list-dwellings-Dwellings [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"sub-address" "address_id" "id"} (keys p)) + (support/do-or-log-error + (db/search-strings-dwelling db/*db* p) + :message + "Error while searching dwelling records" + :error-return + {:warnings ["Error while searching dwelling records"]}) + (support/do-or-log-error + (db/list-dwellings db/*db* {}) + :message + "Error while fetching dwelling records" + :error-return + {:warnings ["Error while fetching dwelling records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-dwellings-Dwellings.html") - (:session r) - {:title "Dwellings", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-dwelling db/*db* p) - (db/list-dwellings db/*db* {}))}))) + (:session 'r) + (merge {:title "Dwellings", :params p} c)))) (defn form-dwellings-Dwelling [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-dwelling db/*db* p)) + :message + "Error while fetching dwelling record" + :error-return + {:warnings ["Error while fetching dwelling record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :addresses + (support/do-or-log-error + (db/list-addresses db/*db*) + :message + "Error while fetching address record")})] (l/render (support/resolve-template "form-dwellings-Dwelling.html") - (:session r) - {:title "Dwelling", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-dwelling db/*db* p)), - :addresses (db/list-addresses db/*db*)}))) + (:session 'r) + (merge {:title "Dwelling", :params p} c)))) (defn list-electors-Electors [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"id" "gender" "email" "name" "dwelling_id" "phone"} + (keys p)) + (support/do-or-log-error + (db/search-strings-elector db/*db* p) + :message + "Error while searching elector records" + :error-return + {:warnings ["Error while searching elector records"]}) + (support/do-or-log-error + (db/list-electors db/*db* {}) + :message + "Error while fetching elector records" + :error-return + {:warnings ["Error while fetching elector records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-electors-Electors.html") - (:session r) - {:title "Electors", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-elector db/*db* p) - (db/list-electors db/*db* {}))}))) + (:session 'r) + (merge {:title "Electors", :params p} c)))) (defn form-electors-Elector [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-elector db/*db* p)) + :message + "Error while fetching elector record" + :error-return + {:warnings ["Error while fetching elector record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :dwellings + (support/do-or-log-error + (db/list-dwellings db/*db*) + :message + "Error while fetching dwelling record"), + :genders + (support/do-or-log-error + (db/list-genders db/*db*) + :message + "Error while fetching gender record")})] (l/render (support/resolve-template "form-electors-Elector.html") - (:session r) - {:title "Elector", - :params p, - :record - (if (empty? (remove nil? (vals p))) [] (db/get-elector db/*db* p)), - :dwellings (db/list-dwellings db/*db*), - :genders (db/list-genders db/*db*)}))) + (:session 'r) + (merge {:title "Elector", :params p} c)))) (defn list-followupactions-Followupactions [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"request_id" "id" "closed" "date" "notes" "actor"} + (keys p)) + (support/do-or-log-error + (db/search-strings-followupaction db/*db* p) + :message + "Error while searching followupaction records" + :error-return + {:warnings ["Error while searching followupaction records"]}) + (support/do-or-log-error + (db/list-followupactions db/*db* {}) + :message + "Error while fetching followupaction records" + :error-return + {:warnings ["Error while fetching followupaction records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-followupactions-Followupactions.html") - (:session r) - {:title "Followupactions", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-followupaction db/*db* p) - (db/list-followupactions db/*db* {}))}))) + (:session 'r) + (merge {:title "Followupactions", :params p} c)))) (defn form-followupactions-Followupaction [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if + (subset? #{"id"} #{p keys}) + (db/get-followupaction db/*db* p)) + :message + "Error while fetching followupaction record" + :error-return + {:warnings ["Error while fetching followupaction record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :followuprequests + (support/do-or-log-error + (db/list-followuprequests db/*db*) + :message + "Error while fetching followuprequest record"), + :canvassers + (support/do-or-log-error + (db/list-canvassers db/*db*) + :message + "Error while fetching canvasser record")})] (l/render (support/resolve-template "form-followupactions-Followupaction.html") - (:session r) - {:title "Followupaction", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-followupaction db/*db* p)), - :followuprequests (db/list-followuprequests db/*db*), - :canvassers (db/list-canvassers db/*db*)}))) + (:session 'r) + (merge {:title "Followupaction", :params p} c)))) (defn list-followupmethods-Followupmethods [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"id"} (keys p)) + (support/do-or-log-error + (db/search-strings-followupmethod db/*db* p) + :message + "Error while searching followupmethod records" + :error-return + {:warnings ["Error while searching followupmethod records"]}) + (support/do-or-log-error + (db/list-followupmethods db/*db* {}) + :message + "Error while fetching followupmethod records" + :error-return + {:warnings ["Error while fetching followupmethod records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-followupmethods-Followupmethods.html") - (:session r) - {:title "Followupmethods", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-followupmethod db/*db* p) - (db/list-followupmethods db/*db* {}))}))) + (:session 'r) + (merge {:title "Followupmethods", :params p} c)))) (defn form-followupmethods-Followupmethod [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if + (subset? #{"id"} #{p keys}) + (db/get-followupmethod db/*db* p)) + :message + "Error while fetching followupmethod record" + :error-return + {:warnings ["Error while fetching followupmethod record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil)})] (l/render (support/resolve-template "form-followupmethods-Followupmethod.html") - (:session r) - {:title "Followupmethod", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-followupmethod db/*db* p))}))) + (:session 'r) + (merge {:title "Followupmethod", :params p} c)))) (defn list-followuprequests-Followuprequests [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"elector_id" "id" "issue_id" "visit_id" "method_id"} + (keys p)) + (support/do-or-log-error + (db/search-strings-followuprequest db/*db* p) + :message + "Error while searching followuprequest records" + :error-return + {:warnings ["Error while searching followuprequest records"]}) + (support/do-or-log-error + (db/list-followuprequests db/*db* {}) + :message + "Error while fetching followuprequest records" + :error-return + {:warnings ["Error while fetching followuprequest records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-followuprequests-Followuprequests.html") - (:session r) - {:title "Followuprequests", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-followuprequest db/*db* p) - (db/list-followuprequests db/*db* {}))}))) + (:session 'r) + (merge {:title "Followuprequests", :params p} c)))) (defn form-followuprequests-Followuprequest [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if + (subset? #{"id"} #{p keys}) + (db/get-followuprequest db/*db* p)) + :message + "Error while fetching followuprequest record" + :error-return + {:warnings ["Error while fetching followuprequest record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :electors + (support/do-or-log-error + (db/list-electors db/*db*) + :message + "Error while fetching elector record"), + :visits + (support/do-or-log-error + (db/list-visits db/*db*) + :message + "Error while fetching visit record"), + :issues + (support/do-or-log-error + (db/list-issues db/*db*) + :message + "Error while fetching issue record"), + :followupmethods + (support/do-or-log-error + (db/list-followupmethods db/*db*) + :message + "Error while fetching followupmethod record")})] (l/render (support/resolve-template "form-followuprequests-Followuprequest.html") - (:session r) - {:title "Followuprequest", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-followuprequest db/*db* p)), - :electors (db/list-electors db/*db*), - :visits (db/list-visits db/*db*), - :issues (db/list-issues db/*db*), - :followupmethods (db/list-followupmethods db/*db*)}))) + (:session 'r) + (merge {:title "Followuprequest", :params p} c)))) (defn list-genders-Genders [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"id"} (keys p)) + (support/do-or-log-error + (db/search-strings-gender db/*db* p) + :message + "Error while searching gender records" + :error-return + {:warnings ["Error while searching gender records"]}) + (support/do-or-log-error + (db/list-genders db/*db* {}) + :message + "Error while fetching gender records" + :error-return + {:warnings ["Error while fetching gender records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-genders-Genders.html") - (:session r) - {:title "Genders", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-gender db/*db* p) - (db/list-genders db/*db* {}))}))) + (:session 'r) + (merge {:title "Genders", :params p} c)))) (defn form-genders-Gender [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-gender db/*db* p)) + :message + "Error while fetching gender record" + :error-return + {:warnings ["Error while fetching gender record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil)})] (l/render (support/resolve-template "form-genders-Gender.html") - (:session r) - {:title "Gender", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-gender db/*db* p))}))) + (:session 'r) + (merge {:title "Gender", :params p} c)))) (defn list-intentions-Intentions [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"Id"})) + c + (let + [records + (if + (some + #{"elector_id" "option_id" "locality" "visit_id" "Id"} + (keys p)) + (support/do-or-log-error + (db/search-strings-intention db/*db* p) + :message + "Error while searching intention records" + :error-return + {:warnings ["Error while searching intention records"]}) + (support/do-or-log-error + (db/list-intentions db/*db* {}) + :message + "Error while fetching intention records" + :error-return + {:warnings ["Error while fetching intention records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-intentions-Intentions.html") - (:session r) - {:title "Intentions", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-intention db/*db* p) - (db/list-intentions db/*db* {}))}))) + (:session 'r) + (merge {:title "Intentions", :params p} c)))) (defn form-intentions-Intention [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"Id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"Id"} #{p keys}) (db/get-intention db/*db* p)) + :message + "Error while fetching intention record" + :error-return + {:warnings ["Error while fetching intention record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :visits + (support/do-or-log-error + (db/list-visits db/*db*) + :message + "Error while fetching visit record"), + :electors + (support/do-or-log-error + (db/list-electors db/*db*) + :message + "Error while fetching elector record"), + :options + (support/do-or-log-error + (db/list-options db/*db*) + :message + "Error while fetching option record")})] (l/render (support/resolve-template "form-intentions-Intention.html") - (:session r) - {:title "Intention", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-intention db/*db* p)), - :visits (db/list-visits db/*db*), - :electors (db/list-electors db/*db*), - :options (db/list-options db/*db*)}))) + (:session 'r) + (merge {:title "Intention", :params p} c)))) (defn list-issues-Issues [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"url" "id" "current"} (keys p)) + (support/do-or-log-error + (db/search-strings-issue db/*db* p) + :message + "Error while searching issue records" + :error-return + {:warnings ["Error while searching issue records"]}) + (support/do-or-log-error + (db/list-issues db/*db* {}) + :message + "Error while fetching issue records" + :error-return + {:warnings ["Error while fetching issue records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-issues-Issues.html") - (:session r) - {:title "Issues", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-issue db/*db* p) - (db/list-issues db/*db* {}))}))) + (:session 'r) + (merge {:title "Issues", :params p} c)))) (defn form-issues-Issue [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-issue db/*db* p)) + :message + "Error while fetching issue record" + :error-return + {:warnings ["Error while fetching issue record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil)})] (l/render (support/resolve-template "form-issues-Issue.html") - (:session r) - {:title "Issue", - :params p, - :record - (if (empty? (remove nil? (vals p))) [] (db/get-issue db/*db* p))}))) + (:session 'r) + (merge {:title "Issue", :params p} c)))) (defn list-options-Options [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"id"} (keys p)) + (support/do-or-log-error + (db/search-strings-option db/*db* p) + :message + "Error while searching option records" + :error-return + {:warnings ["Error while searching option records"]}) + (support/do-or-log-error + (db/list-options db/*db* {}) + :message + "Error while fetching option records" + :error-return + {:warnings ["Error while fetching option records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-options-Options.html") - (:session r) - {:title "Options", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-option db/*db* p) - (db/list-options db/*db* {}))}))) + (:session 'r) + (merge {:title "Options", :params p} c)))) (defn form-options-Option [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-option db/*db* p)) + :message + "Error while fetching option record" + :error-return + {:warnings ["Error while fetching option record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil)})] (l/render (support/resolve-template "form-options-Option.html") - (:session r) - {:title "Option", - :params p, - :record - (if - (empty? (remove nil? (vals p))) - [] - (db/get-option db/*db* p))}))) + (:session 'r) + (merge {:title "Option", :params p} c)))) (defn list-roles-Roles [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"members" "id" "name"} (keys p)) + (support/do-or-log-error + (db/search-strings-role db/*db* p) + :message + "Error while searching role records" + :error-return + {:warnings ["Error while searching role records"]}) + (support/do-or-log-error + (db/list-roles db/*db* {}) + :message + "Error while fetching role records" + :error-return + {:warnings ["Error while fetching role records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-roles-Roles.html") - (:session r) - {:title "Roles", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-role db/*db* p) - (db/list-roles db/*db* {}))}))) + (:session 'r) + (merge {:title "Roles", :params p} c)))) (defn form-roles-Role [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-role db/*db* p)) + :message + "Error while fetching role record" + :error-return + {:warnings ["Error while fetching role record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :canvassers + (support/do-or-log-error + (db/list-canvassers db/*db*) + :message + "Error while fetching canvasser record")})] (l/render (support/resolve-template "form-roles-Role.html") - (:session r) - {:title "Role", - :params p, - :record - (if (empty? (remove nil? (vals p))) [] (db/get-role db/*db* p)), - :canvassers (db/list-canvassers db/*db*)}))) + (:session 'r) + (merge {:title "Role", :params p} c)))) (defn list-teams-Teams [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some + #{"organisers" "district_id" "members" "longitude" "id" + "latitude" "name"} + (keys p)) + (support/do-or-log-error + (db/search-strings-team db/*db* p) + :message + "Error while searching team records" + :error-return + {:warnings ["Error while searching team records"]}) + (support/do-or-log-error + (db/list-teams db/*db* {}) + :message + "Error while fetching team records" + :error-return + {:warnings ["Error while fetching team records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-teams-Teams.html") - (:session r) - {:title "Teams", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-team db/*db* p) - (db/list-teams db/*db* {}))}))) + (:session 'r) + (merge {:title "Teams", :params p} c)))) (defn form-teams-Team [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-team db/*db* p)) + :message + "Error while fetching team record" + :error-return + {:warnings ["Error while fetching team record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :districts + (support/do-or-log-error + (db/list-districts db/*db*) + :message + "Error while fetching district record"), + :canvassers + (support/do-or-log-error + (db/list-canvassers db/*db*) + :message + "Error while fetching canvasser record")})] (l/render (support/resolve-template "form-teams-Team.html") - (:session r) - {:title "Team", - :params p, - :record - (if (empty? (remove nil? (vals p))) [] (db/get-team db/*db* p)), - :districts (db/list-districts db/*db*), - :canvassers (db/list-canvassers db/*db*)}))) + (:session 'r) + (merge {:title "Team", :params p} c)))) (defn list-visits-Visits [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [records + (if + (some #{"address_id" "id" "canvasser_id" "date"} (keys p)) + (support/do-or-log-error + (db/search-strings-visit db/*db* p) + :message + "Error while searching visit records" + :error-return + {:warnings ["Error while searching visit records"]}) + (support/do-or-log-error + (db/list-visits db/*db* {}) + :message + "Error while fetching visit records" + :error-return + {:warnings ["Error while fetching visit records"]}))] + (if (:warnings records) records {:records records}))] (l/render (support/resolve-template "list-visits-Visits.html") - (:session r) - {:title "Visits", - :params p, - :records - (if - (not (empty? (remove nil? (vals p)))) - (db/search-strings-visit db/*db* p) - (db/list-visits db/*db* {}))}))) + (:session 'r) + (merge {:title "Visits", :params p} c)))) (defn form-visits-Visit [r] (let - [p (support/massage-params (:params r))] + [p + (merge + {:offset 0, :limit 25} + (support/massage-params (:params r) (:form-params r) #{"id"})) + c + (let + [record + (support/do-or-log-error + (if (subset? #{"id"} #{p keys}) (db/get-visit db/*db* p)) + :message + "Error while fetching visit record" + :error-return + {:warnings ["Error while fetching visit record"]})] + {:warnings (:warnings record), + :record (assoc record :warnings nil), + :addresses + (support/do-or-log-error + (db/list-addresses db/*db*) + :message + "Error while fetching address record"), + :canvassers + (support/do-or-log-error + (db/list-canvassers db/*db*) + :message + "Error while fetching canvasser record")})] (l/render (support/resolve-template "form-visits-Visit.html") - (:session r) - {:title "Visit", - :params p, - :record - (if (empty? (remove nil? (vals p))) [] (db/get-visit db/*db* p)), - :addresses (db/list-addresses db/*db*), - :canvassers (db/list-canvassers db/*db*)}))) + (:session 'r) + (merge {:title "Visit", :params p} c)))) (defn raw-resolve-handler diff --git a/src/clj/youyesyet/routes/auto_json.clj b/src/clj/youyesyet/routes/auto_json.clj index cccc570..9c7234b 100644 --- a/src/clj/youyesyet/routes/auto_json.clj +++ b/src/clj/youyesyet/routes/auto_json.clj @@ -1,10 +1,11 @@ (ns youyesyet.routes.auto-json - "JSON routes for youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180630T113559.533Z" + "JSON routes for youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180701T221528.540Z" (:require [adl-support.core :as support] - [clojure.java.io :as io] [clojure.core.memoize :as memo] + [clojure.java.io :as io] + [clojure.tools.logging :as log] [compojure.core :refer [defroutes GET POST]] [hugsql.core :as hugsql] [noir.response :as nresponse] @@ -16,228 +17,629 @@ create-address! "Auto-generated method to insert one record to the `addresses` table. Expects the following key(s) to be present in `params`: `(:address :postcode :phone :district_id :latitude :longitude :locality)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-address! params))) + (do + (log/debug + (str + "Calling query '" + "create-address!" + "' with params " + (map + (fn + [p] + (if + (#{"postcode" "address"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/create-address! params))) (defn create-authority! "Auto-generated method to insert one record to the `authorities` table. Expects the following key(s) to be present in `params`: `(:request-token-uri :access-token-uri :authorize-uri :consumer-key :consumer-secret :id)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-authority! params))) + (do + (log/debug + (str + "Calling query '" + "create-authority!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-authority! params))) (defn create-canvasser! "Auto-generated method to insert one record to the `canvassers` table. Expects the following key(s) to be present in `params`: `(:username :fullname :elector_id :address_id :phone :email :authority_id :authorised)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-canvasser! params))) + (do + (log/debug + (str + "Calling query '" + "create-canvasser!" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/create-canvasser! params))) (defn create-district! "Auto-generated method to insert one record to the `districts` table. Expects the following key(s) to be present in `params`: `(:name)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-district! params))) + (do + (log/debug + (str + "Calling query '" + "create-district!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-district! params))) (defn create-dwelling! "Auto-generated method to insert one record to the `dwellings` table. Expects the following key(s) to be present in `params`: `(:address_id :sub-address)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-dwelling! params))) + (do + (log/debug + (str + "Calling query '" + "create-dwelling!" + "' with params " + (map + (fn + [p] + (if + (#{"sub-address" "address_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/create-dwelling! params))) (defn create-elector! "Auto-generated method to insert one record to the `electors` table. Expects the following key(s) to be present in `params`: `(:name :dwelling_id :phone :email :gender)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-elector! params))) + (do + (log/debug + (str + "Calling query '" + "create-elector!" + "' with params " + (map + (fn + [p] + (if + (#{"gender" "email" "name" "phone"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/create-elector! params))) (defn create-followupaction! "Auto-generated method to insert one record to the `followupactions` table. Expects the following key(s) to be present in `params`: `(:request_id :actor :date :notes :closed)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-followupaction! params))) + (do + (log/debug + (str + "Calling query '" + "create-followupaction!" + "' with params " + (map + (fn + [p] + (if (#{"date" "notes"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-followupaction! params))) (defn create-followupmethod! "Auto-generated method to insert one record to the `followupmethods` table. Expects the following key(s) to be present in `params`: `(:id)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-followupmethod! params))) + (do + (log/debug + (str + "Calling query '" + "create-followupmethod!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-followupmethod! params))) (defn create-followuprequest! "Auto-generated method to insert one record to the `followuprequests` table. Expects the following key(s) to be present in `params`: `(:elector_id :visit_id :issue_id :method_id)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-followuprequest! params))) + (do + (log/debug + (str + "Calling query '" + "create-followuprequest!" + "' with params " + (map + (fn + [p] + (if + (#{"elector_id" "issue_id" "visit_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/create-followuprequest! params))) (defn create-gender! "Auto-generated method to insert one record to the `genders` table. Expects the following key(s) to be present in `params`: `(:id)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-gender! params))) + (do + (log/debug + (str + "Calling query '" + "create-gender!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-gender! params))) (defn create-intention! "Auto-generated method to insert one record to the `intentions` table. Expects the following key(s) to be present in `params`: `(:visit_id :elector_id :option_id :locality)`. Returns a map containing the keys `#{\"Id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-intention! params))) + (do + (log/debug + (str + "Calling query '" + "create-intention!" + "' with params " + (map + (fn [p] (if (#{} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-intention! params))) (defn create-issue! "Auto-generated method to insert one record to the `issues` table. Expects the following key(s) to be present in `params`: `(:url :current :id)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-issue! params))) + (do + (log/debug + (str + "Calling query '" + "create-issue!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-issue! params))) (defn create-option! "Auto-generated method to insert one record to the `options` table. Expects the following key(s) to be present in `params`: `(:id)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-option! params))) + (do + (log/debug + (str + "Calling query '" + "create-option!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-option! params))) (defn create-role! "Auto-generated method to insert one record to the `roles` table. Expects the following key(s) to be present in `params`: `(:name)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-role! params))) + (do + (log/debug + (str + "Calling query '" + "create-role!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-role! params))) (defn create-team! "Auto-generated method to insert one record to the `teams` table. Expects the following key(s) to be present in `params`: `(:name :district_id :latitude :longitude)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-team! params))) + (do + (log/debug + (str + "Calling query '" + "create-team!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/create-team! params))) (defn create-visit! "Auto-generated method to insert one record to the `visits` table. Expects the following key(s) to be present in `params`: `(:address_id :canvasser_id :date)`. Returns a map containing the keys `#{\"id\"}` identifying the record created." [{:keys [params]}] - (do (db/create-visit! params))) + (do + (log/debug + (str + "Calling query '" + "create-visit!" + "' with params " + (map + (fn + [p] + (if + (#{"address_id" "date"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/create-visit! params))) (defn delete-address! "Auto-generated method to delete one record from the `addresses` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-address! params)) + (do + (log/debug + (str + "Calling query '" + "delete-address!" + "' with params " + (map + (fn + [p] + (if + (#{"postcode" "address"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/delete-address! params)) (response/found "/")) (defn delete-authority! "Auto-generated method to delete one record from the `authorities` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-authority! params)) + (do + (log/debug + (str + "Calling query '" + "delete-authority!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-authority! params)) (response/found "/")) (defn delete-canvasser! "Auto-generated method to delete one record from the `canvassers` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-canvasser! params)) + (do + (log/debug + (str + "Calling query '" + "delete-canvasser!" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/delete-canvasser! params)) (response/found "/")) (defn delete-district! "Auto-generated method to delete one record from the `districts` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-district! params)) + (do + (log/debug + (str + "Calling query '" + "delete-district!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-district! params)) (response/found "/")) (defn delete-dwelling! "Auto-generated method to delete one record from the `dwellings` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-dwelling! params)) + (do + (log/debug + (str + "Calling query '" + "delete-dwelling!" + "' with params " + (map + (fn + [p] + (if + (#{"sub-address" "address_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/delete-dwelling! params)) (response/found "/")) (defn delete-elector! "Auto-generated method to delete one record from the `electors` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-elector! params)) + (do + (log/debug + (str + "Calling query '" + "delete-elector!" + "' with params " + (map + (fn + [p] + (if + (#{"gender" "email" "name" "phone"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/delete-elector! params)) (response/found "/")) (defn delete-followupaction! "Auto-generated method to delete one record from the `followupactions` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-followupaction! params)) + (do + (log/debug + (str + "Calling query '" + "delete-followupaction!" + "' with params " + (map + (fn + [p] + (if (#{"date" "notes"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-followupaction! params)) (response/found "/")) (defn delete-followupmethod! "Auto-generated method to delete one record from the `followupmethods` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-followupmethod! params)) + (do + (log/debug + (str + "Calling query '" + "delete-followupmethod!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-followupmethod! params)) (response/found "/")) (defn delete-followuprequest! "Auto-generated method to delete one record from the `followuprequests` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-followuprequest! params)) + (do + (log/debug + (str + "Calling query '" + "delete-followuprequest!" + "' with params " + (map + (fn + [p] + (if + (#{"elector_id" "issue_id" "visit_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/delete-followuprequest! params)) (response/found "/")) (defn delete-gender! "Auto-generated method to delete one record from the `genders` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-gender! params)) + (do + (log/debug + (str + "Calling query '" + "delete-gender!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-gender! params)) (response/found "/")) (defn delete-intention! "Auto-generated method to delete one record from the `intentions` table. Expects the following key(s) to be present in `params`: `#{\"Id\"}`." [{:keys [params]}] - (do (db/delete-intention! params)) + (do + (log/debug + (str + "Calling query '" + "delete-intention!" + "' with params " + (map + (fn [p] (if (#{} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-intention! params)) (response/found "/")) (defn delete-issue! "Auto-generated method to delete one record from the `issues` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-issue! params)) + (do + (log/debug + (str + "Calling query '" + "delete-issue!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-issue! params)) (response/found "/")) (defn delete-option! "Auto-generated method to delete one record from the `options` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-option! params)) + (do + (log/debug + (str + "Calling query '" + "delete-option!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-option! params)) (response/found "/")) (defn delete-role! "Auto-generated method to delete one record from the `roles` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-role! params)) + (do + (log/debug + (str + "Calling query '" + "delete-role!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-role! params)) (response/found "/")) (defn delete-team! "Auto-generated method to delete one record from the `teams` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-team! params)) + (do + (log/debug + (str + "Calling query '" + "delete-team!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/delete-team! params)) (response/found "/")) (defn delete-visit! "Auto-generated method to delete one record from the `visits` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`." [{:keys [params]}] - (do (db/delete-visit! params)) + (do + (log/debug + (str + "Calling query '" + "delete-visit!" + "' with params " + (map + (fn + [p] + (if + (#{"address_id" "date"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/delete-visit! params)) (response/found "/")) (def get-address (memo/ttl - (fn [{:keys [params]}] (do (db/get-address params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-address" + "' with params " + (map + (fn + [p] + (if + (#{"postcode" "address"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-address params)) + nil) :ttl/threshold 1000000000)) (def get-authority (memo/ttl - (fn [{:keys [params]}] (do (db/get-authority params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-authority" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-authority params)) + nil) :ttl/threshold 10000000000)) (def get-canvasser (memo/ttl - (fn [{:keys [params]}] (do (db/get-canvasser params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-canvasser" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-canvasser params)) + nil) :ttl/threshold 10000000)) @@ -246,7 +648,22 @@ (memo/ttl (fn [{:keys [params]}] - (do (db/get-canvasser-by-username params)) + (do + (log/debug + (str + "Calling query '" + "get-canvasser-by-username" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-canvasser-by-username params)) nil) :ttl/threshold 10000000)) @@ -254,21 +671,67 @@ (def get-district (memo/ttl - (fn [{:keys [params]}] (do (db/get-district params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-district" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-district params)) + nil) :ttl/threshold 10000000000)) (def get-dwelling (memo/ttl - (fn [{:keys [params]}] (do (db/get-dwelling params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-dwelling" + "' with params " + (map + (fn + [p] + (if + (#{"sub-address" "address_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-dwelling params)) + nil) :ttl/threshold 1000000000)) (def get-elector (memo/ttl - (fn [{:keys [params]}] (do (db/get-elector params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-elector" + "' with params " + (map + (fn + [p] + (if + (#{"gender" "email" "name" "phone"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-elector params)) + nil) :ttl/threshold 100000000)) @@ -276,81 +739,240 @@ get-followupaction "Auto-generated method to select one record from the `followupactions` table. Expects the following key(s) to be present in `params`: `#{\"id\"}`. Returns a map containing the following keys: `clojure.lang.LazySeq@6b32af0e`." [{:keys [params]}] - (do (db/get-followupaction params))) + (do + (log/debug + (str + "Calling query '" + "get-followupaction" + "' with params " + (map + (fn + [p] + (if (#{"date" "notes"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-followupaction params))) (def get-followupmethod (memo/ttl - (fn [{:keys [params]}] (do (db/get-followupmethod params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-followupmethod" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-followupmethod params)) + nil) :ttl/threshold 10000000000)) (def get-followuprequest (memo/ttl - (fn [{:keys [params]}] (do (db/get-followuprequest params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-followuprequest" + "' with params " + (map + (fn + [p] + (if + (#{"elector_id" "issue_id" "visit_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-followuprequest params)) + nil) :ttl/threshold 100000)) (def get-gender (memo/ttl - (fn [{:keys [params]}] (do (db/get-gender params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-gender" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-gender params)) + nil) :ttl/threshold 1000000000)) -(defn +(def get-intention - "Auto-generated method to select one record from the `intentions` table. Expects the following key(s) to be present in `params`: `#{\"Id\"}`. Returns a map containing the following keys: `clojure.lang.LazySeq@27b20cd9`." - [{:keys [params]}] - (do (db/get-intention params))) + (memo/ttl + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-intention" + "' with params " + (map + (fn [p] (if (#{} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-intention params)) + nil) + :ttl/threshold + 100000)) (def get-issue (memo/ttl - (fn [{:keys [params]}] (do (db/get-issue params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-issue" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-issue params)) + nil) :ttl/threshold 1000000)) (def get-option (memo/ttl - (fn [{:keys [params]}] (do (db/get-option params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-option" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-option params)) + nil) :ttl/threshold 10000000000)) (def get-role (memo/ttl - (fn [{:keys [params]}] (do (db/get-role params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-role" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-role params)) + nil) :ttl/threshold 10000000000)) (def get-role-by-name (memo/ttl - (fn [{:keys [params]}] (do (db/get-role-by-name params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-role-by-name" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-role-by-name params)) + nil) :ttl/threshold 10000000000)) (def get-team (memo/ttl - (fn [{:keys [params]}] (do (db/get-team params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-team" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/get-team params)) + nil) :ttl/threshold 10000000)) (def get-visit (memo/ttl - (fn [{:keys [params]}] (do (db/get-visit params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "get-visit" + "' with params " + (map + (fn + [p] + (if + (#{"address_id" "date"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/get-visit params)) + nil) :ttl/threshold 100000)) (def list-addresses (memo/ttl - (fn [{:keys [params]}] (do (db/list-addresses params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-addresses" + "' with params " + (map + (fn + [p] + (if + (#{"postcode" "address"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/list-addresses params)) + nil) :ttl/threshold 1000000000)) @@ -362,14 +984,44 @@ (def list-authorities (memo/ttl - (fn [{:keys [params]}] (do (db/list-authorities params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-authorities" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-authorities params)) + nil) :ttl/threshold 10000000000)) (def list-canvassers (memo/ttl - (fn [{:keys [params]}] (do (db/list-canvassers params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-canvassers" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/list-canvassers params)) + nil) :ttl/threshold 10000000)) @@ -396,14 +1048,43 @@ (def list-districts (memo/ttl - (fn [{:keys [params]}] (do (db/list-districts params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-districts" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-districts params)) + nil) :ttl/threshold 10000000000)) (def list-dwellings (memo/ttl - (fn [{:keys [params]}] (do (db/list-dwellings params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-dwellings" + "' with params " + (map + (fn + [p] + (if + (#{"sub-address" "address_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/list-dwellings params)) + nil) :ttl/threshold 1000000000)) @@ -415,7 +1096,24 @@ (def list-electors (memo/ttl - (fn [{:keys [params]}] (do (db/list-electors params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-electors" + "' with params " + (map + (fn + [p] + (if + (#{"gender" "email" "name" "phone"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/list-electors params)) + nil) :ttl/threshold 100000000)) @@ -433,7 +1131,18 @@ list-followupactions "Auto-generated method to select all records from the `followupactions` table. If the keys `(:limit :offset)` are present in the request then they will be used to page through the data. Returns a sequence of maps each containing the following keys: `(:request_id :actor :date :notes :closed :id)`." [{:keys [params]}] - (do (db/list-followupactions params))) + (do + (log/debug + (str + "Calling query '" + "list-followupactions" + "' with params " + (map + (fn + [p] + (if (#{"date" "notes"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-followupactions params))) (defn list-followupactions-by-canvasser @@ -448,14 +1157,43 @@ (def list-followupmethods (memo/ttl - (fn [{:keys [params]}] (do (db/list-followupmethods params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-followupmethods" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-followupmethods params)) + nil) :ttl/threshold 10000000000)) (def list-followuprequests (memo/ttl - (fn [{:keys [params]}] (do (db/list-followuprequests params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-followuprequests" + "' with params " + (map + (fn + [p] + (if + (#{"elector_id" "issue_id" "visit_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/list-followuprequests params)) + nil) :ttl/threshold 100000)) @@ -482,15 +1220,40 @@ (def list-genders (memo/ttl - (fn [{:keys [params]}] (do (db/list-genders params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-genders" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-genders params)) + nil) :ttl/threshold 1000000000)) -(defn +(def list-intentions - "Auto-generated method to select all records from the `intentions` table. If the keys `(:limit :offset)` are present in the request then they will be used to page through the data. Returns a sequence of maps each containing the following keys: `(:visit_id :elector_id :option_id :locality :Id)`." - [{:keys [params]}] - (do (db/list-intentions params))) + (memo/ttl + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-intentions" + "' with params " + (map + (fn [p] (if (#{} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-intentions params)) + nil) + :ttl/threshold + 100000)) (defn list-intentions-by-elector @@ -510,21 +1273,57 @@ (def list-issues (memo/ttl - (fn [{:keys [params]}] (do (db/list-issues params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-issues" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-issues params)) + nil) :ttl/threshold 1000000)) (def list-options (memo/ttl - (fn [{:keys [params]}] (do (db/list-options params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-options" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-options params)) + nil) :ttl/threshold 10000000000)) (def list-roles (memo/ttl - (fn [{:keys [params]}] (do (db/list-roles params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-roles" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-roles params)) + nil) :ttl/threshold 10000000000)) @@ -536,7 +1335,19 @@ (def list-teams (memo/ttl - (fn [{:keys [params]}] (do (db/list-teams params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-teams" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/list-teams params)) + nil) :ttl/threshold 10000000)) @@ -553,7 +1364,24 @@ (def list-visits (memo/ttl - (fn [{:keys [params]}] (do (db/list-visits params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "list-visits" + "' with params " + (map + (fn + [p] + (if + (#{"address_id" "date"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/list-visits params)) + nil) :ttl/threshold 100000)) @@ -570,42 +1398,135 @@ (def search-strings-address (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-address params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-address" + "' with params " + (map + (fn + [p] + (if + (#{"postcode" "address"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/search-strings-address params)) + nil) :ttl/threshold 1000000000)) (def search-strings-authority (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-authority params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-authority" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-authority params)) + nil) :ttl/threshold 10000000000)) (def search-strings-canvasser (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-canvasser params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-canvasser" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/search-strings-canvasser params)) + nil) :ttl/threshold 10000000)) (def search-strings-district (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-district params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-district" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-district params)) + nil) :ttl/threshold 10000000000)) (def search-strings-dwelling (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-dwelling params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-dwelling" + "' with params " + (map + (fn + [p] + (if + (#{"sub-address" "address_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/search-strings-dwelling params)) + nil) :ttl/threshold 1000000000)) (def search-strings-elector (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-elector params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-elector" + "' with params " + (map + (fn + [p] + (if + (#{"gender" "email" "name" "phone"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/search-strings-elector params)) + nil) :ttl/threshold 100000000)) @@ -613,14 +1534,34 @@ search-strings-followupaction "Auto-generated method to select all records from the `followupactions` table with any text field matching the value of the key `:pattern` which should be in the request. If the keys `(:limit :offset)` are present in the request then they will be used to page through the data. Returns a sequence of maps each containing the following keys: `(:request_id :actor :date :notes :closed :id)`." [{:keys [params]}] - (do (db/search-strings-followupaction params))) + (do + (log/debug + (str + "Calling query '" + "search-strings-followupaction" + "' with params " + (map + (fn + [p] + (if (#{"date" "notes"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-followupaction params))) (def search-strings-followupmethod (memo/ttl (fn [{:keys [params]}] - (do (db/search-strings-followupmethod params)) + (do + (log/debug + (str + "Calling query '" + "search-strings-followupmethod" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-followupmethod params)) nil) :ttl/threshold 10000000000)) @@ -630,7 +1571,21 @@ (memo/ttl (fn [{:keys [params]}] - (do (db/search-strings-followuprequest params)) + (do + (log/debug + (str + "Calling query '" + "search-strings-followuprequest" + "' with params " + (map + (fn + [p] + (if + (#{"elector_id" "issue_id" "visit_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/search-strings-followuprequest params)) nil) :ttl/threshold 100000)) @@ -638,48 +1593,138 @@ (def search-strings-gender (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-gender params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-gender" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-gender params)) + nil) :ttl/threshold 1000000000)) -(defn +(def search-strings-intention - "Auto-generated method to select all records from the `intentions` table with any text field matching the value of the key `:pattern` which should be in the request. If the keys `(:limit :offset)` are present in the request then they will be used to page through the data. Returns a sequence of maps each containing the following keys: `(:visit_id :elector_id :option_id :locality :Id)`." - [{:keys [params]}] - (do (db/search-strings-intention params))) + (memo/ttl + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-intention" + "' with params " + (map + (fn [p] (if (#{} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-intention params)) + nil) + :ttl/threshold + 100000)) (def search-strings-issue (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-issue params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-issue" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-issue params)) + nil) :ttl/threshold 1000000)) (def search-strings-option (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-option params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-option" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-option params)) + nil) :ttl/threshold 10000000000)) (def search-strings-role (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-role params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-role" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-role params)) + nil) :ttl/threshold 10000000000)) (def search-strings-team (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-team params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-team" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/search-strings-team params)) + nil) :ttl/threshold 10000000)) (def search-strings-visit (memo/ttl - (fn [{:keys [params]}] (do (db/search-strings-visit params)) nil) + (fn + [{:keys [params]}] + (do + (log/debug + (str + "Calling query '" + "search-strings-visit" + "' with params " + (map + (fn + [p] + (if + (#{"address_id" "date"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/search-strings-visit params)) + nil) :ttl/threshold 100000)) @@ -687,91 +1732,241 @@ update-address! "Auto-generated method to update one record in the `addresses` table. Expects the following key(s) to be present in `params`: `(:address :district_id :id :latitude :locality :longitude :phone :postcode)`." [{:keys [params]}] - (do (db/update-address! params)) + (do + (log/debug + (str + "Calling query '" + "update-address!" + "' with params " + (map + (fn + [p] + (if + (#{"postcode" "address"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/update-address! params)) (response/found "/")) (defn update-authority! "Auto-generated method to update one record in the `authorities` table. Expects the following key(s) to be present in `params`: `(:access-token-uri :authorize-uri :consumer-key :consumer-secret :id :request-token-uri)`." [{:keys [params]}] - (do (db/update-authority! params)) + (do + (log/debug + (str + "Calling query '" + "update-authority!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-authority! params)) (response/found "/")) (defn update-canvasser! "Auto-generated method to update one record in the `canvassers` table. Expects the following key(s) to be present in `params`: `(:address_id :authorised :authority_id :elector_id :email :fullname :id :phone :username)`." [{:keys [params]}] - (do (db/update-canvasser! params)) + (do + (log/debug + (str + "Calling query '" + "update-canvasser!" + "' with params " + (map + (fn + [p] + (if + (#{"username" "address_id" "email" "phone" "fullname"} + (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/update-canvasser! params)) (response/found "/")) (defn update-district! "Auto-generated method to update one record in the `districts` table. Expects the following key(s) to be present in `params`: `(:id :name)`." [{:keys [params]}] - (do (db/update-district! params)) + (do + (log/debug + (str + "Calling query '" + "update-district!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-district! params)) (response/found "/")) (defn update-dwelling! "Auto-generated method to update one record in the `dwellings` table. Expects the following key(s) to be present in `params`: `(:address_id :id :sub-address)`." [{:keys [params]}] - (do (db/update-dwelling! params)) + (do + (log/debug + (str + "Calling query '" + "update-dwelling!" + "' with params " + (map + (fn + [p] + (if + (#{"sub-address" "address_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/update-dwelling! params)) (response/found "/")) (defn update-elector! "Auto-generated method to update one record in the `electors` table. Expects the following key(s) to be present in `params`: `(:dwelling_id :email :gender :id :name :phone)`." [{:keys [params]}] - (do (db/update-elector! params)) + (do + (log/debug + (str + "Calling query '" + "update-elector!" + "' with params " + (map + (fn + [p] + (if + (#{"gender" "email" "name" "phone"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/update-elector! params)) (response/found "/")) (defn update-followupaction! "Auto-generated method to update one record in the `followupactions` table. Expects the following key(s) to be present in `params`: `(:actor :closed :date :id :notes :request_id)`." [{:keys [params]}] - (do (db/update-followupaction! params)) + (do + (log/debug + (str + "Calling query '" + "update-followupaction!" + "' with params " + (map + (fn + [p] + (if (#{"date" "notes"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-followupaction! params)) (response/found "/")) (defn update-followuprequest! "Auto-generated method to update one record in the `followuprequests` table. Expects the following key(s) to be present in `params`: `(:elector_id :id :issue_id :method_id :visit_id)`." [{:keys [params]}] - (do (db/update-followuprequest! params)) + (do + (log/debug + (str + "Calling query '" + "update-followuprequest!" + "' with params " + (map + (fn + [p] + (if + (#{"elector_id" "issue_id" "visit_id"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/update-followuprequest! params)) (response/found "/")) (defn update-intention! "Auto-generated method to update one record in the `intentions` table. Expects the following key(s) to be present in `params`: `(:Id :elector_id :locality :option_id :visit_id)`." [{:keys [params]}] - (do (db/update-intention! params)) + (do + (log/debug + (str + "Calling query '" + "update-intention!" + "' with params " + (map + (fn [p] (if (#{} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-intention! params)) (response/found "/")) (defn update-issue! "Auto-generated method to update one record in the `issues` table. Expects the following key(s) to be present in `params`: `(:current :id :url)`." [{:keys [params]}] - (do (db/update-issue! params)) + (do + (log/debug + (str + "Calling query '" + "update-issue!" + "' with params " + (map + (fn [p] (if (#{"id"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-issue! params)) (response/found "/")) (defn update-role! "Auto-generated method to update one record in the `roles` table. Expects the following key(s) to be present in `params`: `(:id :name)`." [{:keys [params]}] - (do (db/update-role! params)) + (do + (log/debug + (str + "Calling query '" + "update-role!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-role! params)) (response/found "/")) (defn update-team! "Auto-generated method to update one record in the `teams` table. Expects the following key(s) to be present in `params`: `(:district_id :id :latitude :longitude :name)`." [{:keys [params]}] - (do (db/update-team! params)) + (do + (log/debug + (str + "Calling query '" + "update-team!" + "' with params " + (map + (fn [p] (if (#{"name"} (str (name p))) (params p) "[ELIDED]")) + (keys params)))) + (db/update-team! params)) (response/found "/")) (defn update-visit! "Auto-generated method to update one record in the `visits` table. Expects the following key(s) to be present in `params`: `(:address_id :canvasser_id :date :id)`." [{:keys [params]}] - (do (db/update-visit! params)) + (do + (log/debug + (str + "Calling query '" + "update-visit!" + "' with params " + (map + (fn + [p] + (if + (#{"address_id" "date"} (str (name p))) + (params p) + "[ELIDED]")) + (keys params)))) + (db/update-visit! params)) (response/found "/")) (defroutes diff --git a/src/clj/youyesyet/routes/home.clj b/src/clj/youyesyet/routes/home.clj index 86b2729..bcd418b 100644 --- a/src/clj/youyesyet/routes/home.clj +++ b/src/clj/youyesyet/routes/home.clj @@ -1,17 +1,16 @@ (ns ^{:doc "Routes/pages available to unauthenticated users." :author "Simon Brooke"} youyesyet.routes.home (:require [clojure.java.io :as io] + [clojure.string :as s] [clojure.tools.logging :as log] [clojure.walk :refer [keywordize-keys]] - [noir.response :as nresponse] [noir.util.route :as route] - [ring.util.http-response :refer [content-type ok]] + [ring.util.http-response :as response] [youyesyet.config :refer [env]] [youyesyet.db.core :as db-core] [youyesyet.layout :as layout] [youyesyet.oauth :as oauth] [compojure.core :refer [defroutes GET POST]] - [ring.util.http-response :as response] )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -63,13 +62,13 @@ user (:user session) roles (if user (db-core/list-roles-by-canvasser db-core/*db* {:id (:id user)}))] (cond - roles (layout/render "roles.html" - (:session request) - {:title (str "Welcome " (:fullname user) ", what do you want to do?") - :user user - :roles roles}) - (empty? roles)(response/found "/app") - true (assoc (response/found "/login") :session (dissoc session :user))))) + roles (layout/render "roles.html" + (:session request) + {:title (str "Welcome " (:fullname user) ", what do you want to do?") + :user user + :roles roles}) + (empty? roles)(response/found "/app") + true (assoc (response/found "/login") :session (dissoc session :user))))) (defn home-page [] @@ -86,42 +85,47 @@ password (:password params) redirect-to (or (:redirect-to params) "roles")] (cond - (:authority params) - (let [auth (oauth/authority! (:authority params))] - (if auth - (do - (log/info "Attempting to authorise with authority " (:authority params)) - (oauth/fetch-request-token - (assoc request :session (assoc session :authority auth)) - auth)) - (throw (Exception. (str "No such authority: " (:authority params)))))) - ;; this is obviously, ABSURDLY, insecure. I don't want to put just-about-good-enough, - ;; it-will-do-for-now security in place; instead, I want this to be test code only - ;; until we have o-auth properly working. - (and user (= username password)) - (assoc - (response/found redirect-to) - :session (assoc session :user user :roles (layout/get-user-roles user))) - username + (:authority params) + (let [auth (oauth/authority! (:authority params))] + (if auth + (do + (log/info "Attempting to authorise with authority " (:authority params)) + (oauth/fetch-request-token + (assoc request :session (assoc session :authority auth)) + auth)) + (throw (Exception. (str "No such authority: " (:authority params)))))) + ;; this is obviously, ABSURDLY, insecure. I don't want to put just-about-good-enough, + ;; it-will-do-for-now security in place; instead, I want this to be test code only + ;; until we have o-auth properly working. + (and user (= username password)) + (let + [roles (layout/get-user-roles user)] + (log/info (str "Logged in user '" username "' with roles " roles)) + (assoc + (response/found redirect-to) + :session + (assoc session :user user :roles roles))) + ;; if we've got a username but either no user object or else + ;; the password doesn't match + username (layout/render - "login.html" - session - {:title (str "User " username " is unknown") :redirect-to redirect-to}) - true + "login.html" + session + {:title (str "User " username " is unknown") + :redirect-to redirect-to + :warnings ["Your user name was not recognised or your password did not match"]}) + ;; if we've no username, just invite the user to log in + true (layout/render - "login.html" - session - {:title "Please log in" - :redirect-to redirect-to - :authorities (db-core/list-authorities db-core/*db*)})))) + "login.html" + session + {:title "Please log in" + :redirect-to redirect-to + :authorities (db-core/list-authorities db-core/*db*)})))) (defroutes home-routes (GET "/" [] (home-page)) -;; (GET "/js/:file" [file] -;; (-> (io/input-stream (str "resources/public/js/" file)) -;; ok -;; (content-type "text/javascript;charset=UTF-8"))) (GET "/home" [] (home-page)) (GET "/about" [] (about-page)) (GET "/roles" request (route/restricted (roles-page request))) diff --git a/youyesyet.adl.xml b/youyesyet.adl.xml index d542d6f..ac62804 100644 --- a/youyesyet.adl.xml +++ b/youyesyet.adl.xml @@ -12,37 +12,6 @@ There must also be an administrative interface through which privileged users can set the system up and authorise canvassers, and a 'followup' interface through which issue-expert specialist canvassers can address particular electors' queries. - - - - - - - - - {{site-title}}: {{title}} - - - - - - - See diff --git a/youyesyet.canonical.adl.xml b/youyesyet.canonical.adl.xml index 1034995..60c7984 100644 --- a/youyesyet.canonical.adl.xml +++ b/youyesyet.canonical.adl.xml @@ -21,36 +21,6 @@ There must also be an administrative interface through which privileged users can set the system up and authorise canvassers, and a 'followup' interface through which issue-expert specialist canvassers can address particular electors' queries. - - - - - - - - - {{site-title}}: {{title}} - - - - - - See https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/488478/Bulk_Data_Transfer_-_additional_validation_valid_from_12_November_2015.pdf, @@ -102,7 +72,7 @@ - + @@ -113,8 +83,8 @@ - -
+ +
@@ -332,7 +302,7 @@ - + Intentions of electors to vote for options elicited in visits. From 16af0405375e99b4083296f04a9932fab4b553af Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 2 Jul 2018 16:22:38 +0100 Subject: [PATCH 082/180] Tactical commit while I try to understand why the app doesn't rebuild --- env/dev/clj/youyesyet/core.clj | 9 +- package-lock.json | 11 + project.clj | 35 +- .../20161014170335-basic-setup.down.sql | 50 -- .../20161014170335-basic-setup.up.sql | 669 ------------------ .../20170315190500-roles-and-teams.down.sql | 13 - .../20170315190500-roles-and-teams.up.sql | 39 - ...170401115900-basic-reference-data.down.sql | 17 - ...20170401115900-basic-reference-data.up.sql | 58 -- .../20170415102900-core-views.down.sql | 11 - .../20170415102900-core-views.up.sql | 59 -- .../20170721084900-dwellings.down.sql | 69 -- .../20170721084900-dwellings.up.sql | 87 --- ...0316110100-intentions-and-options.down.sql | 24 - ...180316110100-intentions-and-options.up.sql | 30 - .../migrations/20180317170000-gender.down.sql | 3 - .../migrations/20180317170000-gender.up.sql | 11 - .../20180317170907-reference-data.down.sql | 10 - .../20180317170907-reference-data.up.sql | 18 - .../20180317175047-test-data.down.sql | 3 - .../20180317175047-test-data.up.sql | 41 -- .../20180408124500-reference-data.down.sql | 1 - .../20180408124500-reference-data.up.sql | 2 - .../20180526162051-dwellings.down.sql | 8 - .../20180526162051-dwellings.up.sql | 11 - .../20180611204244-bootstrap.down.sql | 0 .../20180611204244-bootstrap.up.sql | 15 - resources/templates/app.html | 11 +- resources/templates/base.html | 9 +- resources/templates/canvasser.html | 60 -- src/clj/youyesyet/db/schema.clj | 484 ------------- src/clj/youyesyet/handler.clj | 3 +- src/clj/youyesyet/layout.clj | 25 +- src/clj/youyesyet/routes/authenticated.clj | 76 -- src/clj/youyesyet/routes/home.clj | 11 +- .../youyesyet/canvasser_app/handlers.cljs | 14 + src/cljs/youyesyet/canvasser_app/state.cljs | 4 +- .../youyesyet/canvasser_app/ui_utils.cljs | 21 +- .../canvasser_app/views/building.cljs | 2 +- .../canvasser_app/views/elector.cljs | 104 +++ .../canvasser_app/views/electors.cljs | 58 +- .../youyesyet/canvasser_app/views/gdpr.cljs | 60 ++ .../youyesyet/canvasser_app/views/issue.cljs | 2 +- .../youyesyet/canvasser_app/views/issues.cljs | 2 +- .../youyesyet/canvasser_app/views/map.cljs | 5 +- 45 files changed, 282 insertions(+), 1973 deletions(-) create mode 100644 package-lock.json delete mode 100644 resources/migrations/20161014170335-basic-setup.down.sql delete mode 100644 resources/migrations/20161014170335-basic-setup.up.sql delete mode 100644 resources/migrations/20170315190500-roles-and-teams.down.sql delete mode 100644 resources/migrations/20170315190500-roles-and-teams.up.sql delete mode 100644 resources/migrations/20170401115900-basic-reference-data.down.sql delete mode 100644 resources/migrations/20170401115900-basic-reference-data.up.sql delete mode 100644 resources/migrations/20170415102900-core-views.down.sql delete mode 100644 resources/migrations/20170415102900-core-views.up.sql delete mode 100644 resources/migrations/20170721084900-dwellings.down.sql delete mode 100644 resources/migrations/20170721084900-dwellings.up.sql delete mode 100644 resources/migrations/20180316110100-intentions-and-options.down.sql delete mode 100644 resources/migrations/20180316110100-intentions-and-options.up.sql delete mode 100644 resources/migrations/20180317170000-gender.down.sql delete mode 100644 resources/migrations/20180317170000-gender.up.sql delete mode 100644 resources/migrations/20180317170907-reference-data.down.sql delete mode 100644 resources/migrations/20180317170907-reference-data.up.sql delete mode 100644 resources/migrations/20180317175047-test-data.down.sql delete mode 100644 resources/migrations/20180317175047-test-data.up.sql delete mode 100644 resources/migrations/20180408124500-reference-data.down.sql delete mode 100644 resources/migrations/20180408124500-reference-data.up.sql delete mode 100644 resources/migrations/20180526162051-dwellings.down.sql delete mode 100644 resources/migrations/20180526162051-dwellings.up.sql delete mode 100644 resources/migrations/20180611204244-bootstrap.down.sql delete mode 100644 resources/migrations/20180611204244-bootstrap.up.sql delete mode 100644 resources/templates/canvasser.html delete mode 100644 src/clj/youyesyet/db/schema.clj delete mode 100644 src/clj/youyesyet/routes/authenticated.clj create mode 100644 src/cljs/youyesyet/canvasser_app/views/elector.cljs create mode 100644 src/cljs/youyesyet/canvasser_app/views/gdpr.cljs diff --git a/env/dev/clj/youyesyet/core.clj b/env/dev/clj/youyesyet/core.clj index c64c2e7..c9f3446 100644 --- a/env/dev/clj/youyesyet/core.clj +++ b/env/dev/clj/youyesyet/core.clj @@ -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) + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..17b97dd --- /dev/null +++ b/package-lock.json @@ -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=" + } + } +} diff --git a/project.clj b/project.clj index 303e26e..2e6879b 100644 --- a/project.clj +++ b/project.clj @@ -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 diff --git a/resources/migrations/20161014170335-basic-setup.down.sql b/resources/migrations/20161014170335-basic-setup.down.sql deleted file mode 100644 index 1005cee..0000000 --- a/resources/migrations/20161014170335-basic-setup.down.sql +++ /dev/null @@ -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; ---;; diff --git a/resources/migrations/20161014170335-basic-setup.up.sql b/resources/migrations/20161014170335-basic-setup.up.sql deleted file mode 100644 index 4d74c06..0000000 --- a/resources/migrations/20161014170335-basic-setup.up.sql +++ /dev/null @@ -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 --- - diff --git a/resources/migrations/20170315190500-roles-and-teams.down.sql b/resources/migrations/20170315190500-roles-and-teams.down.sql deleted file mode 100644 index a8bdb6a..0000000 --- a/resources/migrations/20170315190500-roles-and-teams.down.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170315190500-roles-and-teams.up.sql b/resources/migrations/20170315190500-roles-and-teams.up.sql deleted file mode 100644 index 7ff7ffc..0000000 --- a/resources/migrations/20170315190500-roles-and-teams.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170401115900-basic-reference-data.down.sql b/resources/migrations/20170401115900-basic-reference-data.down.sql deleted file mode 100644 index a0b3aa1..0000000 --- a/resources/migrations/20170401115900-basic-reference-data.down.sql +++ /dev/null @@ -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'; diff --git a/resources/migrations/20170401115900-basic-reference-data.up.sql b/resources/migrations/20170401115900-basic-reference-data.up.sql deleted file mode 100644 index 26d3bf1..0000000 --- a/resources/migrations/20170401115900-basic-reference-data.up.sql +++ /dev/null @@ -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'); - diff --git a/resources/migrations/20170415102900-core-views.down.sql b/resources/migrations/20170415102900-core-views.down.sql deleted file mode 100644 index c576947..0000000 --- a/resources/migrations/20170415102900-core-views.down.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170415102900-core-views.up.sql b/resources/migrations/20170415102900-core-views.up.sql deleted file mode 100644 index 53346a6..0000000 --- a/resources/migrations/20170415102900-core-views.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170721084900-dwellings.down.sql b/resources/migrations/20170721084900-dwellings.down.sql deleted file mode 100644 index 674fb1b..0000000 --- a/resources/migrations/20170721084900-dwellings.down.sql +++ /dev/null @@ -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; ---;; diff --git a/resources/migrations/20170721084900-dwellings.up.sql b/resources/migrations/20170721084900-dwellings.up.sql deleted file mode 100644 index 74e6a27..0000000 --- a/resources/migrations/20170721084900-dwellings.up.sql +++ /dev/null @@ -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; ---;; diff --git a/resources/migrations/20180316110100-intentions-and-options.down.sql b/resources/migrations/20180316110100-intentions-and-options.down.sql deleted file mode 100644 index 84c98b8..0000000 --- a/resources/migrations/20180316110100-intentions-and-options.down.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20180316110100-intentions-and-options.up.sql b/resources/migrations/20180316110100-intentions-and-options.up.sql deleted file mode 100644 index 0736740..0000000 --- a/resources/migrations/20180316110100-intentions-and-options.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20180317170000-gender.down.sql b/resources/migrations/20180317170000-gender.down.sql deleted file mode 100644 index 5eac53a..0000000 --- a/resources/migrations/20180317170000-gender.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -alter table electors drop column gender; - -drop table genders; diff --git a/resources/migrations/20180317170000-gender.up.sql b/resources/migrations/20180317170000-gender.up.sql deleted file mode 100644 index 9512ea2..0000000 --- a/resources/migrations/20180317170000-gender.up.sql +++ /dev/null @@ -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'; diff --git a/resources/migrations/20180317170907-reference-data.down.sql b/resources/migrations/20180317170907-reference-data.down.sql deleted file mode 100644 index ed67940..0000000 --- a/resources/migrations/20180317170907-reference-data.down.sql +++ /dev/null @@ -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'; - diff --git a/resources/migrations/20180317170907-reference-data.up.sql b/resources/migrations/20180317170907-reference-data.up.sql deleted file mode 100644 index ed1dfa4..0000000 --- a/resources/migrations/20180317170907-reference-data.up.sql +++ /dev/null @@ -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'); diff --git a/resources/migrations/20180317175047-test-data.down.sql b/resources/migrations/20180317175047-test-data.down.sql deleted file mode 100644 index 4a5583c..0000000 --- a/resources/migrations/20180317175047-test-data.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -delete from addresses where id < = 4; - -delete from electors where id <= 10; diff --git a/resources/migrations/20180317175047-test-data.up.sql b/resources/migrations/20180317175047-test-data.up.sql deleted file mode 100644 index 0cc4b20..0000000 --- a/resources/migrations/20180317175047-test-data.up.sql +++ /dev/null @@ -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'); diff --git a/resources/migrations/20180408124500-reference-data.down.sql b/resources/migrations/20180408124500-reference-data.down.sql deleted file mode 100644 index 68bada9..0000000 --- a/resources/migrations/20180408124500-reference-data.down.sql +++ /dev/null @@ -1 +0,0 @@ -alter table issues drop column current; diff --git a/resources/migrations/20180408124500-reference-data.up.sql b/resources/migrations/20180408124500-reference-data.up.sql deleted file mode 100644 index aaae234..0000000 --- a/resources/migrations/20180408124500-reference-data.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table issues add column current boolean default true; - diff --git a/resources/migrations/20180526162051-dwellings.down.sql b/resources/migrations/20180526162051-dwellings.down.sql deleted file mode 100644 index ab91769..0000000 --- a/resources/migrations/20180526162051-dwellings.down.sql +++ /dev/null @@ -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); diff --git a/resources/migrations/20180526162051-dwellings.up.sql b/resources/migrations/20180526162051-dwellings.up.sql deleted file mode 100644 index 41e1a6e..0000000 --- a/resources/migrations/20180526162051-dwellings.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20180611204244-bootstrap.down.sql b/resources/migrations/20180611204244-bootstrap.down.sql deleted file mode 100644 index e69de29..0000000 diff --git a/resources/migrations/20180611204244-bootstrap.up.sql b/resources/migrations/20180611204244-bootstrap.up.sql deleted file mode 100644 index d0377ad..0000000 --- a/resources/migrations/20180611204244-bootstrap.up.sql +++ /dev/null @@ -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); diff --git a/resources/templates/app.html b/resources/templates/app.html index 7b181ca..4b14abe 100644 --- a/resources/templates/app.html +++ b/resources/templates/app.html @@ -23,13 +23,22 @@

{% 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 %} -{% script "js/lib/leaflet/dist/leaflet.js" %} +{% 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 %} diff --git a/resources/templates/base.html b/resources/templates/base.html index 93c779c..317fc4f 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -10,7 +10,6 @@ {{site-title}}: {{title}} - {% script "js/lib/jquery/dist/jquery.min.js" %} {% endblock %} {% block extra-head %} @@ -76,10 +75,6 @@
{% endblock %} {% endblock %} - {% block extra-tail %} - - - {% endblock %} + {% block extra-tail %} + + + {% endblock %} diff --git a/resources/templates/canvasser.html b/resources/templates/canvasser.html deleted file mode 100644 index ceb6c6c..0000000 --- a/resources/templates/canvasser.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "base.html" %} -{% block title %} -{% endblock %} -{% block content %} -
- {% if canvasser %} - - {% endif %} -

- - -

-

- (TODO: Not absolutely sure what I'm going to do for an elector id widget yet.) -

-

- - {% if address.id %} - - - {{address.address}} - - {% else %} - (TODO: Some sort of address lookup widget goes here.) - {% endif %} -

-

- - -

-

- - -

-

- - -

- -

- 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 - -
- -{% endblock %} diff --git a/src/clj/youyesyet/db/schema.clj b/src/clj/youyesyet/db/schema.clj deleted file mode 100644 index 7571251..0000000 --- a/src/clj/youyesyet/db/schema.clj +++ /dev/null @@ -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!) - ) diff --git a/src/clj/youyesyet/handler.clj b/src/clj/youyesyet/handler.clj index b131f44..c9c8119 100644 --- a/src/clj/youyesyet/handler.clj +++ b/src/clj/youyesyet/handler.clj @@ -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 diff --git a/src/clj/youyesyet/layout.clj b/src/clj/youyesyet/layout.clj index 2033ecf..129f495 100644 --- a/src/clj/youyesyet/layout.clj +++ b/src/clj/youyesyet/layout.clj @@ -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 diff --git a/src/clj/youyesyet/routes/authenticated.clj b/src/clj/youyesyet/routes/authenticated.clj deleted file mode 100644 index cc6b9ea..0000000 --- a/src/clj/youyesyet/routes/authenticated.clj +++ /dev/null @@ -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))) diff --git a/src/clj/youyesyet/routes/home.clj b/src/clj/youyesyet/routes/home.clj index bcd418b..deaf047 100644 --- a/src/clj/youyesyet/routes/home.clj +++ b/src/clj/youyesyet/routes/home.clj @@ -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)) diff --git a/src/cljs/youyesyet/canvasser_app/handlers.cljs b/src/cljs/youyesyet/canvasser_app/handlers.cljs index a010699..2b7596a 100644 --- a/src/cljs/youyesyet/canvasser_app/handlers.cljs +++ b/src/cljs/youyesyet/canvasser_app/handlers.cljs @@ -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)))) diff --git a/src/cljs/youyesyet/canvasser_app/state.cljs b/src/cljs/youyesyet/canvasser_app/state.cljs index 241752e..4a770c8 100644 --- a/src/cljs/youyesyet/canvasser_app/state.cljs +++ b/src/cljs/youyesyet/canvasser_app/state.cljs @@ -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}) + diff --git a/src/cljs/youyesyet/canvasser_app/ui_utils.cljs b/src/cljs/youyesyet/canvasser_app/ui_utils.cljs index 068bad6..63e1846 100644 --- a/src/cljs/youyesyet/canvasser_app/ui_utils.cljs +++ b/src/cljs/youyesyet/canvasser_app/ui_utils.cljs @@ -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])] diff --git a/src/cljs/youyesyet/canvasser_app/views/building.cljs b/src/cljs/youyesyet/canvasser_app/views/building.cljs index 54a1ed2..47d9d8f 100644 --- a/src/cljs/youyesyet/canvasser_app/views/building.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/building.cljs @@ -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)))]]])) diff --git a/src/cljs/youyesyet/canvasser_app/views/elector.cljs b/src/cljs/youyesyet/canvasser_app/views/elector.cljs new file mode 100644 index 0000000..0f94f1f --- /dev/null +++ b/src/cljs/youyesyet/canvasser_app/views/elector.cljs @@ -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")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/electors.cljs b/src/cljs/youyesyet/canvasser_app/views/electors.cljs index 482d21a..8f0f310 100644 --- a/src/cljs/youyesyet/canvasser_app/views/electors.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/electors.cljs @@ -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")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/gdpr.cljs b/src/cljs/youyesyet/canvasser_app/views/gdpr.cljs new file mode 100644 index 0000000..b28369c --- /dev/null +++ b/src/cljs/youyesyet/canvasser_app/views/gdpr.cljs @@ -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")])) + + + diff --git a/src/cljs/youyesyet/canvasser_app/views/issue.cljs b/src/cljs/youyesyet/canvasser_app/views/issue.cljs index 34afe10..46b16b2 100644 --- a/src/cljs/youyesyet/canvasser_app/views/issue.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/issue.cljs @@ -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)]])) diff --git a/src/cljs/youyesyet/canvasser_app/views/issues.cljs b/src/cljs/youyesyet/canvasser_app/views/issues.cljs index 8b2ca47..9253a75 100644 --- a/src/cljs/youyesyet/canvasser_app/views/issues.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/issues.cljs @@ -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")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/map.cljs b/src/cljs/youyesyet/canvasser_app/views/map.cljs index 257e404..c0163b2 100644 --- a/src/cljs/youyesyet/canvasser_app/views/map.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/map.cljs @@ -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])] From 7aac88891287886128f2e7b883a3587a7d7fcff3 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 2 Jul 2018 16:22:38 +0100 Subject: [PATCH 083/180] Tactical commit while I try to understand why the app doesn't rebuild --- env/dev/clj/youyesyet/core.clj | 9 +- package-lock.json | 11 + project.clj | 35 +- .../20161014170335-basic-setup.down.sql | 50 -- .../20161014170335-basic-setup.up.sql | 669 ------------------ .../20170315190500-roles-and-teams.down.sql | 13 - .../20170315190500-roles-and-teams.up.sql | 39 - ...170401115900-basic-reference-data.down.sql | 17 - ...20170401115900-basic-reference-data.up.sql | 58 -- .../20170415102900-core-views.down.sql | 11 - .../20170415102900-core-views.up.sql | 59 -- .../20170721084900-dwellings.down.sql | 69 -- .../20170721084900-dwellings.up.sql | 87 --- ...0316110100-intentions-and-options.down.sql | 24 - ...180316110100-intentions-and-options.up.sql | 30 - .../migrations/20180317170000-gender.down.sql | 3 - .../migrations/20180317170000-gender.up.sql | 11 - .../20180317170907-reference-data.down.sql | 10 - .../20180317170907-reference-data.up.sql | 18 - .../20180317175047-test-data.down.sql | 3 - .../20180317175047-test-data.up.sql | 41 -- .../20180408124500-reference-data.down.sql | 1 - .../20180408124500-reference-data.up.sql | 2 - .../20180526162051-dwellings.down.sql | 8 - .../20180526162051-dwellings.up.sql | 11 - .../20180611204244-bootstrap.down.sql | 0 .../20180611204244-bootstrap.up.sql | 15 - resources/templates/app.html | 13 +- resources/templates/base.html | 9 +- resources/templates/canvasser.html | 60 -- src/clj/youyesyet/db/schema.clj | 484 ------------- src/clj/youyesyet/handler.clj | 3 +- src/clj/youyesyet/layout.clj | 25 +- src/clj/youyesyet/routes/authenticated.clj | 76 -- src/clj/youyesyet/routes/home.clj | 11 +- .../youyesyet/canvasser_app/handlers.cljs | 14 + src/cljs/youyesyet/canvasser_app/state.cljs | 4 +- .../youyesyet/canvasser_app/ui_utils.cljs | 21 +- .../canvasser_app/views/building.cljs | 2 +- .../canvasser_app/views/elector.cljs | 104 +++ .../canvasser_app/views/electors.cljs | 58 +- .../youyesyet/canvasser_app/views/gdpr.cljs | 60 ++ .../youyesyet/canvasser_app/views/issue.cljs | 2 +- .../youyesyet/canvasser_app/views/issues.cljs | 2 +- .../youyesyet/canvasser_app/views/map.cljs | 5 +- 45 files changed, 283 insertions(+), 1974 deletions(-) create mode 100644 package-lock.json delete mode 100644 resources/migrations/20161014170335-basic-setup.down.sql delete mode 100644 resources/migrations/20161014170335-basic-setup.up.sql delete mode 100644 resources/migrations/20170315190500-roles-and-teams.down.sql delete mode 100644 resources/migrations/20170315190500-roles-and-teams.up.sql delete mode 100644 resources/migrations/20170401115900-basic-reference-data.down.sql delete mode 100644 resources/migrations/20170401115900-basic-reference-data.up.sql delete mode 100644 resources/migrations/20170415102900-core-views.down.sql delete mode 100644 resources/migrations/20170415102900-core-views.up.sql delete mode 100644 resources/migrations/20170721084900-dwellings.down.sql delete mode 100644 resources/migrations/20170721084900-dwellings.up.sql delete mode 100644 resources/migrations/20180316110100-intentions-and-options.down.sql delete mode 100644 resources/migrations/20180316110100-intentions-and-options.up.sql delete mode 100644 resources/migrations/20180317170000-gender.down.sql delete mode 100644 resources/migrations/20180317170000-gender.up.sql delete mode 100644 resources/migrations/20180317170907-reference-data.down.sql delete mode 100644 resources/migrations/20180317170907-reference-data.up.sql delete mode 100644 resources/migrations/20180317175047-test-data.down.sql delete mode 100644 resources/migrations/20180317175047-test-data.up.sql delete mode 100644 resources/migrations/20180408124500-reference-data.down.sql delete mode 100644 resources/migrations/20180408124500-reference-data.up.sql delete mode 100644 resources/migrations/20180526162051-dwellings.down.sql delete mode 100644 resources/migrations/20180526162051-dwellings.up.sql delete mode 100644 resources/migrations/20180611204244-bootstrap.down.sql delete mode 100644 resources/migrations/20180611204244-bootstrap.up.sql delete mode 100644 resources/templates/canvasser.html delete mode 100644 src/clj/youyesyet/db/schema.clj delete mode 100644 src/clj/youyesyet/routes/authenticated.clj create mode 100644 src/cljs/youyesyet/canvasser_app/views/elector.cljs create mode 100644 src/cljs/youyesyet/canvasser_app/views/gdpr.cljs diff --git a/env/dev/clj/youyesyet/core.clj b/env/dev/clj/youyesyet/core.clj index c64c2e7..c9f3446 100644 --- a/env/dev/clj/youyesyet/core.clj +++ b/env/dev/clj/youyesyet/core.clj @@ -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) + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..17b97dd --- /dev/null +++ b/package-lock.json @@ -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=" + } + } +} diff --git a/project.clj b/project.clj index 303e26e..2e6879b 100644 --- a/project.clj +++ b/project.clj @@ -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 diff --git a/resources/migrations/20161014170335-basic-setup.down.sql b/resources/migrations/20161014170335-basic-setup.down.sql deleted file mode 100644 index 1005cee..0000000 --- a/resources/migrations/20161014170335-basic-setup.down.sql +++ /dev/null @@ -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; ---;; diff --git a/resources/migrations/20161014170335-basic-setup.up.sql b/resources/migrations/20161014170335-basic-setup.up.sql deleted file mode 100644 index 4d74c06..0000000 --- a/resources/migrations/20161014170335-basic-setup.up.sql +++ /dev/null @@ -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 --- - diff --git a/resources/migrations/20170315190500-roles-and-teams.down.sql b/resources/migrations/20170315190500-roles-and-teams.down.sql deleted file mode 100644 index a8bdb6a..0000000 --- a/resources/migrations/20170315190500-roles-and-teams.down.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170315190500-roles-and-teams.up.sql b/resources/migrations/20170315190500-roles-and-teams.up.sql deleted file mode 100644 index 7ff7ffc..0000000 --- a/resources/migrations/20170315190500-roles-and-teams.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170401115900-basic-reference-data.down.sql b/resources/migrations/20170401115900-basic-reference-data.down.sql deleted file mode 100644 index a0b3aa1..0000000 --- a/resources/migrations/20170401115900-basic-reference-data.down.sql +++ /dev/null @@ -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'; diff --git a/resources/migrations/20170401115900-basic-reference-data.up.sql b/resources/migrations/20170401115900-basic-reference-data.up.sql deleted file mode 100644 index 26d3bf1..0000000 --- a/resources/migrations/20170401115900-basic-reference-data.up.sql +++ /dev/null @@ -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'); - diff --git a/resources/migrations/20170415102900-core-views.down.sql b/resources/migrations/20170415102900-core-views.down.sql deleted file mode 100644 index c576947..0000000 --- a/resources/migrations/20170415102900-core-views.down.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170415102900-core-views.up.sql b/resources/migrations/20170415102900-core-views.up.sql deleted file mode 100644 index 53346a6..0000000 --- a/resources/migrations/20170415102900-core-views.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20170721084900-dwellings.down.sql b/resources/migrations/20170721084900-dwellings.down.sql deleted file mode 100644 index 674fb1b..0000000 --- a/resources/migrations/20170721084900-dwellings.down.sql +++ /dev/null @@ -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; ---;; diff --git a/resources/migrations/20170721084900-dwellings.up.sql b/resources/migrations/20170721084900-dwellings.up.sql deleted file mode 100644 index 74e6a27..0000000 --- a/resources/migrations/20170721084900-dwellings.up.sql +++ /dev/null @@ -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; ---;; diff --git a/resources/migrations/20180316110100-intentions-and-options.down.sql b/resources/migrations/20180316110100-intentions-and-options.down.sql deleted file mode 100644 index 84c98b8..0000000 --- a/resources/migrations/20180316110100-intentions-and-options.down.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20180316110100-intentions-and-options.up.sql b/resources/migrations/20180316110100-intentions-and-options.up.sql deleted file mode 100644 index 0736740..0000000 --- a/resources/migrations/20180316110100-intentions-and-options.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20180317170000-gender.down.sql b/resources/migrations/20180317170000-gender.down.sql deleted file mode 100644 index 5eac53a..0000000 --- a/resources/migrations/20180317170000-gender.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -alter table electors drop column gender; - -drop table genders; diff --git a/resources/migrations/20180317170000-gender.up.sql b/resources/migrations/20180317170000-gender.up.sql deleted file mode 100644 index 9512ea2..0000000 --- a/resources/migrations/20180317170000-gender.up.sql +++ /dev/null @@ -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'; diff --git a/resources/migrations/20180317170907-reference-data.down.sql b/resources/migrations/20180317170907-reference-data.down.sql deleted file mode 100644 index ed67940..0000000 --- a/resources/migrations/20180317170907-reference-data.down.sql +++ /dev/null @@ -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'; - diff --git a/resources/migrations/20180317170907-reference-data.up.sql b/resources/migrations/20180317170907-reference-data.up.sql deleted file mode 100644 index ed1dfa4..0000000 --- a/resources/migrations/20180317170907-reference-data.up.sql +++ /dev/null @@ -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'); diff --git a/resources/migrations/20180317175047-test-data.down.sql b/resources/migrations/20180317175047-test-data.down.sql deleted file mode 100644 index 4a5583c..0000000 --- a/resources/migrations/20180317175047-test-data.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -delete from addresses where id < = 4; - -delete from electors where id <= 10; diff --git a/resources/migrations/20180317175047-test-data.up.sql b/resources/migrations/20180317175047-test-data.up.sql deleted file mode 100644 index 0cc4b20..0000000 --- a/resources/migrations/20180317175047-test-data.up.sql +++ /dev/null @@ -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'); diff --git a/resources/migrations/20180408124500-reference-data.down.sql b/resources/migrations/20180408124500-reference-data.down.sql deleted file mode 100644 index 68bada9..0000000 --- a/resources/migrations/20180408124500-reference-data.down.sql +++ /dev/null @@ -1 +0,0 @@ -alter table issues drop column current; diff --git a/resources/migrations/20180408124500-reference-data.up.sql b/resources/migrations/20180408124500-reference-data.up.sql deleted file mode 100644 index aaae234..0000000 --- a/resources/migrations/20180408124500-reference-data.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table issues add column current boolean default true; - diff --git a/resources/migrations/20180526162051-dwellings.down.sql b/resources/migrations/20180526162051-dwellings.down.sql deleted file mode 100644 index ab91769..0000000 --- a/resources/migrations/20180526162051-dwellings.down.sql +++ /dev/null @@ -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); diff --git a/resources/migrations/20180526162051-dwellings.up.sql b/resources/migrations/20180526162051-dwellings.up.sql deleted file mode 100644 index 41e1a6e..0000000 --- a/resources/migrations/20180526162051-dwellings.up.sql +++ /dev/null @@ -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; diff --git a/resources/migrations/20180611204244-bootstrap.down.sql b/resources/migrations/20180611204244-bootstrap.down.sql deleted file mode 100644 index e69de29..0000000 diff --git a/resources/migrations/20180611204244-bootstrap.up.sql b/resources/migrations/20180611204244-bootstrap.up.sql deleted file mode 100644 index d0377ad..0000000 --- a/resources/migrations/20180611204244-bootstrap.up.sql +++ /dev/null @@ -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); diff --git a/resources/templates/app.html b/resources/templates/app.html index 7b181ca..3227f33 100644 --- a/resources/templates/app.html +++ b/resources/templates/app.html @@ -23,13 +23,22 @@

{% 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 %} - -{% script "js/lib/leaflet/dist/leaflet.js" %} + +{% 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 %} diff --git a/resources/templates/base.html b/resources/templates/base.html index 93c779c..317fc4f 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -10,7 +10,6 @@ {{site-title}}: {{title}} - {% script "js/lib/jquery/dist/jquery.min.js" %} {% endblock %} {% block extra-head %} @@ -76,10 +75,6 @@ {% endblock %} {% endblock %} - {% block extra-tail %} - - - {% endblock %} + {% block extra-tail %} + + + {% endblock %} diff --git a/resources/templates/canvasser.html b/resources/templates/canvasser.html deleted file mode 100644 index ceb6c6c..0000000 --- a/resources/templates/canvasser.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "base.html" %} -{% block title %} -{% endblock %} -{% block content %} -
- {% if canvasser %} - - {% endif %} -

- - -

-

- (TODO: Not absolutely sure what I'm going to do for an elector id widget yet.) -

-

- - {% if address.id %} - - - {{address.address}} - - {% else %} - (TODO: Some sort of address lookup widget goes here.) - {% endif %} -

-

- - -

-

- - -

-

- - -

- -

- 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 - -
- -{% endblock %} diff --git a/src/clj/youyesyet/db/schema.clj b/src/clj/youyesyet/db/schema.clj deleted file mode 100644 index 7571251..0000000 --- a/src/clj/youyesyet/db/schema.clj +++ /dev/null @@ -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!) - ) diff --git a/src/clj/youyesyet/handler.clj b/src/clj/youyesyet/handler.clj index b131f44..c9c8119 100644 --- a/src/clj/youyesyet/handler.clj +++ b/src/clj/youyesyet/handler.clj @@ -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 diff --git a/src/clj/youyesyet/layout.clj b/src/clj/youyesyet/layout.clj index 2033ecf..129f495 100644 --- a/src/clj/youyesyet/layout.clj +++ b/src/clj/youyesyet/layout.clj @@ -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 diff --git a/src/clj/youyesyet/routes/authenticated.clj b/src/clj/youyesyet/routes/authenticated.clj deleted file mode 100644 index cc6b9ea..0000000 --- a/src/clj/youyesyet/routes/authenticated.clj +++ /dev/null @@ -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))) diff --git a/src/clj/youyesyet/routes/home.clj b/src/clj/youyesyet/routes/home.clj index bcd418b..deaf047 100644 --- a/src/clj/youyesyet/routes/home.clj +++ b/src/clj/youyesyet/routes/home.clj @@ -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)) diff --git a/src/cljs/youyesyet/canvasser_app/handlers.cljs b/src/cljs/youyesyet/canvasser_app/handlers.cljs index a010699..2b7596a 100644 --- a/src/cljs/youyesyet/canvasser_app/handlers.cljs +++ b/src/cljs/youyesyet/canvasser_app/handlers.cljs @@ -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)))) diff --git a/src/cljs/youyesyet/canvasser_app/state.cljs b/src/cljs/youyesyet/canvasser_app/state.cljs index 241752e..4a770c8 100644 --- a/src/cljs/youyesyet/canvasser_app/state.cljs +++ b/src/cljs/youyesyet/canvasser_app/state.cljs @@ -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}) + diff --git a/src/cljs/youyesyet/canvasser_app/ui_utils.cljs b/src/cljs/youyesyet/canvasser_app/ui_utils.cljs index 068bad6..63e1846 100644 --- a/src/cljs/youyesyet/canvasser_app/ui_utils.cljs +++ b/src/cljs/youyesyet/canvasser_app/ui_utils.cljs @@ -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])] diff --git a/src/cljs/youyesyet/canvasser_app/views/building.cljs b/src/cljs/youyesyet/canvasser_app/views/building.cljs index 54a1ed2..47d9d8f 100644 --- a/src/cljs/youyesyet/canvasser_app/views/building.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/building.cljs @@ -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)))]]])) diff --git a/src/cljs/youyesyet/canvasser_app/views/elector.cljs b/src/cljs/youyesyet/canvasser_app/views/elector.cljs new file mode 100644 index 0000000..0f94f1f --- /dev/null +++ b/src/cljs/youyesyet/canvasser_app/views/elector.cljs @@ -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")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/electors.cljs b/src/cljs/youyesyet/canvasser_app/views/electors.cljs index 482d21a..8f0f310 100644 --- a/src/cljs/youyesyet/canvasser_app/views/electors.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/electors.cljs @@ -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")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/gdpr.cljs b/src/cljs/youyesyet/canvasser_app/views/gdpr.cljs new file mode 100644 index 0000000..b28369c --- /dev/null +++ b/src/cljs/youyesyet/canvasser_app/views/gdpr.cljs @@ -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")])) + + + diff --git a/src/cljs/youyesyet/canvasser_app/views/issue.cljs b/src/cljs/youyesyet/canvasser_app/views/issue.cljs index 34afe10..46b16b2 100644 --- a/src/cljs/youyesyet/canvasser_app/views/issue.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/issue.cljs @@ -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)]])) diff --git a/src/cljs/youyesyet/canvasser_app/views/issues.cljs b/src/cljs/youyesyet/canvasser_app/views/issues.cljs index 8b2ca47..9253a75 100644 --- a/src/cljs/youyesyet/canvasser_app/views/issues.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/issues.cljs @@ -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")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/map.cljs b/src/cljs/youyesyet/canvasser_app/views/map.cljs index 257e404..c0163b2 100644 --- a/src/cljs/youyesyet/canvasser_app/views/map.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/map.cljs @@ -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])] From e19e01d9be5e72c4e4707bac04e7427435c7f6b6 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 2 Jul 2018 17:29:01 +0100 Subject: [PATCH 084/180] Trying to track down why we're seeing a version of the electors panel which should no longer be there. Failing. --- project.clj | 8 +++----- resources/templates/app.html | 2 +- src/cljs/youyesyet/canvasser_app/core.cljs | 6 ++++++ .../youyesyet/canvasser_app/views/building.cljs | 2 +- .../youyesyet/canvasser_app/views/elector.cljs | 4 ++-- src/cljs/youyesyet/canvasser_app/views/map.cljs | 14 ++++++++------ 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/project.clj b/project.clj index 2e6879b..702368e 100644 --- a/project.clj +++ b/project.clj @@ -77,7 +77,7 @@ :npm {:dependencies [[datatables.net "1.10.19"] [datatables.net-dt "1.10.19"] [jquery "3.3.1"] - [leaflet "1.3.1"] + [leaflet "0.7.3"] ;; old version works, new ["1.3.1"] doesn't [signature_pad "2.3.2"]] :root "resources/public/js/lib"} @@ -139,8 +139,7 @@ [lein-figwheel "0.5.9"] [org.clojure/clojurescript "1.9.495"]] :cljsbuild - {:prep-tasks [["npm" "install"]] - :builds + {:builds {:app {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"] :compiler @@ -159,8 +158,7 @@ (pjstadig.humane-test-output/activate!)]} :project/test {:resource-paths ["env/test/resources"] :cljsbuild - {:prep-tasks [["npm" "install"]] - :builds + {:builds {:test {:source-paths ["src/cljc" "src/cljs" "test/cljs"] :compiler diff --git a/resources/templates/app.html b/resources/templates/app.html index 4b14abe..3227f33 100644 --- a/resources/templates/app.html +++ b/resources/templates/app.html @@ -36,7 +36,7 @@ - + {% 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" %} diff --git a/src/cljs/youyesyet/canvasser_app/core.cljs b/src/cljs/youyesyet/canvasser_app/core.cljs index e492a35..f750122 100644 --- a/src/cljs/youyesyet/canvasser_app/core.cljs +++ b/src/cljs/youyesyet/canvasser_app/core.cljs @@ -15,8 +15,10 @@ [youyesyet.canvasser-app.ui-utils :as ui] [youyesyet.canvasser-app.views.about :as about] [youyesyet.canvasser-app.views.building :as building] + [youyesyet.canvasser-app.views.elector :as elector] [youyesyet.canvasser-app.views.electors :as electors] [youyesyet.canvasser-app.views.followup :as followup] + [youyesyet.canvasser-app.views.gdpr :as gdpr] [youyesyet.canvasser-app.views.issue :as issue] [youyesyet.canvasser-app.views.issues :as issues] [youyesyet.canvasser-app.views.map :as maps]) @@ -57,6 +59,9 @@ (defn electors-page [] (electors/panel)) +(defn elector-page [] + (elector/panel)) + (defn followup-page [] (followup/panel)) @@ -72,6 +77,7 @@ (def pages {:about #'about-page :building #'building-page + :elector #'elector-page :electors #'electors-page :followup #'followup-page :issues #'issues-page diff --git a/src/cljs/youyesyet/canvasser_app/views/building.cljs b/src/cljs/youyesyet/canvasser_app/views/building.cljs index 47d9d8f..75ecc24 100644 --- a/src/cljs/youyesyet/canvasser_app/views/building.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/building.cljs @@ -48,7 +48,7 @@ [dwelling] (ui/big-link (:sub-address dwelling) - :target (str "#/electors/" (:id dwelling))) ) + :target (str "#electors/" (:id dwelling))) ) (sort #(< (:sub-address %1) (:sub-address %2)) (:dwellings address)))]]])) diff --git a/src/cljs/youyesyet/canvasser_app/views/elector.cljs b/src/cljs/youyesyet/canvasser_app/views/elector.cljs index 0f94f1f..cdc3e0b 100644 --- a/src/cljs/youyesyet/canvasser_app/views/elector.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/elector.cljs @@ -1,6 +1,6 @@ (ns ^{:doc "Canvasser app single elector panel." :author "Simon Brooke"} - youyesyet.canvasser-app.views.electors + youyesyet.canvasser-app.views.elector (:require [reagent.core :refer [atom]] [re-frame.core :refer [reg-sub subscribe dispatch]] [youyesyet.canvasser-app.ui-utils :as ui])) @@ -99,6 +99,6 @@ #(option-row elector %) options) ;; issues row - (issues-row elector)]] + (issue-row elector)]] (ui/back-link)]] (ui/error-panel "No address selected")))) diff --git a/src/cljs/youyesyet/canvasser_app/views/map.cljs b/src/cljs/youyesyet/canvasser_app/views/map.cljs index c0163b2..e7a6c24 100644 --- a/src/cljs/youyesyet/canvasser_app/views/map.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/map.cljs @@ -97,19 +97,21 @@ lng (:longitude address) pin (.icon js/L (clj->js - {:iconUrl (str "img/map-pins/" (pin-image address) ".png") - :shadowUrl "img/map-pins/shadow_pin.png" + {:iconAnchor [16 41] :iconSize [32 42] + :iconUrl (str "img/map-pins/" (pin-image address) ".png") + :riseOnHover true + :shadowAnchor [16 23] :shadowSize [57 24] - :iconAnchor [16 41] - :shadowAnchor [16 23]})) + :shadowUrl "img/map-pins/shadow_pin.png"})) marker (.marker js/L (.latLng js/L lat lng) (clj->js {:icon pin :title (:address address)})) ] - (.on marker "click" (fn [_] (map-pin-click-handler (str (:id address))))) - (.addTo marker view))) + + (.on (.addTo marker view) "click" (fn [_] (map-pin-click-handler (str (:id address))))) + )) ;; My gods mapbox is user-hostile! From 13f454afb57d2d589c753b13556826863f4c3ba2 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 2 Jul 2018 17:42:15 +0100 Subject: [PATCH 085/180] Updated README database section; reformat of electors Electors page is STILL rendering an obsolete version which is nowhere in the code, and I cannot see how it possibly can. --- README.md | 16 ++++++++++++---- .../youyesyet/canvasser_app/views/electors.cljs | 13 ++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index dd054c8..f21afe9 100644 --- a/README.md +++ b/README.md @@ -59,16 +59,24 @@ Do get the database initialised, run createdb youyesyet_dev -followed by +I'm no longer using Migratus as I'm using [Application Description Language]() +to generate the majority of the application, and, as changes are made to the application +description, new database schemas are generated. The database initialisation script will +be found at `resources/sql/youyesyet.postgres.sql`. Reference data initialisation scripts +will in due course be stored in the same directory. - lein migratus migrate - -**NOTE THAT** in the namespace *youyesyet.db.schema*, there are a series of functions *create-xxx-table!*. These are a snare and a delusion; they are how I originally bootstrapped the database, but are no longer used (and should probably be deleted). The database is now constructed using [migratus](https://github.com/yogthos/migratus). +Once we have a more or less finished application it may be worth going back to +[Migratus](https://github.com/yogthos/migratus); I might have a go at generating migrations from +diffs between successive versions of the application description. ## Running in a dev environment To run in a dev environment, checkout the *develop* branch +To download and install Javascript delendencies, run + + lein npm install + To start a development web server for the application, run: lein run diff --git a/src/cljs/youyesyet/canvasser_app/views/electors.cljs b/src/cljs/youyesyet/canvasser_app/views/electors.cljs index 8f0f310..eb1f5ec 100644 --- a/src/cljs/youyesyet/canvasser_app/views/electors.cljs +++ b/src/cljs/youyesyet/canvasser_app/views/electors.cljs @@ -62,11 +62,12 @@ (defn name-cell [elector] - [:td {:key (str "name-" (:id elector)) - :on-click #(dispatch - [:set-elector-and-page {:elector-id (:id elector) - :page "gdpr"}])} - (: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 @@ -92,9 +93,7 @@ [:div.container {:id "main-container"} [:table [:tbody - ;; genders row (genders-row electors) - ;; names row (names-row electors)]] (ui/back-link)]] (ui/error-panel "No address selected")))) From c7b64845970a0ee3ea4cb5db53c26fd9644ef5bf Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 2 Jul 2018 18:17:46 +0100 Subject: [PATCH 086/180] Got rid of obsolete stuff Still trying to work out where the obsolete version of the app is hiding! --- dummies/mapview.png | Bin 3962517 -> 0 bytes dummies/mapview.svg | 4874 ----------------- dummies/mapview.xcf | Bin 365501 -> 0 bytes dummies/mapview_800.png | Bin 681083 -> 0 bytes dummies/mapview_800.xcf | Bin 1316227 -> 0 bytes dummies/occupants.png | Bin 367547 -> 0 bytes dummies/occupants.svg | 454 -- dummies/occupants.xcf | Bin 1046838 -> 0 bytes dummies/occupants_800.png | Bin 93285 -> 0 bytes dummies/occupants_800.xcf | Bin 201210 -> 0 bytes dummies/ujack.png | Bin 5937 -> 0 bytes dummies/ujack.xcf | Bin 58268 -> 0 bytes dummies/unknown.png | Bin 2863 -> 0 bytes dummies/unknown.xcf | Bin 43990 -> 0 bytes followup.cljs | 72 - src/cljs/youyesyet/canvasser_app/core.cljs | 4 + .../youyesyet/canvasser_app/handlers.cljs | 1 + .../youyesyet/canvasser_app/views/gdpr.cljs | 15 +- 18 files changed, 17 insertions(+), 5403 deletions(-) delete mode 100644 dummies/mapview.png delete mode 100644 dummies/mapview.svg delete mode 100644 dummies/mapview.xcf delete mode 100644 dummies/mapview_800.png delete mode 100644 dummies/mapview_800.xcf delete mode 100644 dummies/occupants.png delete mode 100644 dummies/occupants.svg delete mode 100644 dummies/occupants.xcf delete mode 100644 dummies/occupants_800.png delete mode 100644 dummies/occupants_800.xcf delete mode 100644 dummies/ujack.png delete mode 100644 dummies/ujack.xcf delete mode 100644 dummies/unknown.png delete mode 100644 dummies/unknown.xcf delete mode 100644 followup.cljs diff --git a/dummies/mapview.png b/dummies/mapview.png deleted file mode 100644 index 1fe15e1b2dec91ae3c0383b0cb71efc3cd85bce3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3962517 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%0DFcR&9qx5=>V%IUflN%IT{V?Gl zrA-cz^-qmBE6&vjL)}ABMB^~(n(eP?z$Vz0FZDSUQ}Pz+tbv;{4tLzNUbv@v!AeZ@ zSbi9^9ob)#2wmRi#hzAS?*~>{wqV7kZ+UqUr zp997B(qZ8R;bGIKKDS;;PnXG1c21m=0Kzlaa8xz8Fx%ogK2x`;J*AyDusl9!&wALl z!Ar-%vVtS@yyaqT-B&Vo0Ogu?(zNHEZ}T-EU$Nkixni{VF3wS4TnzEt?k#iEmT&g^5(dCaXvG*G=e!wR32lUsct zL_|d3^*;v+DUHI8;i8>Ow;Q-7$r)`!%=egcf^V|TCUVEf3+wtLSI%>MV_ZFQnSCr- ziFSvXyF{*rroNKge}czN`ENno_fUa`CEme{G4y7JsEZPkEBB z_v;o`X#O9lOl5<-0Xr_PX!wruuaEj_*Dh{f^fNIfil0iFi?g5mK;*=t~B zZvVw!{KYrjjGxM3gEf$A?xbumiiMCRW?Ax<8L0GMxUb5TxwYM9jF|!NPs_P{T^HV; zPn_=$ygwqq`@WuY>yhgXkH>puML!>SJRf*IPrN_h@#)Ji@&5h^&*u|9S#@K{mKh7c zo=+^B53FjpD$mTQZYL5B(fP#FGqxV0Y(2)nJPw@a@=p@ym7lY8g38P#Pvcz^sY;op zwncpA03`P;X&O>8c8|4Hns^o-Eu6OcQHw6Q`c$yB=)B=eU$4-e<@XA|$0FH*wa6Ou zp(>`L?wDy$QW2)!51M%385aY+(TvQ;V|r{?Iz>ONMa>?%ahhRZ=5?uO6i=j{D<*|j zbn{^_AAw~IM+WveuB!jBzK6gF4$#Mp;2ZUmFP<8hK4GlLi@9hhbB+VO#zGcRx<^$; zWHqMid1b{i`lk^5N{o>HONk#G$DV9v75mir5cjQWWwju3(Kxc0qwF=SZpKt<{MIqt ztHV;?pV!=0=q}v6j0@0-Lf{nvRd^ZDbEZK;<7A8lc5A={7{!W`awICiDx)WHw!Ftc z<@A;QPdTu@(t(A`;8r;5gog}*jy_%mSd96 zi1qtiK^u-8mcgl@at&aDU;m)(V#uqYAuPjzfmQ0fkPq+6uahP-D+86m9L~u2Fg+emNn2tFnF1vC91C}c= z*B%d1PD_Hy>%NU(pr0#&nU$hS`PO^=2(($@yhvltkq}ZSTf1UU`sBomGck0y{-En z$Ju`0oJi5nMrjIdmbo3Ho$uEoopgUS-QT1FzgFkDLP^F?`2ZW=#9W@a|L3vxMqv59 z%F@l=I0K zFsA;3&j>7M&b1HfJMX8UJpX9UNZqBJW=aP-nU|D9>mK+%+BQrxyDU#~0(}RE( z2$|$j@-Zl?8T~q!my>fuhTh7^TMM`-^Q+x)@oGm1f0Kr^`7FOt(W3H3LC7v!ujhs5 zxC9Vg3E0r)USWeQ7fMHN1d82PVBId@$`-GCRWR9V`-r`iZ_2g_hpud`4jGURHGW22 zzviqM0!lQFZ;VY3Ox|T$ezxf$1}kzQi9TRqbjX$yxmbyNGOFXdR=+Znt{gc6w^ep? ztP}gtiF!q_>^^UjaGMCB%;5_HV18i4Hwa_Vr47AB9K39~Z!~qFm+sli_}pY&oLirT z?pegKH7Lc&OZ_C@;q_6p=wBkIyma|BAm3CuNF~o-RVK;enVXj2qLC)UsM$nUVaHu% zEMxl>pVXkt!3Ly-AB-lp2b47&3? zaUB=Vxz4rRIbP`l_CNIX;bX&)=)aL{xsJz^aM`CG7^y&XD>3iopshf1$@Sf4=>rzy z7~2Q*lBaUMq;ASzJ^zYfyG;e_ET$7eCs4dq=Uhyc1*)c4gXL; z@lz2_UM;He=oL4V|7c&DFUN@c3W{(nxIIbB(i9!s@diY$NiV#}*s)aU@y1^pZsB)p z!D;P>m1N@B0C}AX0;ug+-)mQw-#~w-*V6Bxc(;CE{kx4(j@@1!PWPc*0p;r&IM12c z75)3g0}LXwYEWk7ZsSxm@`gk9t!bDsqSb&HAZzs9#;#84i-|Q&WUyJv0uZ0JX>Q`DUXp5yN!LfbznxtQO{V z9g-*d;n+$d`wDHfZ2$zoAx){er$jxpHq;@hHyQE!Y| zoU2&EMqrZ6s2L!Bb&sGbd$(gbIaBno`V}}hyeBJhCCW4=Op7syYbV}Jn)kA&Dc^)g z`q(3Vb8}d1^%IE|!V)=Jdam*#zbNvL6#U_ym-ofTq4R_f3)kGoS8+Ytpa^rRUv2zr{Aq?v%^;aqn_{2Fd@lmaYdgk?~fUtpkVj2&+wahE%? zD#|gQ5tRLex3>r0pYQmV29%$xO3dSNR!~`|nB+JH+)o&=_EV<6m9~d3zjGok(l_O&_>ja#-Vk}o zYSHhM{iN>$N+kJD-zfV84!aPAh6800zk^l90_#b;KelHDTdhG(vyv5Ck$%0tA2i3u z2r76VUqNE(rLvKNZgb+AhU+pIR%bHA0QvsF>Zm7z$m_3w^0mf_TVTna)rDsvu>}bt zA3d0y)sl8RnRvm{7g7EMR_|F08*Ey`UnNpDnnCSGOTO;Lzu}zzM1qR&ObshAllvC} z;0i!+FPzwi%WN_1n!F3}S`>XRfEmD5CVB^2R_}$O?r8*)!wiUk^7PsVI{Eo#Y{bM8 zAZU%zlXE*0OS_dB)44iXci!Nmx1VJXQc!I`8bQZ3aurZkDLy$n%o4CExU2EV=C`)? zAfP$~UV-eIxb-@E&@7KKycSsv3@jJ4Oxz8w;MOug6tu;xMRV1Kwbz@~HT#HdcC899 zUn^~WE(Q_0HPD(iM~rEX`}*EAhuQ4B35Y@2_XEauZ9Ub!aJrL{llA_a+l5{p-AK=| zCoMKXx(kVZmCdZ!_`Wq#=%EVfE1Fqw$I$n%4l?lfT;Y={L!>MP80WS%0AzTaXJm#P zu^NkXSjO-%PMpj(GQ)ZG@imliZiXcKeQqVBC3urY+;&b!^pJC2t3N70ok1h_c-9q7 zotHT7nPo8s#&Jd&x>JD7B6`Y69VcZs(ztzG_fcMem7V}BffY+o=5L$u%A4dk?al{x z!|=7(;P54D+-lE{T(G2-0Bq@pC33h!nPeYu-pRugba0MN>1WXE1;KKT>HcZ9GUwa| z+QJ(k1Ax4b3`jeY<4W*>K~%@0bpbyq-XA~&6BQt_0NGak*8m6tASx!jwdj=!^X)nQ zd5+C?A2^<4U_1>^3HBD(7`nr_JC6tY`#xs`l%yh+Ntk|%sPYozjhGv_PH%VIT zx)gA1n!Tv^73xl}mFnw*$@S4?cHF22UN^HyoNYW4_87E>^^x>iaX4zMVpcZl+;n2S zS;L&~lUi(&^?o%GD;T_ewuHIAU@c%J#-!e)k$#MZU0qqzf#W>zhzc|3d8WKyGV>lx zRwI{=^$e{ZAfaobdgGx zN@MV;GSe1s)WVwExNXO6UNmUg`6VwVKhg!v{GNL+mx`n*%1*oWT68jyaz^o;G_1WY zfBOqOpg0sU2W+*&xCm|_b$o3zQu@Qgma2fkt}CnkP5g<>Yce`9zt=nxnO^gcHk{l? zR{_j12c{34XW!an==X#N zw5+o}(y=w~?dJX4UWK`+UP}fUN?0E!OGHLB2MM?X)F#3>st2Ihm3WC`x{Y`8ODr1o&_%OjK<<3jE-$J^ z`?6zT`VspquOtthkIiOl5TPV`a+0rEIT%<@-a*>9$2b;U<^{~( zCUL%IIGwn;Znevo#KiWX7v)n4a-LHHbO+IY6uFm?qeH@BTQ=4lGGhnPz ztWaG?e#q=MlC0CHEpqzb>ub5!PviKrKl`(9 zx(PqEBNupytpmypo} z7r|%5ox(S``rYwb;$8~)?5$uC0F|lP`K$4pEMg@VQQyI$v2Qx6>j7=Qsh_o)EV{$i zmWTR#U;L!Lpri`N4Tvp|EV7GnvpLMh3dBBF3d@sxHj7`1f5OvY)_7z0iIUE`4bZw) z@!v3O{=a*yfSJnZCN2A?I(zdi!dCm&Ixv|Fw_~Tfp|&jP_J#vE*Mt_}L}SC3F+h+; zxwSejcea@hY_8C@;j0`S1wcAK_MmbQkL90e9HPokvE7SR)+#t~pGhQ^RE*M&e7`kY z)}(Gipp0G@rjyC-tAGGzrSfYTEY=|?XeQ!daW7yi*qW<9Alb@@(obQsrGyG@=SuT!JfO1H>OK8% z>x(MbY>4#x-d0Pxb|4}OfjU8*9YCH}JFS{Y#g*s0-L8?*@KBO9L2 zJkNy;y6;Go`Ewj{-2=z@z&8M_e}ps!hN6nzpu9QXlc2hG8_gT*f+OygHAVDWLOBm^j)w z-J|-cr!Me0Fh?xTnz6tN(U;UOeHyeQ=gbDm1o-YirBtPbQ=8>!JQmH>cNy?t-=&Lr zPrLPbYv9H@DbI6kO3tKncZ?NKehxfkjx0SVK~pP7e9c2`9Tu2t&7usS6-dr10G0t0 zmFA>t30-w{ulELv1?7B3-;Y^jA4pQsuxVR}zI}CYA0h5T#tIl_R(mx1frD2WYgOs0 zmT^TXo%P@z?!!yw!LSzoq4SmUcN@?4P8n*~tSTL^dZZ+=f^R}5%0V@ADA#n=WKS!TBwEw9z8&-QE^m_7%rIpZ06KI*JRuz1F$a&a?MHJK}fK zPpn-_Z9ybAsDrV;*XNzJGwtmwe8TTFj7Grd$n5GIOGoQ@jW?$#-;wz`EwYuxzzRdX z@DOBSA6AC)Dw!;N#==qcHFXhneQdgA%K zqU7pU#wxMA;-a{!8bm>7lflm{!pu}=7Mj8A9#n44{3=1VcaXec`rf_cYq|$h@FqFt zlnp8i3a>XyM)yD!+y)@!O)aijwpD)Ec-xZii1~{q>{?|XCzhf7kG5+i8rnaF^|k$d z)~l@2c>p=So)Y~ z;EggcF_WY4g*tgN1HLNr@PeraWgPjg+D)qog8tL~S;1pga5#?x$9b-do`cUvEl>l% z(t|bXp_{XR>%Ey{U2N|D4aB_t&8Lkb0p;baTMpkv7R#|o{!kp*_=7XG%XRvgR$IbG^py$jV`QH(XDU~f zEGbHhTXgW&f?bb{A@^+8>eDJIKaN=Ne7%sz%G2#V6tCt`%l!k(&m8X(1Nkl6Ub~F6 z+}Ah=uJ6;w=`t5<{%~uGu3yQ990NJmIqr-1a-m@xXZfDUv%zbD)4>Ues*PUs)u24j zjU*5VXhJL(-Dk>2@%bIanf%w+Do?j+0H7@4+>X-MW?5O07<@*F(Yku+(ToDjXA4o~oLnMO-4%Oyw{DkH@2BC)a-J&j=*HXE6EkJn{B?gbw9m*=sFOg5y@v zZyM|}JVh_y)j2yW{;jn4j3s@gk|dTsJGcd4P;2QAZ`-KWfs_+>N9>&R8HP0y%>)&tO}-x4)gk?bVotTMn~EYJ{O(myx_0}jkvW) zC{aheHxL>7m4u=}+&Rlan&eLt6)gT2VuMM1;vTld!ipI)5?^dl$%^-^GL?_9s<4%> zqh~DVTu53Y=95>ZaxPZ)#3oU7yl@Rk4;n^EH#^BrImB@@g~t%psPNM>qxfpbW(!>WtmLQehJsK zzV!AMnD0P3f0>t6>Il8_nl!kWaSTY!#d@~Y?+miLT#w)LD%Y5+NSTcybnTgJt-E>e zta5}h3VGcG`EqMgvK)?HD_QapG?wQymwq5F9yPGKv6Th`=Xf=-l!eQfipt>kOQDA|Xjj1FeqN4` zqd>rn>kq?$_5N`jnK9Z{{)iIMc4QypIu!^$D!6=9c0C1c>%Wdwav>r^fO{p>o@CQ! zuH3DCIB+_ zK|NDrs^^VwrH#9|pjfGZa><(K^C@5{=6GDH$}d*-(6F(0F~{?|ri_on{lGCI(?UyM zXMmY=Q$|pAX1Fbwa1?T$ zSZ3DO7;~(0j6`fvKJkq`n9QI?1%WmIoj8iD*&(Ddcxn2!o_#ouuZ`R+tvsTIi3cg6q!AOJ~3K~zv28GNZ~ zHIRARss?b+GQlpyPW$|5d>6dRMJ3PYh3E5q1uy(nrgF%lQNdwupONF>at{vK78q;g zug!2TfsKtB`}v1c;j4Hf&n38H!QHHI6il-m77T`YvP$m#)f(nGEs!=O>4Xdb7C$q% zY*6sRdr@{Q8;=WdXz*87R_T;#jTxfKMvcAN1H8W46s3RUN+}EOLP7P{tE1+fNC@Jh z5)#X13Sx7y;*4y0mLR;1p$z;>7H|zF(^(jEO6P>3SNSS$R+WL10B$aXpu^7!n^4{) z#>il@R0oov^4Kz!0jz~x-0Fx6IEf7 z)oS|)Bu-qFbeH^H3y<3t1W`fOfNmR&BevcMTL=r2f%0=2E}sjsa?#pEl+rDEy0F#~ z`cr~~EQMYA*u|$<6;>3&t!GL0v0~`;Jcw$& zd^T#|yF7Eud7Z>U#LmR4i3MtWxyVhMOuE*h)3{z>^m$$J9mnP6{h(e#lmd6yTGdAU zX0h-n&h= zh`AJNBlvq+S-U1jt)8u#?(sZW)|y#`NCsQ@hNjF&M{fgOGzh!~JB{UFBr~81UZC|$ zfoZlmemsLgEow0t&{pp{27Cmd-6n1|aeY=se6YP)2&Qz|W%e@kDr}BST%g^mEQAF0 zp69827IE&tJ+Eu>QdaU3w(eyK1Ai_@fMe|0WO_|-446^J_IL#hg$`_)wz1t?1X-2= z%Fl#?bfj~5rVhCcodGQ@O`vr^4nrAc9eZ>)>P;ig31XZP)WP z57|~}D4i0WRr0mvKYiT|s}|fvCx_BH0*o^89ZlHrW zgUPpvOEgrPtDHyN*IQPWlNX%r<{YkU7Ml}3j+}#Ld^WjvKg>)?-wvgZo;PQPD1BZp zd0(z$A!C4Lh}d*)o>pKc=V3k9^}9sw@NRFn^fu&A1AeLB))!fJaYzZqF-FPhe5~u4 zt%Vg12j&4E9%b_*$RwG{m4$a}5{I}KFrjEHL z14+-E_vG<4Mq|x$tBe^2dEdjhTYGB9-D6H%Q6s4tVfUtQ2lcGyoG2&i)pP+MrGKn2 zYVuVwXac&s-hko^+{!lvq2wXsn8b~DUIdggkWxUU-T!v0(3J&~tjor)IP8P-*VL8; zaoWx7(uQ^NI=-D-I|b<|*R+)7H5L^}?(=&`V6R?Rb9SI`KYt|wLu|J`X5R(7w19x% zbhDM1#re35taTka{dJY@+O~ul%Hdd!7R@=J3xxEXi_sW(;WYq6;AyssBG<*$|GjcT z1?czDEPc8!-gtjL*Xm}kU@{%x4qr|WUkjN)tdwQVI5r%0Z}To4-lNK2uXc>a7YPDx z1Nfpdy<;`-daevXz6Ifk>gwY2<-B%L+a7zXk%9%8>S9U9 zrH`L!k8s}9_4Y}v>$O-SuWazbG`Sd2Y`}$YCd}D4hhaqZg_2vUA@=(#PpWh7Hg)5( zLo$^gk4I%JKPsTipmOSVc?J+!yH#c7ng-0P*=RY{ljS^lxu92|0NN3pXPHu=xz@6f zFIXr|d^4%i)A7JA%o25&)-~z@W%>iI+?%ckmVsp}EPvbT&)TL<=}vI8`m_m~#ElET zS38rx$5@50omt9bWt}jnOdg9taTglXD9ZuJ37`Ef4Zl)00JSGs`6dF&GNy?WTOW#& z5bO^5Ube>qV?_pxRdVrWJ1Oq*ymp%p5gb^73lkja&|q?&=YE48&R^O|HFvapzCL`2 zZxP7Mx3r<4-(RgCId3#2Mk*Rmw+a3!S)Z?xb{40+7>AntmiOOq9M6+4^S``ynO||= z3GV@A7(95{WHC^Vkj^_FInN;X`f+&re~+Jy6o24a@O#YFHqh55tRbCD zr}E(zdMITsXONYNAzuO@IU=|oP{ zds&grealkT^C_#cstjU_1;{F-<_B_@^H=Z1`Rw=Q`z8+|b{Z%-U-R5zo-L%1eXzRb zexz(IQnfKD`68__q>!s%^0t!PYHsXGqE_sR5Pa1rem>OcDFSv2CfBoM-|+iG?vtGW zO37=+LzR-qet_rI$IOZvb+5rJi_$3o$_eQKX6_1H9y3a}J6HT)$nw^R2UqyT!_3!W zgMl?^&GUQH!x=c&O2Y~)he4es4T}-(U<_@{Uel)J>MCc$d)K-8ahxdxF$bo1XQP%$ zl#&L3kDPz%lvO8%IdC~*ab7rW<2#zIkR`mVXqgTUN@14ND_xH)i_ga(BqEKv?#wBb z*WQmTNEw2})|h5_jgq4)aK8hxZI1R!3lOsij-+}@k-GRO##hIke47d**KH%UA4{O;%nW?PhXes0Q0HVA(N(YZo;7`-T&#GL3%xs?RGV$3dRvK-cuba$ zm|*>`t>S(v2~7U$yK?*(R>1x-FQ9K4`dpx%5FA3CUW*A{?Tfn3tFpIm4Hj7w+f>YL z<-QlCY9WE#YnNB6T`YBHsD-&!@RAK^{eg^Izuq2Lz7z2^&0kBc7xM7-+rsBSe_o5Z zNaNUt&H$^DOw~Qb(v*)V*}8D;)#i=Q8LRv^3{PjH=)k5EC6K$@6t(x*;(b;uc!dKr zFilyWtP{Z`59emuRYKFkdfI0czCfSD7L`M6u2udFI1F{H*k{CAeGtm4$(Vdx+r^=kc}ZEKqk9SVWOfc=only7g#UZ|>>l6y z-uLhafA9zRgp5pTH&k`2!-#d(`PxDSn}`kH2BnQV|DGzb9xu0azud2mO9ndsFlN!#%faYui&TqXcMFD*Z>k9?8E$ zc&PkfX(RbcHcdPv>Y8(degQ5-Od1f&+TyC4-Dbik+h;`wuk%SC-`b|Pu$%bS@_uNL z3J_EF#l7y0+rPBN@_anr@&;)rZ4)*34kP#hYT_hpY+Tx8*6m#a3maiZEyfZWzWdyAEsy2X9`6(pR>3`$jdh zGn^^$DU*RVME!L*on~4jiw~HrXC=^fMl#eStgJoB4El;r?ZNtNJHFy)n^f$A&guelm@BsY=>j&-b+& za6aMwgkxoDvK^VBWgfEe9rGG^K9|#~szr#iG)vG#zf~K`n0KSGXsXW?Io#iQ$?B^d z5h{a32@ zpd*|?IrpWl)!ZMarF!=$B02TAmklBS%1bg^C`-wQvB3>m%w^sgd=(xm1H5=>WVz!b3*h8b&cM>4uY;Vze?UK zf@_-LgX_o`z4%b|_>MWLvx6+z2LLUYoVs1*dAmMaQ0*)nL);-4$r{G3ZiU5UujZlTnP@%84d?u4lC@B^-F%&(|%FF zg1}4&pLGp{)%BJu! z*22Wi5wgzW8q5F=oy!c~h3V)_k!Rn6%7(r;G=sslpz8l)@9TMGS(0j3WcA+XUIqgL z3*jLl1V~6DEHJlUdOvXnzU?L2VkN^h>1do}y_nfYbXJo9161sQ~yO{W3iqYu_wzFI)=@_9H`RQ z%+!v3$Oe2>MFAHwP|sVAkQF;Ep2CD-zz>g-$l+hwfR72EBmC!)xIq`lmd_Q{+5BZm zr5PS$ZToYc=RGnrWOW6;bD!jw#{(}fE2#WgUg{I72gBvp1$3}Hl7Z7U)~Y_ z*AniIQXvM6rGKf5iAi&zgxr^t+U{$gzbgzVn$0nB%z=3>-|#%nTxdyIIz_H({%ZNG zE1)cbfO=dfT@g^NeOBv;=h!)6qslpQK9EGrYCyZfNfT50962`>Pn19;b!qwOxZXG9 z&ft}e4la(Bpr-uhh5`W=VzGpIRM_*Zh*g=~yp`Tgi5JzimO2gnAhw>@sx6q? zd(l>D<*Cz(d^L*H&vS+?H&hm#R6VQ;h$=jtK8puruW9nfav;-Q40u+Yyz{#(K$#)r zS*pV2c4IK{1HL@|yB$CGb3cb)`?X)o1h4-|$G`l`zu+(b@-IJjGycmD8wZ$nwsh($ zhfSRVh>oCr<9~$nUgw-s(8YWilW~W~yUr2N$DCf<^}M$ad2jV^s4(Y@t^SUcTrjAW zhQWO;Xk7PQ0f+%E2#oE~vI^b$P7yL~BjAx08dYZG91grZ4m=(s-q!-Vm&Xyw0}ely zpLfJLGnLVNhuBkDwoKwYi5^;^QWv0V+{lOH7#>(>mBe0HYJl4Tt}!Z7(l&DLvEB<0 zClk;fq2`wsD=1$Cm-zNhma)y`#dmOKDvRIdGX7%Em~aR~ZZBqm(>VWt2!<})K)kP> zqU#6DsD`rw@1xBDvU=Ez7X!?Q`Oj{%m>;qhfUa!bGkeU%=-iXIRk9V^J;jEfksVwC z6myUg~?a!3E$LllB}CCViHwKQXv42%_?hKj89?Nz}Q;{@!96k z?@G`TFd-E{%b?sQB`;uB2ySxM)(#Q$)g{M1Qrncx_Q~2=0zaUQjlL(X!146FmO{)@ zc{+*Fn_W&q+h0fm%Nq$mk1r<%lEF)`>3}4UdGG(?>+WzgA-jO`dai!fK3{{%(T0sL zuEWa7BV6zOMaMQM6xwo(C>Pj1ci;|wkL&%ig~FRXPAcA?Y6~RM{o=MNy z2|MyGH+OBuTX}7a0h>B`W*FznEPh7$%k#P3R|!JyZ#UsKSH?7DYJ|SR%1}P1!JdHo zGbec}uq>YygmN;-%kWqzgycmOy?IW((=(xE5{9ytx3AB46RRtz9GR?f|0-rpdh)*Y ze!8zREIu*ZaGGI6X_({%d0(VkjiL=~6HX1vkT)%{rNv2BS8laLY`cRT?Mt z!@U~jWk%O^dKZsAEN4UVpcim+w7@bENH2F%K;pi^SNn8-bRE5T)mFAL91qm$!(~^c ze7$6kmQ4WGgqeer8p8+1p$ii3EMri{1;D`z?2})a@ewqe;35OQ7T6pX0SeW{;RrEX zy2${kCpbZW3t(k5a@%C+WQ_If?V}dnIkUZ&f{Q@%8MN+I9blEMd>KI@aOq&$(pf8x zHCq|6RmwvC!h`EMBT7GACYR&s<=C9LIIHO(k?F)_UiYg-Ar@Pav<^{AL_NyQ7KR-d zhHD8{h&+-1QpeE_?eEHKNX0^|oQpg1ze0JJeGV`+G+Ld!GtK zI%PIRr4;GDO;fvz+Gm-Rp#E)qxBXiRPwr*_GJB0L#prdNNwu9NCToGy858Btv&MXk z(e@8rZ_CMJfA*|IfLg2(d`NS^bGeJt9tSRn9)(MPAgQ`@Rm zu8!}nL2mGUWQ@2;(9a#*!!;#0?b>=jG7FeEpW9b>OytCif!cX?e};=iTh$?5ggTNI zn>vY6%^BmW9-;t?w2S0#-S+t&Mzb&FSd2rN8*Kg z&xHyc55*aH09XY}j$=)PzD7B{JJsukR@z(lhv<0rp}xfTMK-$TzXcI30pE3 zX($bcjmGyoKE~y?h|X*Y$4l``!Mp zC&ow^z-{n6%EYUG|0a$qCSLG2z8V00SZ>Qxd@2h&q+P@>aVr{AXh7M+KPWCk^&P|% zE|b#R!i>1F$@zUskr-`vOyV7^1uP3Ml(x+G8$0cS$rHY`Clw-5?A7O~)_ewKz+qcZ zd2JuIY>r`!|2_NN{%<;d`Imngzw}GL^s$@qpE}$ffAS}P^1o^?WgaVu0S!}RKn{wf zdCmG3E_Oh0iJ8@2$_HgNOAD*v75ynr)-Z#QbuT|gOvOwL zFu-2(r%l~A%xTy$m8ot|qrIS1N`27Jqay@@UM#Z%mNWuIp#dtH3g+~DS8 zb$?4~Ti+B<7=XviyLXLKy3;F;aCW)?MokR55Tw&#S1S5N1z@`~$=4B}BZJC@m4!xT za%AbmQlljJHY#smOPTK}u*-8YYh0Vo?GQ(oWgF`9?NOp$tPen;cb>aEcRTWj_cE>* z-u*n-sm2Zq_~zt*cba8(cA#$2OVv)&dU_Wk?!A!Zd$f(^Xy~Lj>*3q53={t*SRvNc z1{;;71zQ=y(+vwpuZbWkHGk_p+g0?Z0ojAfZ8+p}vjf{Rs9RhAQ}NOni)<<$^zS-`Ua3dk{2!A3n?kk62W$;?5O-K9#M56w)}>xMJtMa zZ#HBLD4V-1cI-gYHt?7MWzy8*Hy(g4SNl_E$g76-rt!BDn%@-|aVWPCK#weCR1e9( zh}zXvD>96nt+x8ITLZopj$)O;ZYuhs2jn|m`;Q|403ZNKL_t*2LsxA&)OJ@D$qX20JlSA#U>*}=%1Uyp`>A#^ zIoGV^#08=|S(;wU@=c+oGI!nAaYV__c3obu_?acHJmr}fg!Z>|LCIg~QWKKycCQ%> z`l=I2_aQd6O#sI|I$jgoYWj}t?*-GAb6YfJA5u>WN38!kLgKZT!Ls&!1SkF8^lyPrf7OitDvRY4RUviyS-ci8#f z(;<|1pBOgq`uc*`cdv{7!|=dS)rX>ubWES;fQ7TVZ1v25@;p}{=Ey!2Sy~`~ys+yL zjvd(NjmIcXW-tjPTddw6R$B(u>U7!>jy*w}XX#gFDKG8F7FbSk z;BtNYo!}*TchN&VpiFy*PNRBI-scqlVBb=R*womzgMsCGPT7}*9c|G}aPkbC9A#qw zPH0Fez}jQjtK7CMGH4S+7Wi=EkF+B}fAvF}-M%|G7HQ|pml$SIMPyBC9fR^Hl{a>b z4Wyr*0nGT!AU(0`sW%$WFW4wWHyo4w)lG_ zBNnEa8-2WyigeBF|54>JGeFH&-1u^N7oBKHt9~O(d}BKw5Be9{FZQjf zFf4k~<`h5FSf)T!K-t9K0J~j07s*q-{55q8ie8H3%SLzO>Vl0kF+?n6zPAO?1^c8Y zU5J1buGHD_K0*fkCh?&H%eZd+-Q~uM( zU;M>i;P3zb?>}}kzAr}xl>v0!E?7n}bz&UVzhw)|40crfMYj)G6+T9ks9$zPa*Q$E zGjPv}LR~FU2aJGB)LkR}x7yBWX*SwTGnWkI{?7OdvEK5})}23m_<+wp`yAi?&S&_} zXP@Ic-~Jrm`OaqmfKNYt#iyUV;`w}sd7c1XF$OYAd1YoV`+p3NcH6>!0CF$o1R;Vv z#pacHO(4?zR`ng+d6}V%^H$3I4QyXHOua@3Pn1mpXupU73fCt$ZN8p^LEdzK((?dZ zvXqe+gwM{uWf^8J3`E%Du#d*J1%ITC%|^7uSGM!k-yu$tEqBuI%4A1_P0P&i5&SsU zDrB%2XxioJcs`}#QpQQwg39weR|42`RWW-$&%!u47BylNkFA%GtJ?_cUp)L2&dudC z@c_&`lHfRAh4sjqV<35=!LAE2tlZHBC{Gztfw8axfkE;B`+%fwNjV{zg4NH;zDZvKl+{Epzzi|Va*xsdSZFY%NwlAOtnn7TBD&j1 zfFjBo_xc4YP=Ly`CLPrz`0AfCcpkqcwqt*owM@Xbn*7BIu76{3U-AuUw(gCC6HtIn zUK2s&EOAMBkfE_Rme;THJgU!KeovYcU#Om}JNy2aq8ZP3^(2>h>_z?70xO*)>$*?w zUtFEf5{Q^Ke2IURq?|c{t!srLx}fV(qOa`BO{XmRrR$Eu5WO#oFN9oqj~p0nU?{=V zB{?242pmTFUG}DRHgH1!Y3m#LAWNcx`YzhJZGX}FEAOO_8Dc_2kJ3oF~w&ZWm#Cigrm6Z1SL(rZak3EE{)aW+~|=U(wZjGdY_j=5Jk z^B!0pIZmFVL7EE9Wn6WbmWOJniY*&I>J9R@-ul@wfbv1LENwo}?&CM#mwwZ8nN)Bj z%K=5NhIO{~Q--ADZ4!bGQrZi0WDs$YY3XKQWmL>z7#=dL+kl+C3^XSNba8{{!WRi* z*ev`?yv@bT86_1wa2=tWgTx}Q6~1r3$}uc#?s^`t<6v3k1CQf@$MJ~8;M{Zk8JYY? zF1kReXtw_-42CFg>{qERg%_4^zj)=Q^>OtzCv{lA3xybQx)dl>GiQgZY@Wo#-j}T>{-3~CBiB@1**;_GS zMbpG^%Z@ePw@qB4{35c=r7zc*S8lSF!q(@kds@NMZUA+xX zSosEcE`(WE1wHj0ffl+3eK1~M*fo8pc-MaDxn3{GH}A!u_0mra5cP%o8Cdq< z-&T<-%I#v6-u?3U?{WO_5C1T}{`Ifp$A0X`K6X?7)5kyl<3Hk?-~8ssZpQcRXjKzv zsO8w_+i2I2-*;a-ZSx_E*CkWgMpS|TRvB!Rww>;40j2w@Xu<6`(pjNBh~O;sk2%JS zHTr|!u}hwKepnpOru ze)ub&;Q5tL;PZs}#4&)E$GBuEk9ZG261YIlLH$2Gh2GHt?R@}BryvAS2Xp&83wi=7;T%cEVbx9XMz z=9x0V>T(@zawR8Lr6@yT(FrUbw3Q{j%9qc4&V;W@f(#sI@}$NrSpNNq4l<=gzqF6vqz^MQuL7`T@uK(2ERg{vQPyou6Cv8=21f+lf`93f?(UBbz<;l;5c119) zx0C8enEy_I2#(4b3I%smiLX-5=m7F^FOp)pWNbHux;5}-a6LwnMZ=)flwy-Jer6viqKCYc(nA>V?^eZphtI3FI)E#L=MAX!TY#0wUC#~w6( zmiuqE>!+vS?<;QZ2jzx_$>^KHHW5nwe7QlLuQ@piZy#6fGFZ>q_Zd7SAiD=S7O6CgtYAu4wkK+IXFmq0v;!I^wStgKb zLhr5d^qSnAC+2B5C%`Heq*v}05{}GyVrBH&DMpNwy(WB66DTvYlwC5G}v8X4cX{UZvt8i;s+0+m{4VO0a`)z~* zu^0)te6&WkTxv#=)cTo@uVG4}+ z3dG{t#Pe&iYk2rbW5igE+;*Xl)$M3)V?orh{?)cqy|^ZCR)R^YI2@dF^L$E1EnFX^XSOO#!kTYsvr_%m&fp}a$uo6G>EfQ9e0^1?cxo{pth}qiRV3b7c&y67^LD0(6`~Dk z&EClNZd??=sz^HqiTiD^qv&izV(bUynslvT!I1vUc;<|S2Yt=02i7UPLA>6(QM70i z)KayAIMAK-d_1O*eAyhz_TFc2l90TW{^c$}PL-G*Z^(%SzCh}>mA)c=BjrhTp71|G zcha*3lvi~N06CBJH66^fKhv&*v{`P11kN@*+{M*0(2mbxvzXiDC`TT%6PZ%6y z052~C?_M7gNM88zkn-2H#+1Qj0KOK(*b$W%23CT}q58NdCoLG#@z5ZBTapLLCp3YY zISS>6K*kr7ev?>$^i>Lr6kh-x+o_aVph+{eJ!Av!=)ncnqSm;F#7&0n7rl_-oO6< zz=U^4;A>e7(hgeto$e-Ar0Y_cGU#baPcKZ?ZV~SzzqgIgI+jS@5v;4YSMSN=@pwEE zYp-&_bFGBsK9s_M`yF(`YV*-IQdKL-lvl#x>U`wH(TaiFuw=UZ7IgLq?kohko^|uk zL{Ds+d>}|hZx_oEY361VXr0YWP_|E47QpP&ifsG>y6yzI)uvJ`S=sB z)2mZ7`}q~fO4~PtuD>eeeezuz z_R4N?>eB|^=kr(#DGivm@8@q@@~Pl)l%Adh&Wd)aYxwiuudo z6`g@Q8g!j*W|*hNicS`~>h<+iWo_k8)cCUV`CVOa`jY-!+qo;tz4f%2 zswYcdjzOSi73cu4bh@@8em6|-THl*EKXMM3*q?#(7#QckInFj&)9sh9Qa2(8#;jzW z7(u@V?ky;`gFlkxik$dC?$5xuuPlgF4v8|wYf0BHGH6kXN~#;!T+1-s9mA~lwokfQ zZZCludzX7G<;d)U*%yL^Oj55IE1$#+)0-2YDNjLzr8q$+B=zK`BX+Z#v~^GVG~Tp! znP4c=PukbAU)S}0i-@|@jwgA2!vm;3>-xt_`$e$V-|MQvOxHe{{MRR$x6io#Z6i(p z?5LQsQD-$PQCL^ne{Wr?S0q%*`kM{_sv?5b`9iWCH_<=H;EPy6(x(=Igx&Wc4s2xB zowdT)3=6}`KDT@(u_kThoHL)70cG8X)n`@SXFe{PMh(M4ImrVQ%@!-mb|$B6~>H~a6&UoQ8ki2}60 zn-IhicAfIqCKJ%dRWXXtysj7Q$#V9IEr`*OG^?&snyD{XS)|@6?OfnhVqSWwEhe?X zt?PAUmg&e6yTbdeL!Dj-`s~{(jM$n6NmHd!=vrS}wyce+*OHF`Zxy_baYQwuhxE0- z!kudslb``+*pgpZ2G_{jE1(S6h#+jtMeerdsuLrFIP@ZUCGmO$_>+Id)*7z&8_ez| zEvaYH50h#mwA~xOB?cL5kwD@P(c_S3lfAkb$^k0*lJ_q`;QB!H0JZ#E)y3V_b3p;y)Rv;}X5H7^#Q4Ow}q*2JmJ=p!$t zi|la=iW=>AeFDKV+H$`Jk{k9B8hry6;NJ5+bI7(5sM0=f7Dc)Em^p*0&`3RiB2Qu zT^Rs;J|lzl1KxlB9uCJR?_coY!v{Q{Pn^$ZF81V;*GoT#Zk|8}mFLpTha++2ssxuS zkkj7RmMJE5i@TG)Lvf~J*zhr`i+OthS!u_)$WpQ3_M>iV!mj&nZ=~DpxHFW+Yw2f{ z!y&Khq2tW=w}P$p9NwSv5#3(S7B46RtLMDqpnQa#UbfAWk9~4$7R!p2xez$3OX+Lo zJOImJ8*F8|54ra(dFkKWllZ$M`MS=W7JcHaJ3y9L zW~uDs7@4uW_C{S3-_smpEa5&5A*S`dv?0i`Zdb&3)kWoG)ZbJvRe`I1zBnegWjAkL zX<$m;hE7^+nabCRfm--*xqfVI+Dv)i$@OyKUBVLPt(O{ zRWeSE1bK8~G8+VZ=ElDbJPF^%e>4_r&xG~o$r7z?tRh>(YuuNDF1|F;c_W;9kE@%^ zZf%g;Zbm#+cz$xZRuzU_{=XjUZo4V+?Tot1(#WJ!tk>rl%bhN5=ViAFtbvWBH?Ote z1*LTx--*d(Gf~c*mr<`G4gVB|;!Rh@IQBHgo*@$Tk^M zZoBC69HZj$CLjBa<(D~uOC4q=&Qzb6AkF46aGXb#8a*q}lNd)q^>m!)6VK-ZkH-_w z^Thc)a7L-WRzYR2%pd_M0^06?nb36r0~p-nd<4@Zt%FWuU$J|&4Jjis=E*IRp1LH6- zOPu>!&-UB(o#I7;{jP(GkKHKe%axlE4EObA8)py;8TnQ84Rt{*cHllW-N`8&6Q5G< zEDQ!kN%?}1^@hFMAGVKO?^6~HIsVBTDJKx#E4{u;e9(4!yRRo5)P`~;w(5}XKjOkm+6FC^ z#?P(E$nGUCQyz&4k7Hz8<}vV?N7Kb!f0o_OV9}QGcSL2Z<2dq_@_z9LK~whdj?phC}Bb$7qXevxKyiJ*=uxqL=sfiTzG_ zA-_V}zmH9h?{;b(q3t?;KghOaJJjdYo9}3@-9eugXA8%-E1N7c8#!LN6+q}bxr5Rq zWiok$HiYf4-lRsO(vyCAoUCF=MkGkW2u6EAk z=H$*d3;tIB-)cl1blLO>SZ!@R$dr%KzuIe+6&^fHu5DS-cpKJt=1m8xxl2vsi zNGCR1x=>cQXp$HcC8zs55$~RX7O5_kvSUhH!3jzsY3q_rE&^W3D{x)By{2>L6dzeJ zP6NQ3&yd&&@VCkfeR=#qj-UP6pT)2L`mbkY(Eo{tyW@}l_>b`q|L_kVyD2}AqvJl? z{ziR;3Y;0h#Fw?Nan!HK%6Ig2tT5ODDGg4T+@E?TZBAU{VXJZu$4v05iPyu<73>zdov zwvPU8X7FiQkZ6%57TFAoMP5kVN^gz+%JL^x)iMVz$$f3EBPpyJ+2s7f1%;fNUe@^s z&ZQULyo&+p<9qdF0&oYbcr+~J+u)-rSzrtdOn`9V5!(DI8Voe)D-|9gRu7D zOtqU;Z);RM@6`sXJ*U6B^v9zQsi-$WO~n9FTSee{pAdQ?=>P$EUJnuQT+CA}Mx-mu z&47O@#M(QshC(L&_KAz&rIEqaqDca9i@l(*u3;usmc1T5sJv?7$DRn>+kp-`DQx|H z7o^4$Ry=W;#FaLyaV+`qHhx+%x|MCb(4?FMkS5!E+edj^?{_V|wPieSC94}Kv7%MN zi(#;F;D}O1SJT$P2GU+w^8LYa<}ax5tp}nkKCivD!hugC8Fck2YM>@%)WK6x$fnY{ znoH47D}BMet<Zc=TOX|O zGSZpu^0KmMDw|~hm}8bMLV#&sdP28!SPe>TSauMiH)VJy95Al_kFq&4%Ky#a+gO1~ zV0Ur4qrW4wVv%y1<3xQeGMA=_03a3j6-@Gh*#nHLJ63k)A2l?csy6Y^l?7%JRW$S&(uqR z=uoq?gDh!U`>M_cBHMNz(ZzC1B72zpKkn=T$0GE4>U-s>cmdKstr$^33=Jd<$#$u7 z*~}JNpU)`k^JGAP0cHs*_u$CNhOQE*2Of{LzveiYiB(v_gbs>P$hYj1mUJrK4INk}&OUR?nvRE+U4M_lBhe zqwbhQZFx3XEFk8A8QCb*!X>-ybNBwTl-pUtX$e~k4e9Hj_7+I!g^|s zi-G&lI)LLCaDRX@J;uP}cmM$WkGijo8mBjov=-wWmfxzf z#Y%PR*~~7sMgRS|d=5$VmZ`n8I`s#YN!L*qeL@UpmWUuw8WO7|94t>WWuN{IRzP|1 zZ(fVuI7g$4MC(p+=ySY$6|ETX0bl#t*E-hyA9lDq{`61(6o38KfBmtW z@&h>(f2y5PO=GE}J(a1){8;(oif_fAq8^@N_Zv2&KJ5CuYxvMjnTS)BEUG<)4_vk& zOLW2{ABf(WvA8A{7nO-Jm>n>4yuQ5PlTY4d#niRf{Q-B!r=Py!(@$RU>8G!FeSKMh zIV*eD?X+QK10YN$amb=AtJLhi=<-uoWzhg%<(7?ozFYL3hPCwcx~CGpF+gg2-)O0e zewLoyd;x6FNBKt0C&8leYES@l&UYvt@~S#QlRTodx!Z_D0<7(Oh|%O#pV7Z(9~%~} z&&4}R)Bo44PZhVAd`25jCc3dTXwR+SHIw*`V_?oBz8lFSyT94vG~BwX`=cCJE(*x& zkM*3#16mIJirI{tF z581G;!V8x`Uo!ainyY^K;AFzEEFZ_!;?bHApTO779}Koz$UYl*SpP`GOdn{mUFL( zj(TQDRP2$udfp6r_PgFGtrsJpSqXy%Hk>s_uKcSuh>UfQubugJnU*7E0OPGOt7Dh( zFaEqw(DUXjcSb;2;6q^y1c2P=b8I?6^eu#@2r*Y#+(A!fA+mH=lS3)z<;aQ3>A;XJ z@=9NZ18h4%y;Fxl=godhIP9DYEZKy?FEpZ~z)Cbm)Umwc+UI!6d#$`L9^5hF+InuSR9{)G{cw>>VlAn}UxL!@^TiInZ5Na0=7gUoCV(?a0v2xS0p+!a__>W|w{3HtsJ&!o>?J#a zIhJgW5mmMlMCWbx?7`AECGXMgi$780s^ctn)EqvlfmBs@ocG z?>FBlmTCSs5-%ohqqAi7oD7?~WK``<%+Jct+N!uMzstqqimmH?T~B%NoJcpg__x#p z(uj+ZEr8(rwW$NG;UdzgM4a+kxDH0X$WW7Bsb*jL?(pz8QkI-prQ43?^Sic1@2NIt zW$-y}Nbu$H13A9-wXfk9fAJSTb~C=`~EnaRz1e9}8xMj)UW_uEc#vGi-;&@q1 zx-cK``tpMF-I~8Vj)9lQ1Mgm6;Xd*D`oQb!1MglRczJnTGL@Gv(F4p&=dE|n#kyCL zkTPF3=V1r5Kw}VKtz{K>>`| zmj>E}KlMKJzoVmRD%UN*P}sV~ z2m+7a6So#l1RVs$sf9c45S+88si9toMf}*SOtGu8H)k+$Z&l5ga za^Qq!x71U(;(-9Nh(p26>_w~+H55E)Wq0x#_!qE7WfknE+h!WnK@evWn*(#_&n2Jq z!1AJ7fl4yW>Qm8kWyMYS851F=!%qf$Yv0%XU3jEun2Nr%qq66Y*^s+pn`mgbJ6^Wvo-#KGSU)g{oCZ588kvl3nRLvBi@ zImsF%=m7%@q1E?YlrAhIw4~AF1X?;5;8==bmvfF#I!>ZgJjajDB$eIDhya4ma{1a) z;`$r|w(%BYD2A*Sq;Nkb>6b5^H0jaJ39j^N<;jvSHK?L4nYd=DaEt#bW@#2V?%JNW z&aIy}l_@%~P6|fpxZaDXZ)49fZZ~a5GY;F`ZTnoe6@C$2w~ljV|NEKxs7lc7Z4A2S zIMkjK4D_hu+jJ~(%HC1|M5fsawsilJ@8Z$4MKgyw_IK$*waVvs=S!tb4ignL0TKU5 zKn9p;=|`?qU%%y|pb9LPebp?+h0!A8U4qLxWSxhXC@dLs*w7ua6m*rtkYI>(&F=+A zD8L&Pylgft!H%`|6^*>VxEE#r1*%5`*)3J#(pprMW#Pjos=kZ(t<>SEdJg)tT-zTP-6VK-p@85sGhY#=Z{{4rQ;TV(u{&-}E zXs6r)*GOR5qOX;SR#|9!aQTRZeY440of9L86;$qSd>`hwoR2M=dop;C?`Q5qo7igh z;PUEAO}HOYHhg7#@EKD51ceRx8G+kiQEJ$05^?bpuM?h%(n|Z7A>M~(MJGX&E$ezj z|16b6x38dc0E>y|Ma;cirtcH0D=e@Bj8+Mc=s=s!uEvg5XWGJgBzb`4euu4uCXm{Hy4@i-FCnj!Sd z3tprA^)Zf(o|LN!+ETZ788f`uu(-$WZ|MYettzkJvI&j&f3p=FGtAgHvm3a?x4aa> z9U>E{Loa>a3CzcK+w$f)%7;-bMS2-5gO6Oe!U_=cte|qcm+;22pXzVm(hl-)RS%*M zQG3{D5L*IZbIz=+)T(mDPLqTlbl{n(oboyD#VPsbs`D;7adaAYUvv~-yU<%~b>Y>*#p#2lf1{P6x=iji0;c>9xi9270R5(M zh_9GSk?~cq!pL4Fv%z4H_c4l5)X+}QHUA%Ja6jN0B>r19G z`;)7UsLyC~EPaVK`Q>%ebUqn{=dJf5FL{Yw%@(h;%2K}dtNHsoa&zBw@+m8@VU=1> zzNtp1t;Fs9Zu%F0&#Fa0x-Uf&&;B-BfC@0yXC(iFnBRK9-Q$`pm6$lC+rAxtW)Pxr zZ|5bpsc?_TIQveMONQioBiGe#Dam>p`$0Ph-|Qdxoc3C-p?s!2kId%W6FTG}M?0`; z4yBB{=WuO29i1>4n~se{uL&*4!Nva?SnhNy9b-j@c(|6oX7*HH;9A(F-I_XM!{(ad z{pIn4JIoBf`m4W+uYUEbAG;~v)8X#;vp@SY{P~~%`NwX`5B5li-)#_p)cd6`3zy7k zFs%5>WH5Kz1`wbf*_4Q*JHgdyGoVQLzOl&Y6`+mcz+p;N+<=(7zt=ueT z@vS-aBa+TuUS8n7wqJaCIq>e?D?a`79o*;I#)O%k$H4J;1CzH!RhC+lL0@;f1fL7H zkSvbrhT#^pryiu9F5iTtE6W_XB7CM^e!8%O?>5PMwYr*%MOGf_K7I|Fd+|}uYapI& z9Vs-x)S#B&D)H5mUzOHv(Wlss>`O6~wwd(1%uUF)MM9*qwTTIZlZ7AC4tE#>vusH8 zz4(?~OFloM;!(;W)Sp0pZt*0I4T(K>$U*=V7OJ4~L#niT;{gD-@v7NjI8SZHaz`^p@*>uR>xQfpL1Y1SNmp~p-hLR0K2?#nsB+!_FluVU~fDld;&*71w zY_Ms`5L9vmoWqCkueWnLsWXCL%zQASH7L^vC~E_*3WE$Hiq$D-Ccmrl!n|Y$(B(qZ zN}ufGM6HZXfawjqO@g`^uXAEPC;W`kQs)XZ3t8IW!=!9)lyBFJ*Pg9x0Jx%C$_#MR za?Nf}MxcMe)fnT#*j*V3l2%%aK<*{h)43Ib0gW^q_M1u;R<$h z%i*4(yboJ7>~t^Z)lW5Aay~8f2c(StI0h`rj@m4KTIr{@%3o9AraVxYs=?+@OLr{x z5{D<9Dk}WoJ@TCJBG0L4`-JFv)>N{)%j$hYbtFx)j7*Hr-S?MawEc>k^Zwbl&nkLX z*&stY+-3m`FnhV$s^<){_41W5A$#+TqG{L{$X>E2Xhs8>dvQl#IkR;ogH!jIA9L}x zMZGRl!%4p158GRCr&LNl_q>OdNx?nH;w6AjgPDBiJ{z2SSaMJUmrs!M;RcK-XN=ez zaBwVWzj>ZhAL8g2#}O-lxQhB^>|@oz4*N#l;7OJ^^w=dU0?Q`X@GZ-+nTc+)u!n%z zz%f>)^6Seh-o1N=ckkY<>tzpMUF-z0t_h6LOFZi$l*%?f@Zq_F$;b1+@!`P9zO)wr zoS5?44{qNVPQA~5&;bg0@W4x%0iw^QCR44yTL2Xh ze$>4FjzM)x3$;h2d+Ga{wA4wv3w<){wwy7gW4&fO=QAO=Dxa~jVD`m|`vh@k_RQrl zT(%5Z_vu%sG`aA$6&)Q|a%W*{6qoy2{-WX?5AD&Q*?(s zf1@=-{#+eO%l;Hrsn%&5h;ypc2A)}5?uR~=h*m%Hn%WZ!yO`5 z%wWut`_C%9uNW@dOFO|upW-w(IYhMyUYNngz?fBv7GO~M>^k2k4j=Hb#(Qm%!kW#i zKO^)V_o`ppG`wATf{RRZv3B@Kca!t(j^h!*Go$l2su$xP0T!3+ z0g=ew?XJoJ>A>$xV@pFVaA?|ePCQ!5x7@AnPuQTmlVeg3$|kF?V}tA8gioxG+dfVr z5;s;7l=}-T56g?mv%{D4v3vuP229pYuLE`DCMZvt=>_N{yy-i~_KO;0+mBN31P_yKZu(yQ z7B|V+U-&5)}pa{7F-3HJ%iN2MIUX(j< zdZV5zI9Gh5@)Kt1boL^!8yL_NUt*eLIC3s!Ver__Xbjj(l)Qd9@a}v~yt)>qp|E?Z zRKLut6U!S$W+t=zHF6$+SPq*;rTtianlrE|@f1+~33^l4^4qJX7W=VrfclO)ms8sa z)tnA7oBC-rf?`vgu^<8u4sr(S=g(iI$l!jPn=vYUe6eY19<3|<#^Q?(x1urnBC2>vfJf51F@L( z7&smSkMqEElleH$a~P!Bk;LD$LQ~jo9siPB4V<(5%HF zB_7Ad#7M_vk-tv@Bp|zSoT0?aatJF+#bQ(&Kn~_jVYUEtM*I{L&Eas6v62D0sOG1U z0vaVN(+XR1oJmS5WypaXu&Jb4?ET zIaApxQyUOW7ONOM7~2g+4N% zt1CEc`%Ic8xDH`x6HWPB?tvgQk@E~}W~uF7?)|!2eZ=I=yu1U5GKwp(%#w=7A)Bj{ zV!{(D8#Dk^iaSqgkmn-iE;6{?YfZA3Foe(2Us~ z+qmJPUq?Hq?rT4jc2Pd3S?ph4RY~d@7ZVt|W1sZnp2}QM7kaC09*DCo)aIQPaGef7{`ay*JB*Z36V0Nc9J`JKL(XQ;PcNv$7i2?hSz8Z zyfQwHF{0F_rQ@Ulm^J>E<#=BrGduT@j`q~~$Vu5#v&^DgX$OT026fB@prhK;CW^Ea z?d&qGrD4?(NQ_ksDYB<>ZH4=w0p%WCPMw|lchf=SJzLM@-iHnJ6Fb3H#_BHjraW8$ zWuGg^vImp--Q`^-rjfK&S-Cl`*u1Hm#I}^pyR1hL{}ghgjPF>o(L}S%`F+xE|J%Hr zYhZ8?J0&)JKU*lnEzw;X5^W=Aw?bsbyEJ zW#l9=d08<;WGs`%slR9g&}Du4TyqpY7Ju0YJx~2ux^cHJoJ_nT&%7{HBLm93j=$e7 z7y9lvR(*uD{kC+mC!Z}$t#|FXB1tOF0B_bFztKAy8w+pK4sLz6_R;e8I()&f)k!gd zc^&Orzv0%fYMaY<9BXXv-M>WHP?c}(oG-?6xB#F2{9QZl^h@%oO=MfdegSH$wdHaz z>o_+{hPn%wTklF=5NIWF>lA=tcYBjeNzwBHXgg(_ML0 zzPEnp4Hefw{0@A1{2-3U?#0 zf%uH=Q(_+p-YvN0YkFoNlb;Gtl#WYC*yCW|L4Q@MVi0p%TI)O;`P z>B15QUt1kdgCEp=QOzyz_2cm9pOAL9`3z#&>z>NQfQk#{k1>wyu2r{VB=}0~ zjhY9cZ8rnB2Y1S5Gp33x#Xr&b*cOwBo`UHjq-pw+k7MzbuORxI%lDc@suE1DSe8K- z8khr^CC6*b%1=q!+|dpKPp7S5dIBf*TL^1ot?Jj{oF#!gChWz*&l?n&6Fl0OkP|xX z-fVmbeF?IMr289#`0SHureMj=rW=|k!2S9N>X{eeNZXWIa%Lz$Dv-pjgHI{OQ)b# zScQ)ullowlyU~@YgN_4BA=lnmd{BvIIsdCFu;+JolhO;|#AHDPM2;DO92&xqg;Qj; z_V}CR-0H3)p zSH}LiAL(#v{WSSy^1WpAc(zw`5`)Ca-d^7eu+369Jcr2S4MiP&T$?Lzcr(y)y-#&G zfnV60PK@k1YGDm;V5!T~d3MiR7-oVnpfdG!Ar8;y^elTlr%4IyYB1S2ZJQ&&f#vHM z29K%$yPYUYQ-s&7d^&;>Dm`F`Ux zSlG=(<%{3i1iW!VZe21Kct8fP%wq3U<)!=PDNa~H7$g>9iD}Pj66-%Zfiv#y?sz#L zIM0`*uQ)+EXJ(SE{VtDMKtX!Ui4*(`=mMK&r$*p`IdP5?$2f4FvA{=kCv`5fg(;G0 z6LajU&(KkE$`?ew(B)0>2le4F3?J*ahT6jq`kW+o_20K=34TcUD8D_&zKg9Gb4ga;-q#<}p%Yx03kZ+VFkqViDS}*%uGdJv;w!#usVd4;s@OYh zyA;7fSN(_^|1!V;W#|X zhjEO~QO}46QfGCXU;gBk7S$fx19@6qYU8y;0YhzWUm%-$TX-g~)jnqMyP4XQ&!wV+ z<~a_`@Ldb3#&h6lA3~&-ec+uMhB7XEA};r}w;QqboJ}W`d9OYm$AC{M5swH455sY; zzds*q%Z3Nbv4w7Z90yfV@CNP88pDG@cd6cVkbcA|99v-X2Wz3RX1~0N1x?05$uYX_UVocS;U-L!I#1`^|||pSL`bPr%9434oz3i#Hi%m(qB7~ z8?CD=%H)`8n~Q1xA47a}TqqDs{+$;F@1wy&u(|z{?g}yrgbN;B1Te3=mg+ z0k-lRymxb{1|7Kw>#FL4z$SBHQd*q%?OQ*JpWUoV>C-k3o<1G7F!W9L-t;w|M_Ztn z#mIuk zv`@Sb|Hbc^Kvr}iU4<^ZZ{wT79o)C^j95mSQ#K907ahq1#<{r2wja|lhb)4XMb~_^ zk)NDRD}=Y>w|X82<~r^Uz#oRk(l%AbEBGKC%e6Y!bMl2PNs_n6p-yW7$Ni+MO< z-vPWuW8FRE|GYtOLir+*zNJp#BtoqKoSSk$b4&-8vbAH~eqd#ZxlPQYfF_;v6b4SF zURL;1iR(TB%=AL-&9!BQHbs{m+wMI!!AQMhBCj$5z@U?4erMl>>3I(erX#E9+g#;3?9(|s#2_XlS`dNx>r$3$?F@##S-!Us^Qa_6rNk-5poEV z%jNT6fVn1$7vNvAa!v!zm64E>Q8Zs-=q5Ze6e(AG)>uuJ!GJMOoacct&Rj)fVIat7 zQ;Y;xn4PCA3^~t~-#bIP=pdzvl|03SWlV$@lbM8|p8xluOGj(7wijdkrtf6!N!LNV zx#8VsyrF`8|I%;T<+)v?3sW(m9J#;X1mhaUn%EjP7=umOumGBzyiJ{-a;P#{#=o^R zhtoU#WUONDoveEy8@op>o-)vGSRjjgeY5PB0y@$lb$_-irh+D?dpsX8TQHf9|HL$d zMMnILm6tR(ysz%T?Cv=syE0f7fH>S^+#SW%omdv2nFV2OFl(Hdy}f^zlC()vAubW8 zoagTwXySL;B;KvEqPZS(j1l_^>z;*+W-HLbThOj}1~qd?b9j4}a+b9AKEci=5u_z< zF|2Xo{=SgOo9vV2D%s;vC3II%JO~sMOqgeY;fXob0V0}O@5gZl=#he;UJ>(@mT zw09M!79f^!Y8b@P^mf;+Rm!I1YysMZnKqmxO{whs&d~zZdx_8;} z)hFHOxt>R-)nu>g0??Zpjd8WWc1d0<^hrktu*^tl5-0s=DvfeN9kKyJwa*-*=@SDZ zN~dCLgZVd1z??dE$ILaEvMs3rJ}}Gn6hDy-r+x?!m%saaCko`!N7t0pjB@ z9Or?@q+k8OIcEfv*Wy_QhmWHwgaCq%VjMa7S9E1{04rQaT@^H}(&3|>_X(?#+rpij zeC6Mfv{KApCHeXyNZJHsUy>0w9^3W4_5O%qF04j9xyr~6pO`1dYqq~5&%D}Fj3tm( zzwHMnduMKGF>~uIE?Cn=YctDF_kQra^L3}uu9hed8BmTu~>wS4)sg$ z;64GJy;RK0Bn}NIhu+OGOe{sNvOZ?)wOaUU}1F^ z{h0a`rAySFudUZ&e$Xan+X9J+Xr5JVK0KdrU)XQWS*=Pztim#EVh(RQap8oBLm4oP zIMs0sTP1)W$J!g2f#q>Pt#42RKrO=2#h8fCV@&uQtK_8Ej>1<##~V!3Xi7ttu1d7Q zca4d5qh(HsU)Q)us4r+@Wp5e+$fjOxoxa}4Oi!d?$hGa-KmDp(tLpO}^iCiT^4QhS ztvQ*|5kmT5%)TvtEE~^x9`ruOb!nTew?qAdoCn$QN&;2s3lVQ#%S5XIw~698(v-9l z1e7>FFgQGu;)YeMQWsXF&m%qwp`JI|#(0ha*6lPMhBiLcHSU`|P}k~Qea?yKFRkw3 zu(0orM--@B43Pqabpv04M}o%;s*zyRF)5P(Tb4K!Ihj!7gFG+iPFH`|*awiCj*|lp zTiwoau1==2;3Y)5Ki3K-KQqIzfTV6_zDk^#)jk0zHp2GEcJR3~8q)w=Q|OBsvc22& z?x_6<*^d+y8B(JVQ`pDK9Wh^^_E_br3+(HJ6r_x^W@@NVUCW13S+QiROS^CnR>=tjj>S?WFO zn)lDa580{D!Wj^#4&?xECuI!ES7DzJiauQ-&yqSuj>;lIe#Sa|+N-p8d5lE}m)J=K-jw_G z`_Pvty*bZoP??j3V=Qp4?*IeQ-pW_Hdju{AjyW)AWE6Sm7mioqpx}3EYKSp*$*$@t z(lx4K%IjvGhlC9irSNx-tNkL~31*ZpGPqpZY;e-P_+jY~jy#Mad zY?O25q}Z2XhB+4{rcU&OSVp%?sM4lcQXZkJZ1I%K{CmZyt7gpTtl`t0@z4aUpj+t86*liEn04YWhyT(9pJ#l5r@(iazW$UgvQ|n)sp6eY~r?*`%dL|voc=_N& zw&HkG>a?Ni`ndjBc5k;^D4a$6l>1thy>BGuX(#~7;4X`apJb+@`y91uJ$=nNRu+Q< zwl8$gPm05O8?{Y^3$91fMer}jf&u0Vfc8w~{4BxbYd~4`q@#SkRi?~NhuhLmS%G4D z3vh6O=gRsRt8De5i>@l5%+HE*)aT^Abx+%x#HbS9I0k?NhPAMK&Vl1GG3P^gWL5UM z28oA=g!Vb~(CF9aZ$$T(JRoJ_HcR;~JNf3jJtHAyYO|@i$YE%SzR~PSpWNE*o_9f(FtpO^0>Bwy; zN)LIO)`Ew@r?GgC{%KY|p>E3lX)C0%L;f3i??xTkD#`#S-MU#9`p{}$jMX+)SF&ac z6;Iv$<}&=&Aa!aeTbj*oo@VWnyz@q)Z@#GQos+Jd^@iaV3=?w``B;%R`P}@m-9}un zlsu+2#KEobn(XEI9q$*ms_SY|JiKo+ux~j~dQ*MfO>YRM1j>%Gx{S}cvWB9Y=9Rp{ z>$}a~@S>8*Q41s{Hr^nU3lAn;ZdpNZkDB;aE&bN--ui1iN%d^_Ld&*}#uM$Ae!~D? z9{**>ul&ld;HQ83r$2TxzNh1#|M{Qs`@jGD_}72^*N@$lkA57Fm!*T5oDd5G!FdT! z?T4y1RQO|`OMnsQOCk^vK$`>Tl~c`Dpm!R;z%LKtnDd-#o3PLWa~?5gb-<6BcR0q# z$|>63+}qfqAZudOg*%VOi0U}C=rgUF;4{8g-x0P!w!9h@sAM0iLy&e|_3Bj{(sq^) z)lh*de)>La*yy%Cm4D)gZH|-A;mC+zr?xMB;-n2O*qlCH@1R#0NHyda$8 zL5HO#2@6&;`vjY#oz0vxH|=iBoj|Js%9KFMzaxpo$puve2x2SvC(|u>7THWDWXjb3 zP<*F2P3PL5ivi}^_qGSF0ANOTHs{93V8sgCU}?S1NR%UDw~&JzXyBo0>8{ouE~DO_Cb^tJD~w0RUob3TRSRy*{a0! z-Y$71^>YwJ#i@Z5I+I5EeG0gahdMw)*LGgeyBiy&g>7RNx7hlld-Imh_Li&XC7*OA z;x__*AG$aIWg>e4#^FQxwLlzu>Sk%KMGlQM&rg zOIn{rcJF>Kf8&IW%Zv0H7y$rf3}t_%b$v{LyQ5Z`j~h8FnQmjFW_)j7$bnN{)Sfim zB|~L<-!IZ7UskUd53Rl1)-6WCHM4BPUEn6^!N9Uhmhw3-=VJgfK!Zn?G8cHPj3O?O zszp%8ao{lz%wxbG2YeojHe+PgGb=R=0Wqb^dTAI9DCfAdBg#fXQ$Z3JULjU1!C}Ohh`+d6;x(l4V7^}gFY*Ze5B4X+cQ#Q zg8Mi+FE(E1BdVmO;7%c*Ck2UlcI06&XqH?Hh_(ClyCNMMIj8>8tKD1wcFm8d+k1OwY@Nt`0*lwZ9huk}094VFu=Dn6^7*v2&fO8kg85?Hv z<$F?hSMeRoo9Tqt5^qm)L0wFn(X*Bn-%Zq%n?emh8=7ry2n|xev7q92|)1PB@vU~Ev0#)l;2P(tz%j5fU z{QS@VJihwXuYT-id{4*U{_Wr58{hZ_KKtymkKL627RT}OfB|bB3G}(9YR&WssjuBV z=L-s#6fVj+RI%N}5m|WwjuAV&uK5v`y^bIt7c-(Vg3oi}e4h9)KCJJK3HKv(@d2#0 z^Ei(K57Fxjc9eg{K=NAeXgCgwYJH;u%yAwRkoVFsW1KZ71C%Won|=5K{Iq(w|6kvy zY7a^!Cfo3EHUd#e%_3?(19+Kbm7KJdt`D?)rG40Jd4;ZLHuN<25tT zS@%hr8c8YR8FrPvryA5JD+eW>k$|$!Q%L*n;$~U(S*!L*X7_bmS3@s;lw?RZo)bDL zM0}LE^?R%HgBx}sGg=>o6jT@r+{C$p7&ByWO-sFzz>WDQGa{C(`535jwuW@X!WmaZ zHe(g;GvA-N5_fJw#)1=*?ib5cVbcgQ4|ythe+L(X$Wgvoua z_zL$odAkdQk#Mre+XZdOzBnoVe+1cp@xA5!Y@}{?xN#aQf+;lE=M=~ zxar^RuZq-hm#)i*PYPJ%H~B-8_bceC7c+_}A0x)9Pukf=@9)z7ts@#7V!vodR)Srh zOu61i^ljdjN|RukljyZiaj?DIqk?k2gczTzOrlwST1g)&QTy>Njqy}LYlZy#;|d#+-PGJ!JZXFKjuB8kqZ|$BFlgCpsdUh@@j?#`V9XI2 z(7qPUps8E5;fm_f#a=lM>)ih$@`w4Bpn&hq#j2QX``PySKXxG&IttbX?Ly_`VQ z-)?f7{pu8;d5s=}6VyAAb{k}qi#v)|7o9}?k>g$XmpY2a(i0L;j`G+01Z$qp?Q`;( z;eo)>U?%=@%r$Pvg%f2T>wkT-=wvw|BYy)~wAthVLe$&ONwORJ=}2#ce5}BipT#ay z2ZOdq`CJ^uEYm1BB=(otn^4cX(Sc3wGy8f0twbn^iKM@xi**5F4=O7@u*7R6^LUGJ z$zyq*b{ZuIQo)H^jm*%IZHR;>TJb0sl~`}*{z?ULCuP-KVKw$D6i&Cqa+HJ9m;5oawN=Pvt8H7eX-yZOZx|-@ zb?WDkjZA;tD&?$7pZ;r<+fOTYQ=(U$%33FiQ(a-Om~rFMbUhjjvF(?r=Pm;COnu$3 zny9F){;H90b?z+OFp0^NE{(5XGOAx>Oc`pTi>-W#y{%gXS@s$)`u)BwoIj3{?1{vK zGxb?!;&|9w>%=pdA`#QgU-8chC{HUn;dZj}3TZB^iF|B-C7ePB~%9k(;D%g%Dl3@lG6OO&dI57Rs*+nHqj zT68k;KP2`6S{ZS>JV#y-`v}x$)N!6Ne|<|0vaSoq^ZSl@3dh*(k2v57m-nnsqjV1I zI;E zD3+kp0h!5fK?EayUTybcv1B`=uuzBcNN@+JK^61*hR0TK1{)i)RwIl=yn1>k8c+-> zI~+3^Aeaia(lbtiN-p3u&nE z%-Sqo8hc}7lBYeUZcHTCL!A=}?Bz{qh|4>evUG>EtT$7)W!kiZtJF}ylh*>ii}ylc z!==t>=X|r(`?U^FjtdBHtI@=M=(AeYn6c!UdXD2?#}i5sSoL)Vk6o@w=?_v+v5qFTR=M(u|#n@odGmn0$0(oZ=!#e@Va8J91>C^(RGkr(B>+fJ|L^(gDL*HBS~3=V|bOp?JMJoEMnfM^Y*teqsB02UZ9@OTH-mF2OP&4 ze@CQ`w(N^FqtsIOsUsM|Bj!>UXK>qZf#uy9MH+b+Cgk_zJzx7!6ZA7p_i?TuxH@(9 z9hz!%?FnD|S*nB!WCD&sf=zWA18YyE<2Z4i>(Bj6U8q4cj>FQI`dP->lh~miZ927_ z!Kyb)F9@!HJPS+u+tBm6_lT9=M+B6Q#DxC%r{hy-rMM!SlN_ z!6SHYwkAxh?K)7{n@x0YD@)*|3vTC+GK~a3PoJ=fht<5Qi1@k72L9^%BdHJMo)k`X zW5XOdj+dU|TzZ7gU~teRh{E=?e*0K~-mV=U0f`Nz=$O;rblk`a$%B(G8ohS?iF7!` zDOcn*A)R(bmo}7-&3?*>PfJcUovo}K&MAz6F+C^paI(34qs-_KD*)O{K z2R3MLBrt!F)7nl=DOWmj2!D;FW5)s2M`Oh5>1dOWN^z$8;D*08*>A~%{r~l-IzO1o zy2f4Fx>C08E2gWKpX^y!1-g51nRd90x#X+e(RHMKI>yNDvzR7Yc}Ye@zm##Km^vM_ z6TqBnLN2khZu28)%5O)?OW)GgS9)_DgC_hl=fwN_`@`QWSN~-D1BY?%Lo=(1_c3Of zzTH$fld&6FI?YY{Jml^*C+vFR6?B?5OGkR~5Zg42T3b0yeFcaiS2D6hxZodd+16}5 zQ~{eb*TePgB41nMAKsB|QT_HLKIMyb|E>}G81CQoHY=@o?Tv1|W!j~yta_>$SRxOw zk4FS93a4zNz@|?1-D(OJE)v|c;o_%anp~C1Qu8W((Z`Lq@>mC64lyaZE!M-p-41ql% zuiuH=%yhG?cj@gR_>v`e>_Qgu$NvBJ_-T&gIPm+w|NAMof8LJky6~5O`Iq?Hzx~^9 zx+*_&$9bNBJ1!CMKIV##n92ysHsXO}jlNNsggDiWT9Y2=_-7uIgeT@47+5-aU}XAV z29(XpbF|D-U;6xYrR`I;8B*O1Gt5(D?@}ijOE^ZQxIQE0^?6jRVZ;h%UIVD@E;dXs zUZs-~Z~4U7?Pe0YDWL~h`fyGhAmvTJ5|cEg8utA3u=P>;gxju|`%V4^l5XG7Cqh4I z`6arbW&3=)9ziGC@tcJ%Rd_H&^p`Yv`rngnrxUbL-I8xx)t1F-sq@4Cx#3BmbY8

y@1@jQgMoLl@&)B+zQ@^Hhel(zJIP7q7hyOLIsrdFC6z*rNZXfg;_hh$w&RG zE{M&nlQ;lmWk>wOt)03GNB1^sazy|voln6CEDPdv5e8>Bry(Biul;<9i81v5*mF8(vCcjtRQmiwV39&QMWqK(1e)R}vC51BPp zCU`2d=Hyf7nfK2R6i}h}NFg&lZH?Tut~!ir3_-u!%FU9TU-<*QJ!vE8q2yBP?xIP5 zo-e3+_P?jLd~lQ%`k|V4;5K>ax%B(Djdo_@+*;|OSJ{?8gmqfZrBbFhx?80Wr;-KM zSfhgv!dVQ=m+UOy1U~KC`D>0ERYkw`$pG8rxyTo6b?pxM2rh4Du2jCRYn@X!P1s>g zH&k%h@p{eJ?`}qFLXIivpLP|zchq;5L9L=>_D3lC#+~fTxr~MB2DrhZeW}>x5f(kY zoZ(8B29UB|EN0U+Z3UC+IF%nUiGeBiAmubvD$i`Ik_$6DrFISejWRU|r1GA!g{iO4 z~#b7Ke}-I_w4axK$nXOrUCJnV!|=fX$gWO7&#xgVdeq?ZSSnx;4G3 zj(M|KnHa0kG47cbj55>`SNg*lW_`u0;z&bISaGd80hG2NK2Hn&7%_{~eeFpc!6HuX z_89M6G-JbHZZKa#SFXj%Y^$iAxA6#F(dO<#?2a%mQ*JzEiw zL%8~b{ie2!;LP@&%0I($^o@~c_p$Ur=v0gJgiD??RbjNJh??Im_BjAwTb`uDA=|X2 z{APb_e8hG&rcIX9)!pT|*y+@0udAUqeo0x>`b==eUf+j00}y^bI{(N7r|F?5ChNHO zXN@vqTa!Lt_luum%M8#aJIJI5l}I9ra~vd2kQK}O80Rs)Rx0b?b-l2>9LM5`Vcnr= za^C5Tz=}GFXv3=cI2*9ZTk1FU>!^Rn24#6XoOtc|P}$7lK_8O7*&m+Eul4?ZW3%mC z-}OL%Y;Wku+xH*0Md2a8xP7N}jo*m{_Y772v4%o$p9-~=4ax+U>-`|F8X#MB5YsZt zp~^M2t6E7y|>8vaLDQ49pF$BaPAaaGDQV&>5!(M#USCDI1zD1j{p46|HPmE>7U}C{^_5->8kup9^9tH!mnVv@e)Uq zuk?w?AQiQP(mglJL2TdnJS^8;WI%aDmIfC;3?f)&%vN`mti(z~ZSz{T&J?U^#E2s^ zvYp3)^Bg$OI1gq7vpf&(RT{Kh?ECn_Uy+uOVyGPJgh)vyFl& zs9&fXeR^ap+;!KQ@HxZpqM42AJ*6iot9R*YR&spl;m~IrZl;Y!J5F)7;=k^%>)1Xs zJKb>k{ZIK#x8EvqazPWx==U;s_G)*+7Sh@$921xWbHwEL#AH&Be4h2&>Erc2eOI1C zM+0k;8P=qW+}=gEM4WZa73FC|-c}($(JyFyjNDF`x^}p%YL52YG<7j#+3dpm-M^1A zlB2Q14Cm+1pKjI(on5!1dS!h~14*0*a^}iin^=xdVHRbsRhUI2ef_CTLSY6(o87@p z<=e~!uF%NUC>me}FtJknO$g%&*BEe&0|)m3Vbx+FH|N5rYZ~&`7`Toj9msHx)Xo%) z<$NioD-o_VZKO`HRfd}yan0G1!mbERcE@Q^Hn!?e!4J`R>apFOXhmYlD0pyg<_LBu+H^13n_ITp00+4lHyoz z<8>{;PUqX@_511uFM8)$;De3Od#o_iN7B)G{5~h$Qqc3ul-W}2tHkB3*epdctiqRuN8?oJ{+)^ zwK_b&&~S_~p(}z(NA}K|Y4=(gJGjb5##MDGbxvW2sP7T9F$QRk8T3kJ(nRY=bt_CP z0gsJW0Rx8NkoI)khlWp@(W1@)wohcMkI-3-*Vpgks7Zp$$euFMVZCQW7MXlD-+4cq z-6VAKj%S}zF3w!l3ZIxZFetn>D4`R=vp?m$3_!||Xn6zlMWcqLv~GGwls$cgRMsl% zd#hACvu@rDdXI^)YV(9lEp(RO8!RWv9>d{>V1$sJoXPBAl==q_gmfgN(k-1`LbCK8 z?I5;i`jTTyb{$=Qij7eGD8??w{E(pIW*fG#AoR)Wv<=i&7=8TIBh?SiatFqkSZmR@ zpt7uPT?lIAv$0VJxP^@NcG)u9c0zHc!|TZH2x^7-a<=pd#hKEMHtg(^rPo$7V@*Pc z{#+AW6sPs;S{*&0E5KnJhHDtDzBAfmX4z(ibnN#QRF(lH`PgM^g~)XH5WD4JQnfTb|4*H?_YTJrFV%(D{<`PD+nLX$S z@mcmj%4X3|%hp|TxbPu`QMY|c3i-YuH$=Q(GH@?tEL$2Y1J)do>VN3Htkz~HiM>P_ zy)d)oBz}srDc-Fc&qJMogXNNWGOA zm~7W;Wi#IVK0|T2WT28vLAA&+{HrK9^MqaWtF9lt)KZpGeNhy&dR8Ds`4NZ*x0h9y zL_ectZ&SM#R(xRmY>mkl)-eme!0Jm~olIY0%TSg29&P)X{ENVGWm#k9Sn^Jn2d?&? zGGEYz_Gb*|zz3FeO57zFK#L@1I6r^>ylt0JY?f@-uvo8EewMFk)Lrv}UBH!uulo{& zX~UGmlW#0RQ5%G5gcq1$+L~G|HcQ}guS;i;2*Mba&UQKkGLTAVn9VjjKph2imK|d` zVXmWQ2xsc7qo;XZO{_tHcHKL>Q9gls0luv#dN1VwD1ntA7X=cVu;e@RnO?2_!Kwz$ zkcTw^QYqqks>F2<%2`cgMx4&~nT$f2*iV?kN%@So?FOWa=yBHFQDedD88xb!V}DaP zA3&cs(6oa zg0)A4w|TkOMwN^xZc_(TbeeC;Hw#zMPP2JAT2;acd zbW!x=H$H21S(PlXmtSxDhMD}|8f{6Tb|@)HbAvskDDCvD2cyrc0gVlJolyGK9FIX;|`q z*MnRgUBL>~1(m?6qX^_Ur>4a^dc+o;uxl#3d~R0pA0G1*k*LJ042E1T&9 z!{-vBKH;{4dkuf>jaKJ_TobE~ zM2U4KW?B7AKJ)yJL|fuCW)*XA*^XSz2OSBuaC(bBQ9e($1UZ( zrUI)~TV&k(1QL!NLj~aMj`7W~uVl}$qOxYIbJ;6Ipv4a|qQG>r>#miS6xf5xRnHnn zL*(nw5<&4WqyNnM_Afl=zV@8lqbrwNhN`;en9N}E1U$y;6uWi>m1}i-!cMtfT@&rtQn|8hw9r0%=<}=TPhGq1hZ*7rtd1A2JDijH7LNz`$m6$f)=*}?Aoz_22p2DKwIC_+{&?>G9Q}_ zBy`bs$~AQs$7`mx9=0$@Oj;XzfcZFDKsi^L$2JEgYc~4rof&oD#JlNrE`LrxuljnV zs`RbjEPsF0)c_Fb64!W|+mCu*^;egx=zJt^_SVr`!KoDQ_dM6OmyPWnm#Z>wgr^nz z7t@qb%K}L=Bv0`=9h><=hxf*1yOJ06HK@;7h||uTSopb8qTX@d^VsS5YOBu&rrKV-hy^rlc+SXya$mJA15}os-p=l1n_AK9bKk0Kalq}DGsGAuO6Vz zFXT9`n$q?KK8gBkn@gS$TM^GhT{4&)={r-Ng+Da0=z5Q`MF1~+d;H%Wzx%tto4Wbu z>G;Qg{73xRpZyuW`s%B1x+*`@N7+KN$%a%pwnmu^2WF&I_R`N`YQ}!=F@ZL|TcW@p z1Iv^N18XnkF+3;XIj|P*VaM)3>fL6qu>M2v2(b2t9cz;P+ljX~29@LdcHr$ia2%!c z*P;*&BSzVxqufiPr3`JWL?>!dfY#SVjxQQ0E#j4;r^NPDoG$;VPUvK&jE%A;mML#@ z`3oY0An|@pM6Ah&S57qOrK_Ibb%O(m=QG>v(`2cz2O17M>mQwoLf<873WkZW?A)kqT)P_%galFQ7@mL0w zr`W{VXEEL~i)FVdkE7db*(B6NghUilS6bZZAqmV#{FPgGcuhbf-#U^^*$;pN132G4 zzinVu29aEI0Ff~)Ngj=`ogo0bY~}mE46qBjSKUxX^OSDe04(rP%va#k#7Lzh$2Z|H zb8v;>o*AS@F?l#-*-?iEydAk>iUN!I{TV3sxJMa;d!UU|X0PXr_8wGL;MO4T)@in% zn{bkArC}NhVldpE-AWeWX)>U+hws?^349}*1(inZ7&5b21Y9#n*k90@j*e0~rF^n7 z1Ce4VmiW7@G;jZRBPrX%8Cdz%CeY%;o`1hN-8OO%y6c;$*z~xOF{M0#wi*!kn|ty{ zmqPl;hJIsd*TjnCy*5Q_8Z5nRxo-7ZE=-r<;@J6~g+DkS zDd2gJwkrd&otF9CE%!Emv274!W3sIpSb$RrN_+Dk^1NgjJEQl&KH_x3!>W$!$NV2j zH=gm~v3Nk*659+wC|)PhK>2G^@xowt--XI5-mK{Xdtf=+(F;jF;i}bZPS{-LaqTxO zpb)Jqdwo%Iai5q_`|)XTIRdS=63~!r+&6}SWp6=dU|x~R`nn>Gb)DxJ7?)!lj$?SF zJzeGQ!DNEQy;BvWmqW&p`{w`^P)4j|bc+<3i#ADOuOQW0Ew%R1u`wc`n44H+Kk{=1 zow6UikLh5al>Op(QE{TOb-IPKhu8I45a&DMO_5iQ)DeqX0H}J2ju*=+F((GvVHBz3jo^uJB zwI{9^hq-bP5&(%6&2!FhT;7I_R9$qsq+=b17Fg!kyr~nddh(=8;5PQ~jI05M2!^kj z148evdyzVr{l_uY>o75EWxj`|+8av@!+PZmcTc`7J#2x62YL3y-h0${4o zZ;$_*<5z$6SMh7V_G{mCHU3A3yW~9;=i`lsQ7@@UfIrkzpjyVjmWkSt)$a2f4g1UYE=J{?aS9h*Vz65KRE@g!iH%6Z}yFl900?Q9LKmARk z-`{*u={psS3dO8-UF}s$-E~CKvTDxkD~U8MQ3j~-SZ?87@*-r+)D6Y*Vl&5gEf}8Q zM|@(Y-BVbid|jxFV>xzv?2s)|aK){6ZUJTS*;p>q4_YPsDVmYT$Y+YN91HWAaZ^j? z?-IPB?2^Ea1AKjVe*XM9Wd}iM-&Z6YizHm8Fs{|Sckma4F@s&~495#cf}~8rfT|EX zTX-tVsfMuA%h1+*_|-X*iZoCX^9LpL6XiIuW4X;`MKY`{2D4y*+( zF^ipnB$;uR#r%3ugyWZKZ0+(2HoydJ(l?lNY%giTf?;Le}g2HV=Px0Utk2n* zx1dle8lZSy`)d{I?S;X+g6q0tW zb>(Fs89lK4;X!#j*Q%b&9JnS9ub}ci@uLBjym;avY%}Q;C`k%mo9Q@9xxl?K7)-wC z_;<|LN?rYmy^+`7N>?+F17kRj>6iyrKshp3YcRRe+RQsG+|h%Z+RkXLkJy_w^f-Vq zxIeNdn-zbrECY)U6E?#!MX;6qZLMefYTa@UR(kPuui}x`AcB}!p-h=u!DI)(JtF6F zVn!edFwCo`Uuzj9rZ?Y0{g9FTDkQz+& zmlZbX7(r#V{`EuOr@)%H?@FDk4o6gfOY>VQMYC`^A6V(q4~zrbDiFC2W~BkVW0giz zwG6Tzl=VoNpN1(y4qEYBER3zTB(CkW*E*DnFFI0B^mE8lH5|lv$QEugvO1fEcYb23 z!HMEsR~i6CgT$_VT=I(Jm$h91;`KRKAx7%4wQ>;4+5eJs`!17?u#ID?14pZC8Smla zFio$0=TH4ggVMFN&62?*#{L)s69dEOAW^fv#zc-K`DG7KP&FHT1(p#Q#4B)Nd`^O* zOm#n}q&p*zadtD1nIfP@dg#Ezk0)wmW)A914{WSx+mrHJ&hDP+oTmg% z8B{*EfaQ5`0|Le9^?%2erTe-MLUqLl1oImA#artwx3k>8uW0G1U41Ku-xcq&ew1ak zXL1i9b3E)@Wh9+NC&L)z3jYFiuLE{a7ie4hb@BCB6AsaX{MG;49@E6c{1dxP?YGjg z_5uqN$$L4Tbl-7C4Ch=UtS7SaTa7Kt zLH2v~JzvFf3XyB*bcWKt`m4q_lDD+%-VZyrclj>vcdWp2(swC#riV`2P_AYtXev)x zslOXEzV~s}N2{j%9X*<#cX?8_1@(gJi=vTO)2)rp2I_uiS>;Z_vh#HO#_Bjk>T+8c zsp@xSW`P!54vb_l?Sl2cBm4K;e)<0~G zl`UnZzOL2E5mbIV@#!tLXo|&WD;wSN837@Cd@TBaOF-`UgZA}xO^ib(!!WKy`5Jn` zvK;D3k=QKHMW$~HE{h`cr|?_V3x&@zql)+3qxpuM%UzrMpBgOnw2(#KX zxjI~NE~*dJrWg7;Dy!JMw2z8c(tcMAt+tuiTAB7*{)pew^~3*(5%`_SA8!e=PeI)= zg$v&QG7;>J9GY6iElr%vmgHNLZa|&^5t80cBVN$^cxf?n)7< zjuZ=EvBpk84l57Cb~rQ$lMbg4u-)MEmI9mmHd{E>hYcLYjo=k@3lN(X^fDj^-Epkk z{>wqZ@nAJBtOC!+8HRdXmt!wSc?}Y)IuxS{X{uM()lJgW2x+pT--PDGl&|%^1l&6C zWB?MU??yS56jPezK1|1n^EhI~Uz&Jn{BSmMejlqbUe^UgUiunnrS#T2!%36`+0GmA z)^>jk|NBk*3S|ZQG*s5Lsa>)e5vbod(s#+5HW7uNyhr=U+9wn=ke4?G5kU}EqGy_G ztz?}Gk7&YnDu5efmdr{gqsXvSm@!sGuOA3SAGcn}7diUg&Wi#;4{AW2m0t3r#&Vofhldf` z_(1R650i&Wad%;(4(5A#JKH`5maEde9+Vm@ZI1)7a@T>{(@7>o>A2YmTwtrOKBAM& z#&$M3n3=K{4V1QEat4=UZ{%y@^?pfEc{$Kl>YxL2`U)tI)g*YVX1TmpDPNTaFbEgC zw)TMCWkkwK80_#hDI@x1*pU7&;`D3fAv!hJh)&0~3Gd~&3P6)GzIeX6Q~=n<3vFu) zpYX{5H-q^rMR7WooXSon7I>{_fopk%Q&PU}Y_>sVUAHt#;*_RL zRDHZ=UXet#a&AyuD;ljmMoHy{}EmO{zKoM4;Cejw1bzbIlA-{YuH; zfy*!(j{N|s=h!394=X)Cf)9GOl&(rBV_j?#t`N*gW3eJ{3;;e-M-*3jeW$#aedujG zCBldll@%1GhALjHw5@%j$j+1eye7u^T2L+gYQu2&0UWr|!l?_!8iz~&Z4;<6Ba>%8 znyqaQ9OV=k4$#4%D{as7D8n@Cyf`NVi5gVOfMW3;ul1Q+%@`{i%?wurk=Dej*V2XK zwN~%S5XfNw#2hQ_y}7S_jHCoPs;` ze{=4*@SfBCUw z*a>SZm0bv;s%8!MmFk}~eN1&N6T;ix)|$aU^lM>Hc~|yX_3utV8`p7_>NCe0cX?)l#7vjIO1cik|fOx78Rf7lpLp48d^PZM>q zUGtl}Ltn@yyxuWj!&Az~vv0q$`e)()r2|~#1i~J$mbn5GfKAzF86rq}1)GVN{god# zd7gr9edd@$(YVoH##5JFH9<&aPLW6Xz228J)b_LYyD1`=zA#n#CWi8V$@LsxifuQ1 zlMN?5s?zdJJ-^GA8)j)ZS|`$5=f2PZr3;dJjgLu)Zs$~XM_{ap)hyJ#Y#GT&(I(E$ zY8l5xty=DV^zHG#KYsBSe-YpN-uJ%gYW&2GTqQ*dFs|dd$#Ov z;?RXZ-&Roh?Zl^8rTq5k#4!fkulQr^DzY~jfXS`XRy`*~zBjw{;ZHN*u2pM=Ujmy5 z&<%PbV?~a*KV)sUQ5Iotb_=c641$)O%4`lzCjbq5F55_SLF#U`L*w1z(@EZtEp2)* zSyn8M?f2U%<(hCzqNHqZdYPwPN6PiLDb_g9PfTr2+ z%xG7jH2SY>lEx#^Ps;QajQ(;DbeRxY7;T~2?2f#hXW(4brn0yUDF)3&`^K%*^D z)C`V0PHm99@rnQ=hpq-;FqtbFL}=wIWx%HaM>u#m!*{Gy3!QQ69f(;$G~|xx%=0`~ z<(RCTsl2g3*uf3u<$Rp7O54g2Py@Z3Q4|KZV;?PBwcGbk22F3`<1@BDpI{m7T*eHV zA>(cpQ09!IFnos%*<-KH(=BH}((s$H5xu*IBZrCy={Qth7L-$H*Et@ z&6RjZ))%QvS6a0GzMBzDC(UjI$L#76=`8^&QjrP41DcYNJW**SOJL7PTR?@CWM-?9 zO+whmefpb{q8n^t9&XpFv}ja+oe?GWA@y95nsO+tedz%p)tjMK=#Bcdx< z&Z8q?1uacL6Zt9w$rppn4vzry#g)qO_b$QZc}3dO&`n&e48$IOT-h4eIYSkF3>`jN zLlgHVM~vW=0i&}hS1eFoiTrOR>6rzK6Px-gyU5#l$A3Jxi4RZ~XZuz_c?FqeQtB_}wZhpOcnN?`R6V9xy0iD*W$gfv2{YkMHN$m+XmdK=yrR z&6vDq#Y>KtX85R~l-C?LVVqqt16bOg_i8<~zp!{}O^|T-;W$DmmYgl4tLtOYsqI?c zw|%ax0)1l0fn(_p9Qh0#&80UW7bs&%jHab~>b+Vgt;=4oYsAX3t8@r4YuO^Dr-l-B z8*esA4}`pT0Gx@87=O{OQ8Y+XCuKmj<-UbSr60DKWO<$^-rnAt49{mdxkGVzGsad= z!$~vAel%Cg`jNx2CKDAsdpUfz0?LcN)bBQewkWRme3qj@@St3I-s4oQSqIBLQ<_T6 zb{wNYWo!m1={PFAdf6Z$JC4o;d>7Nij*F6Q$Lswa@9*z;Ki)CMJM10FgS*;Z@?xz# zSUNu>ns+By@uOwibWB^0=~|_{m{j(3bB9|w$A}}+*=16;)db^QU2$8fERKL<3o0|S zRjyj*gt0DnezM~(LsH#M&p3QDHAEJ&zmKtaVU7P!`1JOMx3@Q(`$|=DZs=>RIsxtz zuh$uYU8~sp;jl4 z9$apYE|qBrEZJ6Z1nv}kxZ@7e;PqMo<*&Z_g0H@O0Z@}dm_pvna2$?to$!nd#dQ3(&IPl(Ev*wD z+`ZD9!!RsXbA_BM4AmD*5GQ(OH+rsSy2QzksQL=LLXJGwt|G4{4A*470cRiB>rdf$eq4}-My+qnGp`00<|{LSC|F+P`{o#Q|L z<3I5I?|&aZ{NWG3>8kwP9ZtJY{auLRMBf9Dfo0<3eVmouv$8Vz5DbkjF{?a;LG6r0 zwG`WH|Con5Z#HN7bS&#-Ax{~TIp1QX@_7apJ@F|5%*SDvlM5;quCxf%5K7MptbL!$ zS5zu#v)!(Vd6Z9ue#YS%AV$^G$_MIR?bC%H`W*34Qdh5&!jdZ4`$D$4og0pE>DoAt z$V#OXqbjq|j^D)I6WghLU7L?oCmOe4^4R>NrGK0Liht%ZDO3QGUTd35w3&Q1`Kn`0 z+WxzmVSg!(suz)7NV+i_4?#_%pM011N5|8yyAtaz--U&G{CT^D5Y4bj}2xG?cnnBBu_Yhy~BmJB}I+A^RXJazxU}R;PYCw#> zvL{!t?-=FaGp>f9BS6a~D2q-u->y0ER%1+<<~U+y$T`EI&lO`6*Xu${A^KXYZ&o^L zt{&#~2sx<$ZV`Hz;qB9!F;l_OWoWH>6I~TU4_mYInf99LwK=<=jFTciZ5pqjqDxTD z<>dPpjhFJUC@-(|$6I;*1A(fhH`c+|wpK-fW{Szh$ibA{A31`=;CCDd(WgU%+1jsq z!2L+3wiL`rr)D$~K&keUcim+^^$IKY@_i5 zTXX{kKH)a1ugq2YJ~xVr&P%W)P2~aosD{S+jAvT3b2tVZYerf;Xl5{vw3Q*$dQdq8 zwHh{(dQnpn_dsSfl$;;xYZ*_{S)Mci0$F99Z)0Wq%C_?(oueBv1fO+c$so{Vv0FiqS(_!YeRvvSu@%x3>`wOr4 zwbEj3?Xvi4*nl5~F#ywjviCDow@IP?#me0?kjcVcwM;6aGAlbb)6~dP+2nO z<(Q)!8U>83oF5z`O4F)Sv6F(6-^nn9T8TQgK&QZ_W%e2Ae@GLLF6 zagNGXYp=NDo#ceJwkYUhfQ`T!h&{kV=1PhoA`fB@t<>VNl@fYxX{h;b&wA>0ucH}a zRZ#S(8IY^EY7CEb&ZUHI=fT`!K!KKDiokMCzj% z`_%&#_?Q!ya}t>B!?lh5)Vy5zh?UVNC+Orv9VGvDp6rKaAJRY$urfm++cVbcQmZTy z-FWjQXXnIq9ysTL>o{?q6XP19A1UXMe62XdqAwiJGu@dsxj$D1`kWKT40%5f9M`(O zq>S9J)%A}$P4TT>>i8@@+-5f)41AXSELtsIn?5n70mGJ41`(7rET;|D*rns9%ZPQo zPqtxD*~}uH`U|g%X|KgTys^_7*IYH6-@D3jBwe&FN3``k4&dgRMSkdxb>eYWQ=h@Od)Deh`0)X(^oQWB)>xkb( z*CtPnl;2EKoq=amdT{oU+8(xbno(D%F|g5b7x#&y6JwPO%YCSW2P*5%mG~ve5#!5I z{Hc>TblWtoH!)$-T`J$4dQpeheBqi`wqDCj(=Wz6+q=H%li5`!G=7x26*LfAOZ!9G zfRsj_`X`a5v8?2tESxf&y2%5Bk|vflsZKL_Z(@SE{4x`j>RrcD>Yb!Zlw6Rxh=#jf z(DpM3k{Igt`})oH3dbdFed2zj?UH2N_*!{1>HT$w;3wjJ#mxFqu^(l?KG}q{7A#%b zY{QmPR&unCM?)@HU^W6yAlXxpX4b91pk=pM|Bgh}vDIYF_Q#s5EY-}AoBmvUNc~Q4 zL8te($4_^d8Ghq8e&d_2#!qzo=tn=oAO7JV;@|%5-@fUp{9GQ_^;)u?6W~%l15LSX zmzB7(v}Eci$`ug@X@l>F16>G;o@89CX&%a}vP0*bc%k(7moH!N)mLBP)7u;V`%_G2 zd^_Ru!kll3@s@poW$*a~pKG=9%C4q*i?VgMJ5#wnAAHXHN0tBU6#hX_-y%QP!@RvF z))%otCWa3*WhMV5ZiGBbog|;+b)^CYLve+%`Ukc@Ce$LOW+>ZN6SmF#N^7?(k=K#iiLTK;E26?jfiiJ6G z^7a10`}+&8*Ub8mzu5LMVgV|7?p!(@V79DS!T)yRQ?x_<1nDE$ZJ<`)@c9{H=D`HQ z$4wg6-q<95@hFUT_o&4PSbT6YA2eruE8<*C87VRofRJW0)6{PEN=l;v5`wcuR$!Ij zqNh_aSni96`&o#=H%V0qIf z8sHOSUYLd@L?unN0g=IQ&B*X$!hM8xV%p4Y_79ZbI4IYQq~#E1dd5~=m4#x2YFlru zOa;(?5Ccog7DI$I%;EJ+AV5bDfx$+fyi*NliR_oG>&sm}gzEKZeC$v^g*f^>X?Q=O zi98!P!J?e#FL-8u}9d7JC*BH0iwCm;zb)2T&q)~(MoE=6+9Me5V$hd2pDbY zB{PG~r9?G-_515uE3Ur0gOj7oj^Ow8`EbWYhyHosye?d?a|MmLqKoHn#=ARSuU9&8 z%?uX|uuHMt8b7f`!@R~ye@J~04uy0q6hdhIL4HrUnzwwNM(Ia)R7$z3=l0icMoHC& zAaJd0yukh*a84wV@~L@QkG2w1(xx`h?mD7W=CP{XY1jkI;&5W6RWBz2;sddj1jG0s z+hN=IMbe-Q483kEnBL3t?)JL9H$}Kt zpOdImN4Z**dZrt0U7v2)0k-xYj(cawpK+|+&(iLuGyyQ7bW6(_q`uB4o~ zI_@Pa=jNQ4xdTtsx-tH`&H%xP^tfZ-m?N;FQgV&))C)XP&UXiQ540NG_`Shw_MjcA zeKf4bbuFW99=MJJ=P_~32*k*{vj?JYvd;w5>|-K>W$s)5*54Qd$5ktMbutm1Lw!YL zrDAIVFp&*69S6_%>Z)S)@i@2_Y7v;6UA-BM>##ItK+#&=sRC_)4QJY)vZYHKmcFw1~)?y1Z_39KJnwH$km5o@O7h`h@FkaOzRJPFRj_S+3gg)DHa@gjVk zI+QvS5dgdlSK+ZFuGK0(9!ed?|1E8-=v)t1)XI~_rE04={ z%Y@){tqv9PW#ieMe*rpV`UIBXSM2u+zc&oP_XsmrWwZXtOKBU4UKoqFkLj3xr1K{G zQ#vsnO~+Xo1&H_L-Lh*~qhm?k4WKDj68iC8s;%rJkx{k!N7MdAn(x^s7qHw#56d&< zNB!03W>~O4WYtCSP+_B0kM;i7^%D6!WKUfFiAE9|H05~c_C2Vauun+f(3}|KR$suW^R(n0AUYU@XdvcN-v`I$x;Ch zW+Hji6W9qQhsw4M9W41RGAurKW1=`agX{DSDD5BKE1iI{ENa|UGZU27N2OKbtCB-E z9n)Uw+jak+r`@kL{Kz(GmNvEhT04Zh)E}AtSfQm@TJl`{t}<};@qhnY4af-)+Cv|9 z#<$1+2aFZ{wcU5y`m{OCtN!XNy>AK>5r{olXos{Gs@^Sag;N~}XY`q5yb zZd{kf@8bW&3S4*-g3eUWK9w0*Sl_JDLTy^=bws_dD|F0Q*yhVuU+~r27recF72B^Y ze;K#r;`U%>T%Z_xCi@k^<#nyW=YlNO{9rx)bZeDhH_~XMtBK^NQrK78?S%$bYA`Gv z9%9oq^`W>cC~fIsmRDK52ZB>Z`37n-ocgfpy5StrcOSG!+7{GlSWJVwj zaIOlFv;iF=1Dt72&`H|rHS#xQL=`qlrGk$%KQ{P#*F85~R6y2g!dNdi`-t}?2>15G zqU%a;jR_1*pU6HAUKk_z;7EZ%!KA{Ge3*MoBq0>&lc+iBif)Z) zLMXxZ6nu+J{RfZ#wfIMJ%L;wHi*0eOhgX}|S`trM|HLR=NlMxPjcyS7>G37DcRv#fF>z1SW^T1{sg31#`@QXgyqv4DE$b#?_5mgAZLS-O4-7GYF?__nWQMiJEx`^zCkCIn z^=mXxstn|PO8l#D~eApyMI4xYz52_gJCK zzqLwftxjJ1RUR1Q1OObzh2y$#%_CDC&MUT-7$dfmD2L#TRVpugb>RD2eY?76jsFRU zUCSwyI4S6rd!)(gW((ry7-&OB91FK$AR{JpKaoRS*PQ`T;)@jY%_&$8l29Pwh$5%Y zIU^-$rM|X&hjkfDo{&|k3d&Vw?sZK*7ah?9%6dlXE9IpeuaxC9GUC*nbH1mft^jjY za^1J%5e+8y)s5HczjSs6$R0)e{$6AN*P1h`WJU!9_?`=M#?}@m4ZkzC_&8&Aqt~BT z_LxSjq!W^6OH6xp&c=f|Q709t^s5xefbw)ydak%V_s%TM69fnzru;yTl!rqUXA@Ve z?qqKUIG15itI#+GOnFUupBR!IWajW;7;^>q$kXiKok!Csh!<8nVqB$+=*Ejq(ps4t zE-)~3&56q|;lX{Xz@0=k42O-iT062?=<^UK8O+O205o^0*=ZdBy5N3k;|H>5wwz z51xFg7OA-D>z$)k)9Omb>T8Yy>JqFBGO)F+#B$hu4FCWj07*naR4|N(U^0i5PH@ST z{!yoN-l%LDRQxi|-D@m>GO2`s`@(QK4UjaTOk%)@x)s3cli-mfCTj6LJ^=FpH`G4Y zN_Qw-J66nVTh6VdZDt~obm6*cnR{=h_z+|yHi!c`CYn=8>ZQNOV@1={MKK0VXhG|1p*6w;-_6ga01DKw*p;Q!e`7 z8-`#TKmtOk!qwXxKNL;GTK)a^%IrL|)%5AKm+<(5W*Jg^-(^wB3d;79@j_D+2Y=9v ztvyzln0%A`Sy;aIRu_yZSryeEt1nikGUbdCo9oEkYn;`DUesT<%$Ba_SP?w+XC@~Hi2p2#q3Zr~T zDrSoI!V+Efq2$=@=$7YpwFyN9fz~R%83-=*p-};>1}$0y|us6mY-}m?477 zMVF#Q@#f5txt=djZE0kapJ;r#_p@!CVo-(9g^$&3>7dJZB=Dwj8BjXO`!L)o_(UP* z*i712dvhE{MZ7(y^#9-x;UzAMyRu=s@;L=BUf&sVkA&jN6;L*JjBuJv9~lO3)J!?# zS$5|}Q6i#H3LNmY_tkNI0NB>AIySuDO#1FW0s9+n$LhO!pkT%Z0_4zokQ+@Y;rgl2 zhRgr;lh<2osBLl;*cnCTNGcWrG0;GrF>`(;$D|{p-dE3Q3+QNR!|72tQH$yKb%STy zXRfMRKXlo!53@~uEay#}$q$R)BOM6&Z7CbfYgX!ONon%_<%Qz}>^uShtd+@c=ZUq? zES+eV1O=}sdx*nqeV%i!@3Ny5U`hht07VmyF-NTY0$QqFu6AU%s!KTyb2Svf9SU zRH=_tR(PJf(D3|dA*M@Y1lG{M*lVfl`(n36my)8)z@j|d#G+P3+eH?O;MoA+KB`TP z{|YBGOq}1xHSzb5db{GA(Rh{RnechyPE`@AV`U5h;Uv5k2EHPFX&QoF@}~+aU1cWi z9NAI;o;-`|!bRC7tJS(pSkFuiRHR|LY>8aJw+VWkRjhb=9BYO0a#+krhke8fZxkSq zGL@DZT;_Xp=JV1^Gw)G30%Q8BSml3JO6t{z+JgGfR@W!~6(@D?jVi$;HTt1JaXIbawru~ z0cH2pS%2eXER7YF0m)wF^@ihrSWy+Pfcl86AfyA;uwcX3)!Dd z20(9Xx0~8E>EQj{lX`Qf8+CQk7B|{Xwf`lh9Q)k0jE9~y`HwOnvz%~@p=9JbEuY00 zUjC8*r$AW0hxhS8-`?0KG03EmtY^`zINaJ;%ew8lQ?OLZM6c)eK3G9qFKjX^n4AIS zOn*I7DH$R?rXl?$xw}xuk38%c`JIAE>FtFe-%*nmHHo8Y0{y6S#<+qoO2Rd$~dB!U8>f*9H5^N zFvsQG3Se8MykUH6f89T){7Q%HloXA*U;~shlqDgw#11g2E`1SA7HPZ4^U~7(TXt$E zMAm!ztT2bXZ;*Gk2a6v$9yC+ZCew3V*TaH8LWWDVi}d=vX#;O~qwIDH4XbCEsBqi?$%k8uA9wFu`=rOSXFQe9f++nN9e%rO;S-r)TIu%b>(F`(U4lk?l-8vumog!$S+jFXaWF2BL_iScD& zrj?b)!XGB_uwsEH;d#lgUaW*IatWKd>ZKPi~O-EMDddYp1 z8BjiJg+brPMC(CdhXi;}3|PTN&o(A7V;w}m$rurS>3v2)m)FFR+RYNpt}8v4!XeI2 zydU8GhR^wIyf6(r7?(l7v5es5?AQgt3RIno&GS`rR=UA*8c^PEGiqhE$QTx@96|tj zO+{`qM|rKyA+J6tmkJmZ&Ta}!3UPRq@uY5x8??HY` zXH2YCE<@Laz+BE_mO;=oUH1znrRcOB zR0tg?B-u*m)?}-VVA~K-HcJ^0+>nDWA2=}Qe$DEpeQ(s%LGxU7Y~?_2 z@=PyyEvwDhsj&jK2Xgo`W#+n8XI?rCxAE$&jMC9edu@5vGF87Tw@J~O=9RcJgSoY` z>}n1}>IbQ*1K7q5Kbrv-E5$g;P_b^Kjx>7@Dz{0O-m$_B)5$&Vj&WTXT+P4hh~T%3 zzdVOr+vrPO*zt+S825f(vug&9iw5yglQ|w{j`P`ll`;+D&J^-F^*h#t5eX=-ab1`o z`QJTu?^fBh(qNBiu~OM94R$8!~M!Vn&02wmp*>I$JnI<>cDwkC3mAPnn|F>Tpt;w28-@>z23oq9`~v~#NkmX zu_l$`h7g4%Ch=vThdg+vVAfj3lk-e zZJ7=QkCx0(d*XqPLdy_FrJrRxJ_j0ZQrxnbUj-3mHzy}_*^=$KovU3th9E9muT))7 zH0M7g_S7+1@(NH#`}$)>1!gBwSq#z;#L|8XE`NLcbcdPYyWjopH(iadJ^uX9{~Z7F zFaPpQSL6SQBeTf>9}c25)KuyF{d*N`n~YPrT2G4P_ZY{9+6{6d<(1k@lrd{^Av0iw zKDZ{X%W$4wVr$XbR*U+`tR^C!=fK-}tev(vTO1Ws20Zn4ZgB(D#I*Ene+}`3Ca&jF zrlD`c2#5fiPK$-oIo_rI@6tBL8Ypu z17!~^%hZFy(Mhb@VnVarT~l!&gUOXyine{?y0jbD$8m(+eAHxvwTe9^?EAp5SRi3Q z<}=*%I)O=>ET`XTy9{Z^rcEaH7?kGue?9J`!Rx~7{T=VIXE=k(q-8MyGpMrf4jk9S zIelf;V&7rlI2@%_Ir;U%OSUgddL}j~oR~ZeKpm`vFl862=uo^!%tX|+u1;p$#?z^ZdOU=#4%7^Xl>1{c-fY=$O4V;<3IE9I!p(2dzG zKwEyVsjO}SHNmf^^H$SK0$xrTaYn85*EM^>tOQ{ib>tW6#Xd+^N11h|A+GIP_q9}G`0Y90U-;dsut-KA=~7&S=e7Gi2Y$7o2|LPGEkzBi3{!wn>ftYe#r(; z<9p>{au_NQVsizRmvMrcEi&g?vzH8ClLyvpB`jgX*&RMY@kqL8G43j*Bemp{(r%i! zx>b0&1bk92-ew-- zK*IZL1(RQ|wMzN@%L~H}oaY+P<;;G=c^=_R;7rPOonR3I6_{U>w650`3cqAiPK=r> z&|*tSa$dP1G6B7>pNiB1xx>(^V~nD#Jr+`Q|) ztV7EFUPr59R^Qsd7~B_f#QV86&yqA9f9!!}*?X^$SLw>E5AO1#Q?J((i|6j5BXkr~ z1jW9Tbj-fy)mPtK*K%MV9+R@p9OF2w=ofD>^L*bi4Ci^`?d`( z04+!Jt_e#Lc*;IWoh5sH*W^pV&ux-nVd~=;Yi07)1Iyh0hS&=A_UaoHwr;d^;hT7_ z`cIrHV(2%U9PjnGF?BM0W&MD|=8_L% zL{1V}scbP;CJ;`cSS2iHrn}$fQUGRnJ5S8>4R3zJ&J~oUjNN&Otmf#tLf^IR$0QZ|T< zYl(e3&+ftBkN=RJRJyc)UvqlQ)qf6Oof>1tLO5Nh_f4No2jm2aC_6KINj8n5lj!c< zA=B`|#wXPMs_XT<{WkrBpfYdUt{eWz@>s`8)jQ=HfQ%L7=T4VuQ;v0CSwj#GAM@H8 zjL%V4)aU3kWk#*1U@jMV`&3Tp&(fExkZ@u-km-YxS5P92lYz5OLeZJYcb)d?KdHTp zb>fMvSf!jbPV}IxEWN=!*)=m&Rxx>^|08y)0C#0wxn5UpvBj}5%;3}DLsIjS*98N% z;C<99d6s-ah?u2oAB6mr{_{LXqni6@Jv)G&bs&dLSXQ*>-1417Tf1mgX3BRGYo)y7 zRtucWM6!GG2x*fOBiisNJ-n|@VsLq6pQ`V0Jjh`3wEV?y!?>riJhUBq+S3*Y51qfu z6c?G5z2}8r8yB*}-4V0pZvG30l&52u5t%0pA#li0V>EG|)mQ=hBC#a0t;vgtMb*l+ zHl`ZZ6x^HrpwI`E?z&-=mNs2v5ar7T_nv$0+v6uae(9HfX>C9BGkW~p-~Ao_;UE6t zo36(HGsnDMOZNb!qjnrcY@_(6eaTzAU4# zv?~PFs2*i|b>V|nUs7r9ie;;0LO7)9s|dmn3HMIJr;H@-RonlJemU-Q+uKP zS9Wv$Wv6fU0Q>K*|EuRe&O7SvF=0Z|Uw`?6ufF<{^kYeBnL2X9`FU~`w_~`Atr~QR zGgDq)*Yaa1e$#s8L<-s`S?%Ik<+)jn7G$zxyx0OW-g#zDKxNkiZ3S3pNX%gsoU|bI z4hra~G;wfk*Y$u5>K(W=)!nME_i*y$jzh@v1{?7IT$P-Z2g>xvQ17>P2fZ{<)aWsuE%8vdIb@IEWdnS$|up`HU;D>Ya@iVFXv3J?bDd za()h)CaCA{oqTs1=_m5^M(2maOlex*0maw#Ih3{(pDS!F9?(=#yU@IMNT<_Nb!AEV z4WuLy1bHamvL{Wx&an^BQZ9uNU?cYYte~={P|{Tp+6EQKLbTSF{qjMZi!r>nGw;#}Q0To=0S8ILTJEX>48~H)ESu()sC>#RTN3K9f@FbsTGE-gV#@7p`LkAatxpj{@*?&{(D@XLExu zHoi;Ri=(A}6?$j?7A4hX)nvT(8*U$}Bed)f?kuSm^4j}#%5cYRyzF9Y_3xq`g8}t^ zm6Lnmld#gz(lYD2sXyEs&#Ig<`>1{oeHp_h9cM-dwZX$d?QS^S;LPq3pZi`j;yiok zgc9B5pyqF>bEGcMhd38?>_)lSg9N#WyEgpRP+xI=iKw$_eM$vaOrQSytX zOuL@{rZ_0(RkPuBHLcPtCru7=3{TC97}=C|7@TrSj9^@P^q9w3V}lH3)8PRvBKO zZ@R!NtKMu&b}V=++0nNq5uDuzN!4m^OT#n134O;x(;a)GC?`yK?>-B~gCxmf@^E_Y~R9`u4wG0`%9|MI~FhB z#q*Iiw^36=vSDs&@TS}a>u#k|YNsWixTDMX3@ktRf0}MEsjJ{lVivwpdnxS-(pq(H z>NmlrsS~&oom-*kXHGbb6xm+;W+yh?^>y0RoM>F2F)b+foWPj`Z>qQY^A=!6`Tv%` zv^+hJKKV41+ezPC6DVeF)x^HtS1OM&aJ(Nl#(~#s`H^2-yn5K0NaD!tx;o!lqZ{9^ z(5yIW!*V%hH*R&&nh1$~HEivvHFD?baB4@2=>pk7U&nGzCG)do zeH2mnDEP_MK-;o>HL~M_YE-UXDruzFz&Lf@P!Ij}2$pMC8iRME*3y#WRq(8_y0HrE2^*qoS=`f#O{ zNTn*mSn)_w$+avrLtG8>Go~@Sq`rCWahG9h)KAYp)y{{Bvza?vn793k+;%dd?GrwK{)|tbKjZD~ty1}nm64%ncjP9lBC>>$6ps;-PgO2Hb+v%=mB|`BqM_y2gl==Vf%NGlmnb z&Vv(zEd#ogQM<#MDQlO^(en$}^{Umek+Lnv4S9EZrs6fMV3CiJZH(d9jPxNiD!DnT zOl(2r;B&5Etl;vH?AK;k#DhSTq(q@!xSFQ5EPWC3y|Cj}TjgKx@-1bV=qttZDU+2%|37Z_r*R6Y)*mT6LTE^$+e7_Q~xBM9({5w(<-J&Jb&-%y;tJ@Ik~*65DV zg*uuAl6pjGplz#4^%-w`_}B4oIsVgs`cHp$6@EPa%YXSV_&@*W|NPn2_{Tfc_IPCL z!<3&tqaffR&E$I)@tT%u)`PY$9PQum)@h~9jo8Ry3mk+Ep^Nph0hOiA6Q6ozfndv7 z|CUjWCR*;Cn5yuAYz@T8rR9q_aplXO+7FfBQgJwXQNqu-w`r?7%d-jPYe>44wxn(! z<=E)P;)$FezbZS2^W*J5kZWyI04)spB$tKUQ32bAm=J@lscwlOssdStKgrbiL5 z_0zjL$Y-cuSzoNE6CB$Yux8)97NcdA-k*I_2+asd1e54+nLy)JM=MW|UZF zO#l9?aj64Xx7CDwtNo=7zwYn!4`jOwm#^ZH#%kz$vcZ;vbo8<4^4g|M>`{say#|1f z=N`Aw$}}cw^;!b4TuQ!|VHIcRCh6|wY-ys+mq6Nda89>Zj4@3!xylF^1Ln9s(~I#t zxHzF+g38aCj)2*n#J+nlXFJO{WJ(7GM*^k`xcwl6WgBBTi4gt4p>Q6ijNB!>zffFr>4RQT$}ZCF&Yqt==Lx+^b83sw-7zXWNND(l-@KkREi%Oo9!G@ zYUDeradh`Vv_myFE)N}Dv~+JLBEKKQK@<<3eWwk33nT_;fUL$*;Tvhl8T6ubq7&-< zXdpj=GG?-EWoV(DyuNlT3^kZkq4y_ggCPQ0Vq|!0uN^r~I9BQQs3KXEyRVx2c zjXMg0lgmHf{Y1fks?Emu@%X>8g-VM&0YOSp z6j|ExLxaf#Q(T>eWf4AT42NrFn(G~JTXx}Ekq-E`-+seynLhaI>r;Srj2Z2d+=q%| z_f*mq#2AjRm@pDxW7l}Uu7%I_iF*)EgqZz#!(`QUImnn=u&@y6{p`c;JDrk2IoW+i znP0MAl}n*hpi(M=a;@b&>lm!z@J!9f6n}8YD#NUm(oE`YFISJY6>r4*fCN~^ltJ-c z?hD`SL~x8cpRX~ru8g+&gD%r`+B8_pV#@|IEMM@&bc9|(<(dJR0X1M|dm&aTYDrxQ z%40UE;kz7KUi-0BO503RReR*z-}wGsu;0(rkA~kf;1e^9f8qQ4JGV=rW^Wl17_!HE z^N;8T{#Ku@+cUhn_;wTziT<~X)nrF)|6wDk0m{sV?J;iS;19Lh6MD~;4cn=`*#LzcjNQMeZ?fFy#VY;D(h2Cf&!|adev*BM`uuZ29)D`f5!@C z-@Ev@`y<*@lMwC=v)*fpdc{n(I#~0}{k98G9iyNF$(E^DdqqUqr9x}rzG`!Qb{zxC zyF2!^-Z>F`=Pdoysoa*Knr%8Z=VWLojooXKMs1yOV!zTA&%aJRKUXS`pfblEZP^?& zeh!*r{G8uRacnN<)44qo_0@rQi^^vuP2QKkbwGJ$G%Kt-`l+$r z3@Uf_H9blOoc)uNYIv*+GH!%Jv3&|6n~H{()wcq4rr*6~K`|@;O8Hq*`E)xjT-U~D zU)Y~d^i59i$lbfKvK@SWdvE(fN7yd$l$7Q>t{kTeu#E~bmpQb?hAWuxW$AI;_@m-WMSBV znw3lV8*lQ1bub};X;tt{lXu9uS3KI~SW(EkGpZjIr*u85?t+2qK11KfzOLUGP}Yg| zod&!97yZ`1Il>ndwx;?*t-|NDRc zZ~V)@{L7zRjepQXWzu_K`C;ePCoZJoNEcbAxa|ak6H4W8cHGc!jC#piDcUUjPpjmE z)iy*FWj)zZvmorDXSF^2Q{*QwYi1LYN%zbu7^#$LLq%zOJ8W&3M>Z|~&47K>|B^L`n(uVO2l!yO@{z9{#GYdi9YoiVVGWcF=Vh1{AV0rTS@PX*x z`C14n+#Rsxd3~>%T%j>d#vm)0ypxx&h41h51y(jCj;$r5qcK{^3bWc5-FT1S?h$LL z2?1(rwEW;u{M7UXkpCxgrGf0ZiY?s>FmM|tZ$_7r#CLOm1$j#XiGoLJRG9{!)F?kb z|FEigC3tc!zn7VHz9+FXhIjEhWl2j~PBI%@0d2RnbUa==s% zx%?f^jNxaGZ;q1RMg9ZE{a?j(WT=w?Q;1kfRQ9n3hAby4FrZ9B-a!ZKQKtgUGAtFm zm%L@#iI+kC(nO|A1Qivm6`>JS_ZU(BE)p1(paD$H?I9N(Kzm<9IG7 zWmnr>9^Rv#lbC8Ui1JMVQw?K2GP7`Ckpe@R=NqNZ9L*Dk-Y@T3OdWs8DoF!mVhV%G zx-S<4%a%$Cl`<2>2c@y?pcWPM03QdDyVA20{O$VX_+i|Xk~Dr2M|O8M))z>JP1c8N1y#FvCt4IV>G%E5^=ygL}Lm((Di0KZ|G{Rh^@===<}e3l(}S zm~p@)>x90MG)~}Zd`9`VfHNI&oK2VK+)vUFDTX7>czj;h!YB7)3s8FF^ZCNp=PS-% zzt#11MJkhbXRYVDpIyMK0*tQXy`9{2{+G6uzF5of`Na65BjMf~_8oE}^rlytYpq_v zJbWvK<+O8N0#NoZ>&f< zTdz_q=L^s93ev`&b+X#H`cwe&Fa*#+a8|?7f#s@5>z~3x01UZ7QN7^;al!rhjFp-^ zmt#D`;L9Z<2@m-@BIzH@O^g>`ujUqFWs7^ z3ggWBh9kB0h3;Qy$7hJ%9$26-Nz<0BT+Z>r1C3o{-(`dCLsOIiQ6nyX6ve9nfMv1o zJ@sb=rU!4jlt(93xyYuO^Q_4>sdc^d+R$IQ$Oz8q`EOlV_1g>Gy%QysSeGJ{TkZdp73q{ zI#e#Jt$esjPj%EeQ$4aywZ70GbOp0Bi^5tP*Abw61oq*H1Fw4TSe=lQq(Yu_s_R~< z{C!MV>AktOIGox(>prd(?dz`oq@buYw+y_eoZ)A7UH39d%rcnVa?1icoc5~(2Pa>) zE}7?+k$boOvK?^Stt)=`)4kJl5;lMlNN&4WRxT&a0&ne*j}_$Kb?>=4S%b^k_vg5K zJElZyzkrUN!h*a`U{Lh(Ife;R8ea-_;hPT3$yFt#r_Sn{VB4R-FEQB|oAh_czn}V! zt7c^dErUvDy&b~e+u_Fk%Dw|~pEE1RQiibThZR57at=F}% z_Xi*T2DMnp9~(RMCMSX1f=`C&K}?ViG`n))!=ee0D2ij*bEUFxc&<$13hL=_ZmiLh zMdG_jmDZn8H%EWbvgN@$9xbm)ib4lkc7+4*v)|%bbO221>BjJFOKD#|2ucjhw&l6t zOWCd6-p0b?zp-boAtt9s@Hb`HvPx;*q?9%Z?FPj?w)x?z`VlaO@Ftpm{M|)o@;oP@ zhzu!u5$||^&iV<&1R)vaIeb=Jdw@Qc`hOA&)a^;~c|n~cW6-o-gIVM^%NB6|!+s(j zV8^&}j2Fyw_cYe|8mKkAL}>f5ER` zzy9oM{No*^`ys9s$J?;$!;iC!I>7-Y#$C$$gW*~F;Ze6vi_LeG*N>R!LipDVy;_)n zVmtg6EO}r`Kiktrf8!5O3aXv1tCU0ke?DBP-1e>74sM>?juB%*^h6Wl(2#wy!(>0? ze0=Bq)zCQ@K8r>LFWqufX~a_Gh-pHxAMQ3wpD*=SFH}*UaUpX}%!T-$1rPN^qh8qA zTQ}8B2l1v~Y?4ZF6&mNqR)P#Dx6Pmd?^imZ`Sx$Bp;F7%e)R@x$&2Q*Jc?|e(;pcJXeNci;~%MvBM95>dAbK97(pP z1E!6Q6gV>L1RH=qp`8Y{qaEIi8j8%Hpv6&H4$C&(D8WZABqH$4DK|niZ`NJsUz1|MNqSvW-^)WlHA8a7NKkL%?{}|j= zGE>BMZI9%$(~fXD2IqT^R+OMZ(o2mAAGI*NuK9go@pe`ybx}?drW*NN9J{N9?y*vN zq_*T|yJ5B~)fSa7=~HzsClNd2tgruYEi&!dyua_LAw8uX{Xxb5mUJ!tQXV~+=b`z? zYaw5w^|5+)b8pCH0MnCrOA?(_Q)%(gDMPHr;6XGx=xY4DQOO=M>h(xKp)w1u~j}7=8z%I95(Ea=9#2YKj*iKa+#x$k9!padTKfeK7xx~Hw7nVVold*pM zfYxj+`(gIXwChiK;i)o0X7|L2N}Vluqx!9A?idrbc0WT^gwi)h?O%AYs+$+5ap2tB z1$0`)YUKsh`*REwP&Pi9zlZ~==IA(}nM_04@*j>|6Md%rg1+8nSbJxH;cERZ zj)DWo%s8-NAU!wk&=};TJwzx|;XCPJ&*|liMH0d5uM{t7wx3``lwy zXUdw|7up0PjJ{gqJZMsSBLd5J((>LL+iu*q=T=48pS$VJpnp4$9KDK7Cnlr}*3V;% zoJZ5O$ImIZQ8q&j6ut*CcoK03*2uC|mlBtYlGXnQG_b184;WYajCiE#yBa^pU;UH& z_&2w)nER$e_z*y+|G#(I0MQR2wesImUVGD*Q)X6+T>8mSbtr5ub%LQXG}IVLzQ5K5 zA5hq63IuO0hxvkK#(_v#pJV^Nt8VPPrqhC75o|<`-_YpIH>IDig)6t8;n=)%oL0FS zP!?x1ZHR+Dp)bgXjX-9D2TR!Bf6~bLmt+5lnGj-LF(K%g#H}Q|LQd( zuq+gJfD4e^tFdCK!MvcxH!MtjiLNi76*-$T+q;?|O924}F#LIUWdfK%YeYo$uq>_0m)I%+>1= zFUiU8qzN5Uq&XV1qx7QIoA)-IN@tUI9O%WI&y}yLA-h?k&)700Be6m0S}%5}N!jIt zXhNN1ps-cZT))ZNRFRrwXLRCTp^4~O2%n8Op;Ut7O7~jcX?vMjW$xl6aU_1xfO4!< z&Y<#rIK40}Cykn=uL zC_I^byJNZIzF$VJ1Ka2*IGkxRV21z78;nOd*l!Cf7pmXV?btq}j85d?%HjiQ?dOj(xs) zHp1tJu|9OnNRdLcS^~UH?tja2+3#-ZwPVA&KP}6ubf`r59axq^<>ZK2KCN)WFxr^C zE)O;%wF2WX1;NC*YI_P{w#`MrrV8peWM5E;f3Dp3^;*EOKNn>I0~m_}_r7t9GX8$9{hj?31(I+EdxZv?_0Z1 z_{h?^3f~z_b9wc2u8n}jeN)+CS?D@G7)n2!$drHN$+a$A_Q^?4JYN9}0xilYwj@Qo z%Q+)SX;XJLP`Nmfs%UodQ%?{BfgL>31MY=d=S=$4Sbk^pb~v3q+PaIYE#zxtRbC3C z-b<O8HW93OLFXXN|ozRSQ^>!}N!Gyj~ooWvmP>wG& zK(>17eaw`)lT@q&sA_7+#xUyOnX5W8a8Nn|r6a;{y90Ro>KUIo*DZl14NDbN`>Y@{U1{3aA6meG<$2=GbmE zW0%gxuCi6XK|e>uYl6mFR}AK)llguX<~>O;KQndbD9c)xdrzn-B|VttV4(ARG>eww zHt}T}pyWLhzBSAMUc!UJoiB7AKW{* zVk(m|WVKMVB71f~S%Tqt-K#JS3<||qWIu8I?%JnSS1QM9l~$3>o&zJD9FtzSJ?PVAUBSan`Q zW?l>|k4#_JTq(U}jBbm|UCHZoztQDZWJg&22AKM|TjVSiKwcOKjto5Qy)N{9?4+^K3c*mmaH0d6AIrA^u7VYMl>S;{OBK}* zoo2EmSJ5)YLg?&pmSsOUDoD=k1kA)jT2;o2Yjq#lO8IQn&ow?$_FR6!A>Y?|)o0>k zo#4elFudh;;e>&cG4Q)Gx24?Xq>waaG@duPPwnnm*!WzUhju{mnhcAomKPm+@<5m8 z={I=JO?v_g_0=@AvoT)cT75fdaoW`R(dnEEt@2@dKO8>BppMHarxoKVks9laNiV|l zA;Z1<-B!`Hq!Wk29C~fLI>ilv8vxe#S=V$RB)GdXjZJap{&P64yQ+gaXv*=`p z<`DyqtQ4YKRmN-oiJY{oOLf450Dm3-mgArQ`JeynDm;$w?{ECK|MuVh>}vdf;1KDZ z2KA&qO*w=Uis9H ze&J#BhA zwR77RU%2n@%w(2yFvvDt8@{b*Mx4(eGBcM@B{v?YUe}CP^r_A3qK5&WoO^Z%fdr}M z!o1ls;&t@CJkGsVL14yfazR6w(G6wHp$E+{km*>w>hE)XGNtGTpHKX0rz>_WL)k1= zC)X-8dkre@2a^j}-aVLA7;00?k%FHGOqD0b?0ls+P%S3lJ17v^ushp5-daLNX!2T_ zQ`sB^!(FTGYA71*T^O*|FGf+D!qHmq`rgB;fy#nu5 zcao@2WjFcP>iR+3gAN>!q^JAD>2~lxNE2&?5rp!X#lYHl2g6JW;W^8AlqibUV+E?6 z{h9?8_(0F%Z-tS<)4hY_juu30kttbykl5wDVZF+tlNf~r#E@!f77_h^Un9W@M&HS0xQ8@xGGv9Kf#4q?s9{C#l-l-#K6H2Ud$ zGL~{G`UVZrzEb_84ytJN&n%o!oN&algH3Zn1QI+%@=PqtJz0)(Cf6)lv33D0kU<7X zRp`YjLoaSySj%ThzDh?*+RQ*sjNw?Zygs6v=qxJ)VAaP@-k0A7g+1jR1p#^G;eL`M z%>i#YQvH#nA@1NEgLlke6;RgN|ES@9tVKK3sAt=;1onW5acneXjOYaHv!{TopB`NeeIMIit7#*1hn( zOajVD$6VDGJTl*9-$77!U~g)U4fnh6JLEvYa!*~E{}>=h#+`kk--}!;+Dd)-8z*&X zI;_CcK-mKvl`JDy->vMI&zgG`SL*8uI=3U`>vQ4j>w~WhD(}5<-G+M^_HDTDzz-a| zGZifLG52d1CL~TfR>Cqk4x94yw1+~@NM?i#a(5d3@4EKgY15M|q4!r$zG9)24U}O~ zRj+QUOj(ky_e$F8q@E6jTX(O@caG&_g>tQ`^vEc4Ths>zU`Ibcj;K2tOS9 zcdeYnkq#5;f7Q>7GpqmrAOJ~3K~!heuZ45g$j)+((dxIs({Y1d*SJN?ygH+0#)%=o zHWec6m%jzG`@6|Anx#gA>umguP7h7LjPg>c46~T*pUzS<4-871KqeaWYK1-hBZrl^5k(OzC5&jbqFD%s`j6b^S3hvcFUhBUupK8 zb@Xyr5c6w0+P0kUwrbO8B6U)g7iaQ)|BiZR_{-9s2e8qZq*#rr7M^v_Uas$So0@_1 z2rl_*<5&=Ed#u_A(vM_-ZaEasvj2sSMK&4tNvi6TLynAKx5-0A@F^L`B$1+JKVwo> z@xJt1t3tUJ{Ya}wzDVNtcfC^C$KJ}i_xTH}RlBv4X3u8-b^P0oD{Z2GPse}%@Bba& z-`{_BHU2+wlnj3P%(2xzX$M}$rw)1Qf{?QZZu-Mx%8#-$hv=gHGyPliahO!NS1L=q zi9XEH<~~1ymL(HSd@3`b9OK7^APPAa*mZ4x$@D_RDlba)*YZ1kRHf^GzzGKh-OiHR zW-L5;+*9>VJE&}4lgVQq{zF(~i4D6)Wqf%B4!VK`)}${ScPOs!*xGY~>F_001Fd-z z2b+1+ukAec|AqzuW=)^?w_lY!2dhcBoO$|^8kru`+|p_9k%|a-rs|TECvasb3Nir>LwNK)PdW=Ufc@1gl*=(cXM2}G z5-NCK2=UZlW?gLz9%Y>P3uj<-qh1SBI2}sy;jz;io~ z`Z?c+GW2J!y#0-%jIM(cXF(K*%9r!vxaK#RZkUx5e&&P%HCW4GpzS=m{>OJ#e*tDk zzaF&Hub*5YWsX;MAYl|RXw|~Xr1I?m3Ic9%{#6=1^es%?5ze|y-z>F*d#`9cs_@fL z%b_ib?lfaD$$ETlk{(c?47_RR^S9=&1~lYFofc3FSx4<=KX-k_MY5Qo|9}qPFl=LYG0!~1NoHCa!x$`N%8EV& zHubXdKnnotUPvc1)BjPEqkudqLLfiNJIBbVSXb4$ke_a?y7~CA^*mCK#psBD96Tmt zQ9r~aHdJ64K6#D(Pdynt7Q{1LLvM~M26QOLUpFpg>yAk*8wSf@h@0+QF6V+NZy2M; z=eAuF_*BJg1n(uZ&0O`yta6Pjf#^Z~FLgUCv2wz0!dXB3DYZd||!gIR9|OK0muwuqD6fLpL1`U)x&UB%@$X(a0WtZH{W5HfwFE;QIw$*ltw;}je|;*2 zvg##$M)kn?N7-@)NlWL;XRTiaV(L2Wpe6Q7*<6smV%>t|y(;-5*S%jTS1{Malq=I| zx!1}@-*G)NJ7rqqeRsbu%T(YDFsHNq(2Zp5a;hhfFyTk>rx@OJg45YkD~Pjy8SIS} z))&6MzVQ9)R~XS0cy$?l_Vx9J-@bmsZ@+!v>+3iC_7%bNudkkzTiq!-O7l%N-ZP2t zD04#2_xE?CQ{!IMcdzhnJ6dp*6$|9*;gw>RTd7dytRC}DUEg#a+;hq>#m;M2oH&+yv%!73PfRZCNM*gdkLM(g?6)IWeqFH@!spu9 zpP0Dt*`IW}eL@f2TP8~=zsKL&;X~jgQ1`@o9%!$=R7{z*D%_b15msh6^2A(L%iW*4 zGVBxnH2LA>=Ei19KOyJO+F0?o%cqwo9(C!@Ck6>V1{^Ep+AQxU2Atp8en?Pj0SojhavzLmjO2dHmT&?UZ+k{y?=O3}H z?^XC<$SbzQdeSuUe47-!H@3^U_l^Zm7H6}a?I}u^tW^86#H*5eb_jd#=+Q2=K_d;` z)*q@zx-;a9gC|&zfj{a);|jfU*Mj=8@LjfG(5|+a($>8l!#gMM8Ct4zQ~5vu&S^gH ztol4!rMB9kXW5r;I#hin8k>l0T(|g-qNGXw<^|&PJ15-tgfv;i%Wa$b>3%QOFd}Yd z95# zM=PbBNDxRxBsW+K9^P&UKVNg}AxK;<$Va(CdFMois+a2{?TBD{*W#_!hPBJHq|(!@ z`6Jjp57J8;+49;*hDVXc!s`1UM3r=pqh}OpK)D39|G{`Gp<(iJQU2<~Z76MFST6f4l9 zYV56J9<@?-wr6iDN$vQ)mBnWT4mRB%K!`fXP=VzltI(Hps6JZFuY7~MW2IxS13G+# z$VFDmkn|FsOPcIh$_oGf#>U3&_p`&iTQpO+h;z1RSE8W#n7^GeGlf7K9qlT44gOR= z9f0-}e2?nSF>QRW(5Uyxm3}jkmo*Aidvu@u@zHXe*l8#z!>r-Zb9v<{?Y2j%)@|77 z+{Ch)h&1>dq9eT9+J9V0>@jJ9BI2g(a3Qa{vAo!wxQAXR-0$=JtLCO<~%^v1Pi&^pkop0j;SBcJ1` zbt%a3MYm~)_sR_hUx*u@2%~9Ly`Q|l5%eH^YBiaRkKjiM2*?>YoS4e(TE>vY!mh>s z9UzF6#y==J`5eU_=@9)0+K&I_Tx!QszFaW#z=yf#<|4o7%2D}S_o}`)180_7u6#b1 ztOVY8lR@lT+9+j@NXll)jSh}d|B6nkzQIGD>I%8F6u-$M=0l%H#XSvR_9(apnKcddFUvz8niHaK|#&2JrNWGk^WXZR!d!wwcuP=Okz9P*xufIOE*EG*7)9&>oXOlXr^zZTU zrUqJLVm4Yd?svnwXp4%6Y(bzeCt}^U=M(~`- zOIE>0U7j87$po~0-uRvsC|QQ{9+7~p3Pb-X`1kJ9k~bo2D6F^k5wE3_6mB221o0<} zW1`}X-jf;d+&)8!IhmAg@SMm%?YH^bc-yj^pt2S&TiENuUXFc5oj==gUyl9R*cnjv z+&baI)b3f?a_;SLNNbA9N5$Tuy zU&r5l{Cf;4|F8e`zy9nh{KFo#AmEUJ=jBgG3pmk@`dvDpyuGaTmMSXGwOF&(gM7k6 zno=I9pMja4;+uuu4l{0ugnd@`l#N}BBVrS-vGrqK>y}_vnNXS4Eo)C3ELSYomP1*= zos;qa>wxloATToc1eU;Lm~A1XA}aScMpGX zVQ8yPPob;*N)jf{f_m6Nhu>6MI>9feKf7WK^kPXMK>z$tq zH;~+F_YlX>{z<@PKxKhy`zzOac{~x5hFx$=Jo|}gcQ~AvS)~B%mC9CuzPajm29;}I zxk=sCfD^}wSqF)aJ+-dKzHL`KagK6y{FD@S9c8n)L;_MT0B8A&noop+FMmZL| zfR{SU+F-?4=`@hDE8F5_@c#kICN}fu7aSCTS8nwA>M>MaitZ4#qYb035e*C#Hm7n) zu)Hi7d>L#zViAMPi7JD?-`&E2yf=-hfl1F*hG~1)Xd8uHJKcQnih%f+zw@O-kpe}F zHjaMkw^O4(1%8#C1G82vlV6KI>>mp4!#P92$5LH8P}GGuP&8}O7E1S4dK_k*W*_E{@~dZigeD#iljI;(>YV9rlU?}5re1Gi0(F5+m#tk z-HL-JdU%X-WdzB;(U58fFwc*no)3<#IZFog7%yN!!e{EgW#L$48n2)U6^1z3PEvQN zg8+ZT8ERD5cjD-I29>!Ud)JD`;F&||S@NlXi|(FOd?G(m2ZJ;3=X;aqs5qAaz6wMv zkI7G$Wl))`n53WH>5w{t>FQgu_HXPvf^F(h>nt8_vhU&Av7d`=EL+&N;OO8P2cEmE zVo3)%sE_D8A&B`-P;#4A?dUh%XD$JZ$LCTt%D*y5?Bz<&rGF_A++O%YSM0VUY9fe(43AY$`kmcT=ypJTLEg(n_di9Z(*n3*?|^uCaYqU-Y~0*h6}8E00WB(J zCgtd;po#oj1|VeuGPP~iw;gLTUJ)q?392oB12ac>N|PZFQJAPL7n{EivD$sV>3yc5 z;11i4y>e!-WLIG8XP`oKqIWxx*MVn!VpDL!g#|Y*vmNY#s=os-0m>3qKk!WV zb{?4$-;#cX1NLki_wxn$LUg-2I}KJCfmpeCOg{V3mF~zuCuPTIxYYgG3Kv>xkoMWy zzAo}oj)5zdI-|=H9-XUvt@rc1*D;%T$N1TX*p9pVgZgTWf#Z)@zT! zR&Ccx?(1)@R1SSzV<_wU>JZ4P7_k63gSguv`%<=ZLLCxH8otw&2Y?J3cbz$sxS}<- zq1gG}iSd5IWcRo1mz>vJy{=9oFFrx>b2(zNk)@AFzron2I3!YHqsz+bvTN+fwVeud z>c2CHTr#q-%gLzEI#u!BI-ngY@%x-4p}6Q-@^E7j7l=X+=MW+>iF@#h${WFUEVxq9 zv7hq#h0voWK-(d$TOF{N$fyox@|Rj2UIc1gg>BeerBAvQs{{sFhQyYUGW+t4?N`a{ z4+F}db`aZr$0QJ;g$9+~SLsMrjyO)bRQBc*?UUFa=GcZdK9rm&r}KRr>R@JkKUk1v%K&FjkwQNgjf{UB8L~pTg3J6I zV@0o(;6+E)ci@0*v37O0puP({!Yn*eKe31O`ayIEtpr=Ns?YB@SE=SydR zFT~^(-RJZiXHzb-GJT)tXBz_WujAix{CiA){Z~-=|GDEQ+?l@~mw!CAsCNptxyOX| zG{k+0wi5qIBjPHhY*wuYP2m2zWn5*cbjM!e2V$uQX00u8ayuN$R3vd*EDUr*Olr$N z+l>)=3m%kQ=R{oFj@vzb$b4VwzVyBA3@GmmDyLP41c7W-%WHqi?9nX`J7acCYv-iB zU|7YRP5x0y8`-J*{Wo!azP@V!C<~`(?jD` z_0nmgQ@PlMcy+uN9q=tgZnI0q^s4cIF9 zJcf*x#IMC6UKW8E2c!J1wYGb4&o7(I=iPwPG!<0#aF9G`BsDEs(nuMDw+)OQSk|*m zpfs|h>`CtVYc&wuJC;h=(Cov+H@9Uw7O{tMjjTEOOT zkD0W=BP(aeGbOaDn1k2+`Q14*_3NS6`Mo{wIaf&(|6=lSE7xc<*M`Z~2vM1#g>9Zi zJ1twW;(+PBGPR7R9G_0N*%r3q{rf+r(Fh8@{B`Yl--dHC4=h)dio7?IvEcP|8SM35 zj{XKZvktSfq7Qn^!M*oF6i348D3q3>bP5NHq>(FUjJyIa^g;5+y0WhE9f8NSH}<;A zi2=7BFH8^b!Ru?Sbcn5*XjC$0H^9Y>9y;0#0Cf5=6=~>Xj}@*<#^YqQL&kQyM(=oE zxFa2R!V{{)AHtNn!(xI+@;3Jtx10&=hDbBG-u6t{4c?uqkIXB&Df^?}<`i}@ zu5wS9aM8XW1~lkCRw>6A&K0{l21VzC##-robp1+adRC1zbhNySvR(tq6uLF;z50Ol zqf0VYXKnaeW1E-*cuK3Ea>RwMjcqwTQ2bZv3Yjg$TTT+Qm9D4!B#$S9b(MTpjbG(h z;40<*JJRnL9Z-Ey-yeO_5?}rwiWA*0dChI5o7bAZxk7n;$JxFkkouiL<@tBl1X*=( zw>?4LKa5B3J?wkMlJ#DV5a~Abe!r_epSK-)YY@WwT6Kc*bI{=G;7m;d;>z0&y3^K* zKIMwWyMvn<01~KG*A=jI<%3@JYU8>7zvnl0!@IRVw0kXFo~v-L)^XdftSi&l?VN<- z&+<|XUAY%KokmO#ZWVB!`yJ+Dxv$=PD?;|L+h<8 zCDacxk3-l(u!?aUgdW`9o}{G{GpU;Z5F985DNM5=4!*__Yyi{q@3nCGg0BlZ$NR_A zA^e%`i7|S`1Q6QYt`1{vr6s+nG(W-8L@wBf$xCZR`z_yFTQ$At@}wdP<3q|m$$xYO zwRYo+>RfP46b96G@Pp!@7fcb)Np=yhw~YF;tadb;==aJ0rOPQhWHKJ!${o0?F)XX^ zqg~109yAU9#O%*1SLNKB%(I$=ZDRK`GnyeMSXBypu^00mU8Sr+<({n7nM8s=?-yO3c!OA<+Z0;v zyak-Hc}|=kcF@S@ue$ifUJoVFfwuZSb)#_|vbVmkJ!m^~DFbfi5ujeVLOFuK3%6uA z3{_zjce<_*fIDpp8}Bkh1rUuZmNlqMCzvZW#8S=oy_qUy7mF%?wUI~)eoY%?+}iqO zU@?)oF*(j;MR{ZDbD~!j1^~7(Sc-HMTnC|L(gpo|TUSs^mfc(B8Z3E2ZDW2<#VB+xWb> zqy5WS%RKjr;p94l__KPXnQ{E~*dhiclo<8}&>5(*f-VG`whQnHM}il@V|8+*3(!68 z%J4jA!MbMPMob^nB-NEB)UXS!My{ED|13_kXbZ|;%eY=2S3PhhQ zN2gM}XXjew=bp;oJMLx>Te;FZlET3+)H58|JwPyzmofa~;G;mUflFqx93->M;ITyL zHEcNQnhA;t^J+N3vY=tVj%zDA0uC%-?F_?n*3t1!eHT}$F*x7bFrUJ*2OkZcayqW= ze^8K>kweF77e;~mM>4JeuYzMAaw3K$9Xmx%5n$E!*_=~yy~WX8+MybWLRMH?w1*w< z@zG)BWTvybnI&&8c>KuwaF(YL$ z1uIu-);ns?jaY4ED`vr$WBnX^!b7izJwFa!7&r7M0-kbU>mS?0-_R){?FXJY4g7`+ zU7NUChz<8bHhJ#VxUe(DOd}lA#vJeKpF|F7!{zMo(s?~zF&smX>(-62n#L{mhzJnb zicehET|YU~8F6rO7{dHkWJk9={}({j{T4IX=SmkG#|cAfP<0*c9Ip;$2jO8y9Vlo5 zxLgrXmWfqe9v#xLnuz$lt)Bdgx-@hL`;PZwEmM8C7%6O@}%5>7K$|PTxpqS%5{*S&5 z`jr+*FxdAGk*&?3{81Hc=)J{X9O2b}#fDzAX|2!3(NUVUbw{L~+F^jDgV1)Q;f#Ij zt?H@HRW&542eZCrEB0)M#XDD~x7UGpTyI3W$(=GQWJv>F;GW}yZEeEUIDZ+a@fcUg ztQr{=XndwHD$2Ix8O5@5$Z?S@6dYS+yi#wgxFn&TbsSDVepgOD7a4*KCKG>2kkfkH z*SD0T!egT;uSzk#?^ViG$u#U*qMnB3DEb(vb01QmCcY(xSt$!+MH;4mf~6Ze-E{_( zZ7r;OVcosL@@C4iZLs^Uav9X1gV@j$bu<&vCLT%ptv7w}B8O&h>6Cy4Ho83`H~Z=2 z{nx&V-#Znz+EkjdvsZGjlxa-ib?;1d{QZsZ?{Ao)Rx|UO&pR%Ro;3hlC-)f~Yq0eg zGuAfINwaEAO@d|nr!0TN5R>L|O^4CgyY(ub8un@3&-0;=kNO@p>zAKxqHL^lkL`11 zDO3Ea4PEUh`pIvi3;ZY>lsn`7g3F4YCtXo1z;!R>Thb|ypry7QM?Ht#HIGTEH|75J zg!HdmR9Tv`mq6v97we_;MSXW1-s5uE?ymAEzc)@lXK|-Q?t0HR5hLW2yDmQQ;1*5q%*-;(^a#Lv8Y!vA?1q8 z_2AK@qgnY7O!^Yqhw$p#(YPTO^|}!uYd*$O!OD~=>PXIhukq%PEk=4$(%XBZuMJE; z9pTs2^>)@JGm;oc&&GsI3f+V+N2-Fo|_qRk5)*-g~;n#ljnzRYuGw8rLd z$l!A08ygJ(03ZNKL_t)1zVDrZWv2ez<7GD9dwgFq!SV9(uj3!+`2F|a|LiLK!yW_s z>NZX?mQ-I24ATz+Xukp+B~$VPYEqJ`tj5DGQQbj3da9ukp8Q+RRmu^g**mvB68}d{61sX%<(0kkIwgFf?8^>O0_sQp>rOMl8UiWyp$rW`j;CS>RF?>MpBbFq(NE8SAId>zDV z)XCH_O^tB~>pkeu`ihItBCDlm`aTE!#!*q~5_b#?(frzlcZNQzMRKS9ta~{oh=sXY z{?5r&j>4!=-nCv0-IF0QZ9C~Ebg|>bg#?m@n`5P(^7f_ZN@oFSPdi!cvjQX1YO;`H z5`nDEIFm4R)!%^6-rqq?OGC&lbH(%8iuve>s6EKI&l>n5IuX4peg;tp&Xxw3UsfeA zyX3b^oF?T8Y-X2%va7>|kON`%0Bc}P`UP7>%9{+R%c?nZ(xC&&-`{tnl>MZ$y3(Gq z^WF#2d8m#0(@_Jr47+S&(si#0Y8%@*I3u);&W>(6oUF~>o0U;V_ONNqfZdKwEYE$q zdv?)=j%W4=JA`n|@W9+9rSfv;IH(k-?8HqsJ|s zZfW|JU=_$b+91@Nzsc7caGQ?l*7dEBwTR@sHwTGSx)qWk=Vqe;gjYGEYN`>Nol14; z3;OLw9awi2KO{}>63z@RhZC5o2|ZU`G6R4Dm&os*nFJizYgG^#V37K*n(chvUmZw~ ziysg5B@0>W8ppK_n(Gr*zoieeoVo1JngC(KtZl$2>h4QcpdcL)+p%%u#>Vy= z8w59sWRi1iVP6~mQ3svDG6gCufT;!JqDnD99h9vLn>MaA0-k(v0-=*pUA`M~P_Es_ znZE~3LV)Q!oD;89n%Jr{>o0mp>O~50Ke`GoM<>_)6-aL2AuPjkr)G}(=@ceWNn>k1 zGn4ju(_i#f{C8DbfSA?0YrB(NFPy1sNTVTRjx?y0>BJ+p9K=$gqu1!CpN^fYlDU6j z>#09F-pUo)pyfraO5L-s0igDwDQ4Hsl|E#DCcYYP_n45_a)|Ug>zI93qvFZy>IA4j z(RnWU7z|Zojk3!qL5WlNjsstT@)szTQ`L*KOEK9J(UzQ)bQ+Nlx&Ed=6oyG~x%6Lj zRHw3Dt8ZXYc|EciWkC7+W?*^Yz8CDiW0n8DapyCiOIEI4ky^PX-jo68;Ot}72@u+j zL;I@Q^o9u7f0EX+p3%PRcMbVD-q%|uSWUW>%o=DOFRZ#ZZi|`H_r3A!*Dw6~^*et5 z{dbw*Ya`%(Iky?1-sGQUU^%yIunqIoznwH-|5E-@9I$gE3C}`r+;IF8`+voBE_N3w4peLn+jLxSp3M#-1`VpCyc;j2-XK)#^3S zXDaiO17d?z1sZ5nJKbXvII}1LoJgi*v;k*X25Ve_(V{Oxz7k`3lU>h|sfYVxd%cU< zyGjOHU$@@WpmL^5m6WNP1;cEPhtt9?xL*CwItp$QncVv$W)?+{elc%fC(zl7iOipucEeppMCJx@&B&l*RNlH zb`}0%k6Nj0HZn<`va@YPFZn>(>xsGRdpagk=W>;@ExO}Pg zg6Vo03;1y2qTr&`k&0dSzB4$NLFGuA6kEQfxwyB7AHqGi(26tnnT?{u&b-#bzOH!2 zxTqy?$h|krJQjD{8{6`4Nl>}Ko?$NT^2h(<7yatQio5Bf^I#B)|j(_U9|>m6NU z`+K}rD(k&Pw*Z1&&xh^S0pcn{$D!hN@9bdQSNYLZ#^<`{NRPJXxL|?%B{M^%g`bT! z^OAPTKOEgX>e|Pb~L_6ShMTA)6+s8qLH@HA)To3ib_MjV` zJhR-UAyN1>-6Mpe6O z7&E$V7=Z6ApQ{i{$nIl*f-4-E-0RLg_V=n#<&`(q)=d^6td~~Fr4EDcobP>4F@5?>mLxaq`ArBl9~2XxQ_kRf--;XpCU0nd>kV^%~BWb%xWyAA4p-pYogrxwJzkY*iUae{;QV-81BZBPUfE?(YaZBOMO=+7)oP)`I7L z)N2`h>~Ws}CwXTWG-s!aAwk~U`$<*P`_D46Ux(bSH}YB4k$9{ie!K@QAI`MZeItRD zhJV^g*g=i?f(JH1(?>tS`A$zAZq=5baEvNHYvo<-5dy?@<=Dp~CAz!!cUdl1Ei2G% zL$TY8YWows_6uHG;y~>wto8Ui4wZv2@`Sa_Nxo-$-I!wW)cuA^t)*B*>(mWs){=U@ zO>FqF(x(v4i!!iZ&Xl^X2dGcj-v@@WsWT=oGq! z4)W1XTYT4&=eWP8)v3lD?z1JfLHm zgSgn{NmKaI`r-$`%VEFkyAcEhW&hN1#eGH`sxn@#M>$<@aG%K9en{R~E59Yh=gT%k zE4TWoEsTsQwtHXV=RlWnW8MA2jnzuiKD7vlmrP}!qV>4a2V=ad^M&^}@5o3^_4Lw* zAcjTB5%Po9r_1lAKWr0@6U~S)uzd-Uc52X}Vu&%akNz~w;Iu#O;NB`j1I=B>Qu}&O zt)!l^oy0L|_zd13@}6?|1%EvVJ-$jr`Bcx3drR{D(Y^Ne{$~xW3+-)wylRtmde*!6 zMwE6<>i2P1iw%FCt3{QCf=~R^{2%mc{x)p(214bqPK;ce%S2}`4H zO%ubEH2~lj5F5T+aP&2uxohoOP{0ZP#kbtbCCAHs-?+AJdywOdI$6dWuUnR)on_|L zg;js*T0c5U8hw_ne@~+Hb<01>xa1en^D@qgvpsoiY!nV}a6bXJDO9l5O&Z3uQ5uRSsley$6j>x1k1;FEvc zht})a_JdHr=+;NHr*vDSwIayO3?HY=a%n#=#!$8S-fCNpvF(PnttR3Vsm0HUiw30! z+=I``%t6o3c<3#x-T6{%i?O;`trhoi3goF`KwEjD<=u(U%Z=j7o%<8;K88 zGG#gWzYkf#J&?Km%F0E1-}v?Yjj#L4j7k^o`-AWM#&yR;B?Gf55#xvwD}RzzCO_55 zoJf0J7w&sQ7k1#N=ZHOQmuz}{JSL-3A8X5L3qXEzZ#zQ&7hA*A4`?YbGdC{0ot%RY zrk;#;aElM8-Wl4+N+0vx1LK#?Lw}0&tpP{ar)}!<{7`}lOjUdJ^}9`}kf?R06LhD3 zL}nu)t}r%EUyGyekTQ;=?d9+fIARS(Z`Bp=S;tmOZMSt9;F;OP)`csv39)aQAZ<*X z%AVa%64gsyO_gc`$7*9g8-$qHlwDyzmI(kKq*I_P6$Ot7eigu%=RV8QaplZ7;AI)9 za70u+zS|c2&vmLcYbS@yv|r*-ua(N30ma9@$BVgRsZIq_8UfqVr=vXK+xi4I}LombzC0N1w~X`gaJDZh#Q{pq~O@dpu|L z-l`MCzte1943kQi$ zy?AoRE1T8L+4%%Pq?rjXG3AtFriFRDLluL!Vx?L5pciM}&!Ia30Tmx9^b<|^VE^8% z98N8rVifa;;_TKmoBcDdOM;pm?>S^@4PjBJDb}VlxRv^KX^>&1QoqW09(x|{-Sa`X znp)+JlB53X>2xL2MNWC$ml+q9%H%jS!^gEE4K-KZ?*zsBidmZkBfS@L2Ac^8a7Shc zENom4okiygfJ#yC4(xm5+ai7J=elrxxZ-aCp9?XUK4z!|j%YzUweGwYv{1SnNr!fS z30DnLzl;aU)Z=XV8_!yoKj3Vsf84+1+j^nuMs=*C`D}=k+*Ll>lnvuFa zfh$uK)l+IHgEB+ZJUG5>l+kkI)c^fqI)Eup7X{%%_7oMp+hbxlX+6(6J80PDcm7k~ z3dK(BQ~D+hLv!g{8caeL(x%Nwn{0sR{p0;W0YPpGQ&PS7&g9j{|K8UQj}6yx)!c|!9Snk2L^9zb@CBhj_fh9 zpXti$iw+oWRg!*3v;;sCfQc-07-#lLG{aORAI5m^B!y>lT`1dqHe{wD$^I=dq zg3PU#A^saky;SC>&6xTwrg6y9$3D|9?F8 zjtm-#LkoEFcmWn65N?71D% zUA9bPg05xj2bL2gP#deo=#cHM&*>If?UMxt>Cl%l!Pj!jkQG}ulpUlG8DH7{JUwq_ zp*e7+>Z{Y{^fGYL{z$veI5|4&&mH*KetSEsqAD(Nxuzp3x4&{1`Zh+A0^;PTEO%#M znUgDvHsh~yw>*zw1LefA)mUd6SG5Z+&Dt{y+Vz$httM#)_F9)N2IB8mZyQ|WJkowU zxX3PfeOd8y_}sew8slLGBDJH{&(9_gyibBj`wEW=E-_?KSqY}2hy?E$a(d6ijorn^ z^Pc(Xcix}-u$gUaTb*kAk*;mkKB`ZL$+6F+44e~qPsd81n+%g+-*@jX_Wk{Bxt6nK5?x|k7Smm4X##re{CUjnl((E zI-UmXVYq7Zk2=seKMlzB?HMo5Af7@}VW-yGGpM5xZM~*Toj>oHv zr?R1eGWT1sTpehWjwNxs;Bt0(mpP6{1+}gExu~3if91JpI1OgD>BUu}8n1YJuI_c; zUEFrKZR{-*LAa8|L$+|QAa#D#K8c(_a;GEWq%V!YbU5g~%&gnP+4Z8eZG88D1M;z4 zM}wmt-En?)G;r%4k~FwJ?sZ`9aWuRq&lj0olyN9c-N(4$s%7o(hiH(p?D*XG`lv&s z;ucq1A_zm~&`F@MQYrSU`Xyy-mJ+o(pMjkRF|_-HRAzI3$abKwa5B)*AlJLHR(#|B zj;s~;eRuL4x4{>ouN$#Ah3Rk%KTJL{AeG*vUy;YA&|9lp3y zIrZIHhREBJLq+a*$Jpt?x*m^lOW-MozuZR<=7*df0|Yp*$`i2lV<7yeSW7Uu1fgqP;WP;$xY)?J^)3_EPq&l=51zUJl zFiTNK^>E>2VN*Y7Ycqfw?O8R}o;D8#4gxv_INV#8&{57{vR=QfTD~+B#_=v|-l;L} zB#qCp!`(ueCOA^CQm~6BAH{x zSNfd;U0dy98}$+TR6Ru|LfTCp>cDXal`Dn2tX!@PTeHc~K02zZuPmC@q#w3L+b^H{ zsrT!LPI~CcKl*t5C|~(`hrQhUa)i!o8ih_tzXh!LsD6V>TgmrP)|R#@_x8)$-go`{ zXv`apnwQ~9Q|~(r>4%8FlHG!hC`0FaTAp^1^7-XZErjD*1Iv~1Kyb~loiE3=^B(Fq zr}*@6-Z5QoVULgx_q{qbFN4Z^$;wKXz;cPytUr4&>)LP6m$%K-SfxLgAENNI=<2f% z>$>Fy<+tbfaeYs{qx*LZ;87ocoa2>~H~IeR508w1zE-SIb8njIb!IN;OcT9TOqbeY zf%0+atg)R?%g&Y|+AJS!^|RegRGe11=ex};oVk^q_1}nZ}7u*Sc`8dt_Ux30{LzZNq6$UiC!zTvAtQz;XK9G`r9q zZ&C6XPzzr|M_*W%=z$J`&p|*@g2oiJps+K@2$eW$OR>;m~egzxXZ;C!qv7cEK{%fOS^x0X@IkCvcosg34Dsfe z;La-xj?d>Bf#uH?i+!%oRg<#Ubzyy&F)gR5RbNoAaO2gl4saP8;;MCpfZ5bQ3V=uz?`6O7={PNBY^FI^v*`* zDrXTo4XhQ`HyA3=CXS1G=IHoDk=2x*6)7of6aZ5==JEY~NK>wdWyzF8UsE-V*x~et~7bTw-Y%+R{PleP5(a! zS*=bUDIV-N9g53cE)TRy1!VeV162yUe&#^SXb}4hEcb1b4-D^tWvw#=UHiCa$mv7o z3?Ab1qi*U_U=i#+qbh30q>Tb+V@BO(g@&*(`IFyDkpSS{2*bI{zXT36B*cv}$j3L= zSOoXYrU5F-69(AsRtr(d=d~9@*1>kKfYCGb9r{etNe#rHM;fqeP2!CHJ!UB-uSz9H z-_OZ3@wQVP4Yp~#!2&lhND|JCR$a8YTbzS)F>kD6B zU-HCg-?8W9`o_2Y%DUdQTDkj6l)eyTPH^F0-XuZkIkNd|UpMew zz;(s!INR9E;2BVMk5q0PD{Ia1(-1FH=2-Oq-a99L?AT9tbv6#pLf4D}zC8lU_Xd93 z0KTw{dvJQ}Tf;3i3NMrplCd>)2YE5-gun-|Fr3B!R9fQkealm8KK3aOADW=_qsXSC z=pi$TZEZfsai^HZtj45{GeHicx`QaEY#Mb`Cy{7!mCvxcpOU;Q5(9*A5XNLm2CSVt z9elTaV=F}f}E+arJkjTPF?Rq@Ao*Eys!7P+>dJ(TX;0_U!Fn2gtZ%F)AU8}CWJ9IKVlJc8u=(hD3PiY=THR)uux{!PJc5t~TUrF#mgUq=)VCd>5LCBabn9L=h?Bpf1;3FAS7A9S`=YE{* z59u3~c-;jrJPhhwsS~dzkm)|@C;JUDUbIg%KvWK?s*=^vFtgFsH&cny*MlD7D;RxpTuaN}ziH+CQr20gx>LSC3w?k4 z(e1EIl}CJ9DV`y6O$F#ts@FJHTM9z2<6g1#eRS&3@TX81x+4BpWMKs}OHUFC3>?<_ zw`F#NtHCBd&)Ta8XO3^rfbzA{d1kBiI`zvHe0#4OI#C8t9!K(Z+nC!O>o(lq3;VNh z?}hum64Robw+xJ8dqvD_`M?l!!j81nMQ#(H$XGr761qKF(-n{Fx5-NNYrm>!&_tf) zDn0yl5YG>}XdP^ z)^zA?4yT+so~V^~ft`U{Dp6xrd_A0WpbJCTpUn$G579CG`Hv9TU&mj^UxyyPcTJ!M zyv~ZnfFDMc%V;izEm;>*6D-+24?y6e@@a`Y5!-s$8bb~js^~f#DslV9eaDX>Prh-l zh3hhWT?=2I3tyiPe*OC3`}+&`=YkoqttXwTuAxFJKip=px>3qX+Y;!NqntEUrav*0 z$X^#-OaGSITW=V>eB*n|pKRMmA+G&{XwSZPY&~~fG4U?;4w*J6o_JVQ1nF$%xuTfD z-{fRRIW4QXC0W_y*{O@F$R!S`bwaDA$RMXkx+i9`qK#iOy}OHEA%8zjf%urvwlEuw z$E%umzyl`%H+P#&A|Au8s@Dfr->T9uIsz=z!ITMHg03ZNK zL_t(uGFgN7{)-1S1#Xu!0CLy7PiuVBu^^?r_RIjiP0RDXkh?DqOK(SU-(91)>o3O4 z83b+m5Vap*m8-5yet$Std|oSmokW(px1sRz&#RYGxHS(um@2bD_gMvCws{CsR25s$ zx5PQ>+K!Scw`hLQGVc}ra-607s*jEO>Yi+~P5!tn!B>r&DsZQPI zR5vvoQ0X#KNY_lJR(n-b)lJ#nlb>I8)o~nMQ|+$TX#3QVmo)UMsZ;8eVkjk%Z4T#T zq*vx1EDvYpAsfnJ0zD6DQf-+4LBAK{G$V~xtCZPqZ&W)R4ucoY8c7`v*;{NY>1}wv za<$fPzx|ef|AgPZe#1ZI^{?+=`2Amh$8}vW`yBwrDxZ=&6=3!$`dnmM%Ht-d9XHO_ zlgESK+9}7t@v;d1F3(jMe!)5W(s~@sbJY^HBFr3av6s2wj=ycVEoHECf16&Zecv1V z`>W7~Sp<~#eML&1g_s;9ZK_};+nZyLI71qajh#*!bwI^^oJD)`VDUi#NYvQin5{qI zna6Q}Y`t@7ZL1J_oafjRzD0?fcMW{#qf`3)ELmDV_N_K#6?H=acnv7KBl2GLSica{ zg!~FQ!F_6diPN-#$?rjBS+rj=%Y9?BZ=`=H3mQl2IP>RUK3cTSHg?*ooJ6!Jg93w{ zRC}du@rWo3>XaHtY@A{c8S8w<17on*MRTnthXeFgbo6efkh*9Ha>vitU2Ot8fv zQDa*$ppJ=thUcJ8u|Q6);=aMPLcHue$jWh9LCzWdO|YUB8|3g9@1o<{_BzIk$Zan= zdX>BKdsmy)gf=4C4^EduQD$EG@jY>nAJM?_Y^T5N=5ump*Y7F& z)MhGKNh4ou$vqrcxnEsn@_CVd$s(7i zFstlN1wk@Gw0wPa{a$uLkK1n7816rQ?kqu(;o!PHqK44J$Oc-(~S8o;-9c)YznLLwm)^>y1BXuP@#xH?W>uQ> zLzipg_xyHjkMq~@*YVf!N5`&IZqx1w-QjZGXf<%A$~1^fYizNw!$-J1VmL9QQ?N?N z33rscG+&68?^EXMafqt=GF(bw4=yv@-(hQgu7!Wi?08>aAN=;~3*W!K@tr~Cbuo*G zmwncdHTB`PUegkJuuC_^;!2q~t9Tx$iQg)rDgVs+y-B{3+g{F|#(Fx*^S*EF`^Mhk zTWf!8%X3HQRc24D{=2&GhrAVXa}q6e3tOTzQ3S|KBgQVGG( zL1nJ&kKOw`w%GW*1(g@RJ|BF(zVP|t`KyA;#I*Nrd>h2^9$OVqM)7ftHETJb3(_hG zoc$VZG8@;P{*nyTz`Mx_?~2K zPX@uK_X-T@YE@YUTndGmig!MD(^=} znV1r-9$4RD$nA&-82lT7)vI0-P&0o#fwsCCOB!00w3yZWmAQV zh8%8#K!lgGe^AC}D9tT>g?T*;94iqdFDU`qLK1MFV~n&JD`{*x#xyv6YNqOk{z|Tt zuSN4ce)i+p_oEZ8<{Qa+}|0yZR7n5%oR;=BWQF}Z5M5}DaGe9@X{(~YwEWv=lx;mJAt%a}87k>Nt z!ax7hKjEML>7VgWdH&~r`e*$9`|r5c2WG4I`u>hRyV+OVm#xQGx0s-RXY}zd8U>I+;Y{OZ}{T=EHX!sbvl`v@`5J=w%sthaW@jpRm`ym&AvD8Uw2Kk z`p!vKKnIjR*MzE}99;CBsb3HD2iE_6BVh7){Z&j|g?%MVHQIVf&IBxO69+YQuazV+y^953w!0}6T z7z5C%8(Ma6?|qcd0JFBWYe#jKyakMVsqSXrvH#8huRu`0&jIiuGCumj5^$R_^|8&( zqL1LR9;YL&LHbiW%zFR-*n77m$#ooCbb<2N)pO{n^=#X$$8@SPMBEQx0SlBOYahEG zZFVe`=^?pX;seARBuJQv%>UhZ6>bVGBqo$^t(1eQQ@g-jC5l$ym5rdwe%ez)E7Arn zrS-LzPxak{FU4ZjiEGg^3F79z!jTLlcUs=$T^mI|P&zuYF7R`vDnq7m4>}|clH#*1 z3`#J_AUH=kT6|;lOJx#9_LSx&@;!03Rk7%M%LNe$s-#>04zm&TBFm}CvP*-??00{+ z@!hJGOmFRyHHovqS-$pJSB&>>&wbJdcDbif>ezx~DjSM3IN@{XSW+_6EfX^b|7Fh} zX0BNqS3q(wp01bWb_v$Is-fr-q`Bv8^+xm#O~NLZP_IwzZ2t(Wm2N6E#ty zCrE_zZO2OG`-+K=`>M$lwo$9}i&kh?jme#n386DUV4#*O&(bjy9?_{SA=hlY+FF#K zL349I<)^c@vz)dcd#^@qTdkx?Uma73n;CFjC8Erd$GX7kSfza8g_Z0@ zoARjM(C0;-sGK?F7|SdjZ@fRtg2GYp&usb!DpR8mc^t9`B^OWr8o}b8^kA@F&6GSO z_FN|Cv|<%XBa;G^dFF()lG)?oDU%Mmq#TjaLGv7;SdOL3lLudQYrV1PpwKU2!VCaO zZ!7gMTd1<0x(M+=$Mnyh%72bO$KO5fJ@-?7Oz5E^P=YMvUGp{lP!6S3H$$e2OCKHI z%}KhBoQzIpaPr*DNK0n)%EbD6-QA8GA=7Cw7?7#2FZ}xY;MZTVN;$SA{ouMRGxg1_ zTupQw%3ZJY*IjlrFZPk{2}dSn%w|7f*FHdU&xM4gEaY;LDGVs{vvZ3*)#*{^9Gj2m z?QBoU$tT}$2vhc0y}DBexW-tRoSR4U-Wf;^zlyaCa?EAQ1~KIthzB^2=lX#{U#y11 z=zRC^JgN@wiEgUvKkR_t9_p9`OyAo2CrU-YXKBz;)k+$bGwzuT8cjpV1>hO=76qn_CP99# z9xa8PdUF#c4K7~82@s}kTjM%X-CVgc?dp_m17-U7&b>1u^)=I<=AO!*t97^>K-&#F z-@W?I;o+DUX3}}k3?}LGJr#T!Oyx8kN^aMqhkie|EpWLIFy>gkA8s>{tl0v&9j^g7 zYXt*U9+i$ZvhVUJ4RB@7s%|^W>3ahu9eXupcC%P!%VH z_Qyve>Ab&YOG-HWJU-eOG7*zT+FLKPZ?5M8?{r#dy=8t3<>aL;e6ny|0}j2%ap5?P zw4>kSnqCl&pE5}iyoC?QJtsW5)Rn1##i$&*&DjeP#;>sNfkS(TeE$A#j*cKrJ6kaI5d2_027em;4C@Y#>0%&r1?xXzm^;IjC|M8E1z|2bd`%YP~ zu7&lzu$Om?ipqNRC<7RpDo6x}`X5`zNrT@dKwpYfD5*R5^5AT;pxq2CQwcpdeDfqU z4Jhw0!_G8rB_uMJO{G99C3r_l@PGY^S)`u}_xA_;`^LUEJk#@p^4T+xjCB`lP5OCg zm(f!5=75zX!>oS)9jz61%xRA>5so%KZ$hl$FYG_gDfi0Q5dNg!pA#W|kU2)atayEL zVc>^mP8LMo0ZM{-9@?R>bjr`P6p6jy4BW93fc)(s@^i&<8Bi(}J^4@WZPa7DYtmu! z9}F3<0p*%(lLN8Lv5mo;gwx7)QfVpP@Pc&5K?i0(|Gdo|=_$!XEX8<^kIP$4=cn+DQB=)EVlZe988;BU_%bi7Vy-9)$*BQA6j^ zwn15yxkg|wI8_ez!CP#?4J|vPZNi5k?LM|5(C219pZrYAJMp60Ye+egJjMB&2tiO{ z5+FG)gH#>vD`_lwl`^L4(|I(Y8{VyO`O7m?x0Ka-EI>}Ia;<1r2W0y@^$r-yo(i}f z1UH(k{H}Fqu5!?cC2BKjK)H?n*r$$kcHcRHLY+fs-4Ur@`pQ3!P7zWk>(1lJtseIT z&EB4UzKf->tNPx@~?ad0OSb;q0Mz~l$(=l=F_$g`6VWoz&gfZgc0wbbF6K3_gQzhA}6=YH)4 z(}daBn&sXD$8}F-29^2oT&2{X)ahDFYIRQf*4ZN(F2g?Z<9bispm@J@q5)bqUSgY^O`nu$t z@Fr<*)w7Q81rT-`?@s$xHsqu}1$05bQnD_%z4lD|aHQ+IC>%_LnU(Zs1z7!-%aaj3xPS-mg3ve_R!>g(LH8l{9X)_+m@uYA|5Ebr7ex?4YKtkE|ur@p6B z&Hau`H_aKE+^^U&6X-UF?TwW&$15}Rtn@jr3O0W-xExz9{`HT)aNiqd-;s(sySny< zFJ=w1n8?pn#_Q;l*g`au_s*=A$P5Q-$@?rX@hWk8V_|s&mTfUpSdV|%%sI}6*kAes zK3q!BlQH$z!>P4*?Cp4_{1IbG4W>}E#kimP^}HSmGe&u1Hizem6q(sd<@8#Sb3V5Y zYsH32jVQh_nk_L4r)I-mVW4;#aeHsz8}J>g*1oy%_K_=nU5?99E4|j*u?hT<{(6%c zGOxZ67>TTzp7%M&qsi$wIN;A;#yw@UK|H}HELSNf{>AUf8R#T>s-kS4_4k%I?9fXq zerTKwest#@zlQN{t**b?W(S`vQZ$3+_@-c(ZJzI{F!iiE(ut;1rW_UXeV1`_DX2hK zsb6CdmIt2h%nVRMUfO2|d?`}Mm8Rm5Fe_Zk-&N=iUu?`6c|t`~lv3H-q&@4G&Y+X_wSO}<6HL1c z@3AZ#5WZ!#YAI=&0?$l_W{#+clEu}27vo~_Q1=MKd=Z6dmyKItVX1At?u`dF+c@KHuq&t z{bw()eZ0NC>q=-b#ylOL2()E?JN30F{gk69_h0u#fDvrvl*+pD9TO=?euunkxB>4J zjX8XSKiX)g*l%^+_ic<-i=MNW(%@?MiKwqn|IqNcPA^_a+}*n;qQFJB-PnGQ;MkD! zmZ|-z7pZWp7HM@YpZDHa%W9HB7^#Mxvo`$&)@;XJ_(ptHObvL&lmzm4%bD1g#RY1Kd|RhJ81Gto9{Na@(-$TKHTG_t9o|PlsE#hC!~V52)3qmGPU9Z zspo|4vT{;hEwEzP`XfYq((*F{2K6`8y9yVBL9;-d??TH- z;o z1HNa6`dLDzT3`I!i*3EF@Go~qiO7~C=YHf>I>D8btr}X*+fH5j&++H@bNqZ>eyS#a!BHz;2b zdMvlPNd0zuueR+iFv6z0b9JYRotEL~o0JM-H(WBQO=CK-y~dKgmXE%O-qO76r%ybk zdPPm_TDg+E{8${DLq9mBsEmCFnd3RH2dF=o^hF9OT}I{Mi-McwFT_@N)BZ>q!S_YS zZMo9CzHrayy^@OJpPC9$b}= zW=Yew5RUT%W!kguVeecHd=^$2NK^z>39I%}gYZzmH&?Ba_|H{!-irJ_f1`p{`q`nV zuuI+mXk%FiEIw@nOX}Md`>7!n_l?|3SuB=LAE$ZrR|JA9=l#ZYF{NX){oXfj+%<6A zaQnlvJ3jsaF4RntQ{iofuIYg{%9bgm9J$QBS+AncNTZcXYk_c3)>POE?sd*F$$Hl| z?3F9z+=79)7%D`Xho!)F9*pl4CdUeid2~Nr{`@p)A&74^jt*5hVR_U~wYJjet#H8Q z^n4LE(&po=47ZGbw{ol+8T#Ob)2Jxp5CTsMh+HX9PAS*lr47=qVt9fCPluCS3&STJ z0zl9H?S04z;tD9jh%hLVS`2M+5vPN#t)LpK8fkCiitx;ViSME~c@ha{52?I3?AL<9 z1WPS3JqDH6el$woFJ?49MLd#fG+|@2F%(tfd*R7b_Za+-O)9bPE*;Okimlumr+7`A zP0T!r1Z-VJp~hwcgiVqfJo1egTg!U zv(i_?fp3Jswh*Rta{c=C3*X=0_}9OF;n%gCsn*m5rxq{2G3U9S;w|&D`2bERl8wxid4oo?V1F~nAlICoTS6?=t zFY%zrRj`!tNS<6nf8e;naM+-ATM$O&m!2`50`W0E&7)cmWW_B(O=wkhUT&|_>3Wg4NLik^;wJo)h$US# z0lWN6@ev;qib(Y8h|Aa3A)A)l>BGzh92j--G$t!vje!pt3lBX9NGE&ux298Z>`Q0z zajiozuYLG0RKND;@D!}NnW^byb`0_(rZH8g&!a7AkBt@llDb-X-_EqOn(mtKtDe}C zltPDEu%3{kD+6`4V8XBYsZBV|Cg)Jj0O)jVDUHwjugA#<9(=&M8Dt_gEwmZ=LUdF!Ji{+{c`}aZHGPZ=?>sH_pj5Z~8;b->-3R7OlZ}k~%$;SP*jjTW4 zC>s<_XDn^B&(Bff&1c{VD;oVccci_32QpJ z2g#G+t9eA)QEUTgwj95vG>3;NXgjtJt;Mo}b;;k>*ew8<;Zi9MP`Om5U z*cg)va!{7kwP;8sP}I>K_t+mLhvKQ6h@e|hDXNQ1RJx!I-hLoQkG}B!F@UN}PTDo{ z?;PKq>cj9Kuu0xE6#e-uw-#O~4^5jDlq;3mTI`cj-j22<&dlJ4K*pPI3|{~!xA5oq zbNo5}=J8oqGYC+Y;aB0 zL|~aZNh=*f@Ur)fkFz{GHj!4;wL<2qW9-4!hP4KUE5N)~DuIGH+p$&?P0Y;f{e6OY ztg2(*8~3$wUw6(FpDC1xG@s9fudgrcuP=B_!app6SHn#RC(kv=X5ow%rMcgk?{RMf zGKFGDe7-138szXoZ(W^elWZ0W6tb)I9N6j)ZX*uso*3nB~gW1?V&v3JQ8oSl6R{DHwZNzt48(dt}Hw z+oDnL?RaePM7!-A4?BjOc%3h(ERe4noF>}=Z$?h9={ zycIcCtw(s3?dCD@1CH7cHv`O#hwa#;5)!vfzGojCvAS&M%UDtf001BWNkl|QI0ymCtSeWe zQr^bj!G8I@+VPYF4_rNoxXQEQBQ1|mxGYeAKsK?l_{5+}*RlBh2%UvixzYwFUzRg@ zU?U6q^P4LA$8K|Rzyice0WP2;PpJmZF=&<$e4%-T)k@_)2MkLU0E!Of$7(H@Sm?ilFEaP@6>N|oa?>PbsY6I>7{f^pxet; zh!SMi0JkN*6e!7aMdyn0tX7H_Ol)y7fK^G4-J^^YvA z9Eie;^;{J_d6moGl%g*!(JOn7-@iSC%7_or5_ccp*%#`)MYYFc)tmQD<)zZQ_&$UN zj66;P%d>{&+i&_&>6?e%`8O1c@qFifaXhxR(e9Z_5QRVW8m}w`fx`>;z8^R)46O0A zRw`drq&sk>-o2fxdE&>Kh{m9DIrq4FNk9`Em5cPJAUw=3RT9&ui7E>K+%844o;;9g|tqzoPsSO2;-HtH+OkvidozUnlVj z->Ppl!L@ZCQ5v2VTbHKV9n+LEBGdML<1*kqZyzX~mdu(HLv-wjll0@1O?zxz7A_AK zTo4X*Xc<=eh)m0u$BC`vqXY|O)}Q0g@#pw^$GVot`1#uimes-_(TnTJ=0?j5*XNp9 zS2M7z?@TJSqYYEnZrK!{hp(FpmE2;#SBph#)T3#uF>tJtDBHfs1%TV|ec!O};N@2a z+&mY@tu?b5(LPcboqgxW_L&h^{0Rk0wO2$>E`S9*N>rq18umW77xmCgBi^R+Z9QR# zSx#jaqK#F3ZdrKgzR~2$?ik)LL;E{$_?SWvXROI9GYfSrGIdKug%d4@Z9*JTyNq!1 zmXrm=ArpC4OCj-s-zeu*{0qRwWVE3syz9op?0qTojIq>KMW^*bI`z%%2T0oe zY0 zakQ~>N(aGWfi3x3F}>*H)_u8pkGeFm)MD$u(xzx)^UP96>U-ZGIG?kmDd36$Tg@%X z&uU>$euru77yl8ZMU}*RM;g&>8@JuHe|#tjBE03E-leVW`jSy`K~0pHaCd=+Nx?dX zCiN&clws3D6#(CnVCP0mj@i3p%lG$<>-w%05wYjV9geU2&Q(LXO+gJm4eiKo!4-5~ zXErE#%%PDS`gmT;Go=t>+>7NNg#g{@9N&>1Zjnd5LCkXn%BnpxA}|=i@%Q3iCk0Ke*!*F&lQ1V9 z%(T~;4m%4dhaTmxndoqL2a|X3mPHdT111M>Tp5;- z7OxAXoaHOPT*&k31O*!ZYSc(N0_l2AKvzvIxkhL0aof9$x8sz4=TnL%50vSSju!J_ zHD=-#@uA0+D=P;rD}S>ti!G#X1Tf&=@`m-4QgO&!#k>$Xa2D%GD$w{eS9(?Cr( ztd!RbESHQz8^zg&TIIw3<6&No=2kxrxf<1`o`g;nwh!7hww=YM?nTE*2!fc5q%bc# zi^etHKLs4h674(GE^M2J0cEw>I(t*EiUo)VEl+Cf35Xq&8+{usmEhHuv#Tv7r*T{; zpHDj{VMRJi+@Zex92Sus`Eu#>LZB{f9Xex=W?k1$DhsN;GI_cjYCi>)74HPQibTbZ zP)8#JbqpqRg7uQ18Fibw?lI?h)7E%SjOED$zAa0D~H>wzv6cjrV-=(GS;#J${}* zjP}sFo!xb*jbjHt1|cWFU}pf>9kAy%1WotpOtYTY7!KauMJC@~?pT|=%ZeA%*^ImO zohV!QKDP*R@_xz%t_s!Kdrj)^XZMbj4T6eCN zU0AicY?Th9x~RsCI{o+cSg~!kVRnJpsd@sFv=uE=>YBf}kEe>=r`=HjJx@I=g}#gP z|1shG9CqtKDRumk|0P4G?9?qoC-0%E^WiTS1N~YQEsgYw0LUxHAHcSqns)`9no}1Gceq<-@Lw)(2cW1EmOWY z+5ox57}DbGyn8}6Db>Z{*!sqh^VBy{ypZm@r!w1)O<67UiZ-Z~g z_jja6<>&tX$X+XHuv_Fn=jvu64v~&CEyti*E^~*~%JFdIMtY($e3XTyG8;31o0at- zBn7$>m5vvk6P*$&R(bCTCOU#hxC#3Yly%Z z8@mg>zA5UXxkize%}OT8*_>6DaMEEQX;;Z`i@p}XJtEjIpMnzJtDjg!3yiF3Nuz~n zc4cIsJM9yu9zh$|<=C66bSf2?z&7gCz`Ui9-rWWXDATZgOl(jl;))-rb14pyvA+V| zD`Wey-}^Pts*3AxP+_SD`IRMq6U*`tpFO~Kyh}Xe%@K^rAbmvL4W13xNd-TlV7Fdr zq{nj@|3e5v@VDFVE;MT1X|SzV!>cm&oax=y4q)AeI|ItyZW`nbMc1)R+F{_I_VO-G zQQS`^z2DA-`%<{m5`CO0pvU9qUm}Xa6d1wmZNR-9>-$dG@e5qFqx{kLp5JrGH&-fe zX}h1-Ns%VgSAx)oVPDG9K|+m6l+GL5tiI<`zmngzCz>jkRj}Z@C|#af4p%^PZ@GPC z=8l_=?w%;tsS9u1+aoo&$E2&zeZeov^rkGz^izrBQGvb0j43Dj%TuL358*eWg+6BX zy5|bF#?^^Otr4A~?e#d>iIZDbg{|zmi~;4d+#7s$lz(!NY$;a>6WZPmy)pa((=vP- z>=@I+jK6gss6*y!Y+wPk1H`BUmfZ50DWtUa(GFT2bs7@`wQ87}rVI9jK~X{SyuwduX1z=LcpC?qKvj;#HgY?@ z{d;6()$^&pLs^qb{J?2`uXLl()T5-grp1;yg8);OXiaoR);EZVKIA|Ftv;4Kw`>^E zd%99-Lss4)?hS0KOg_F_mIWI5D4UbO&YCVG2K zswtR4z8~l!H)xBhtx5a%TDgB-rTGgxv-h&^y0?~Ha>NDa2ec*|dB_ma)77aZ`ZD=) zg&s89P{GXvzAQszegotcHlsdB0QVH&Cr`A;opH1IJny$|p_B51xoj2TB}}+7zU;B) zc2Hg~5SK0yXQeHQ;-jv|7wu8QpLBn8e#WE8qtSLa^&dy3zjh#L9zZ*YQ@*QjA^af3 z)o}2BKC;r;W76|-$66ahm-M8ayM=i1c{_MM9G!_R&MHyL549p~q_QOURTFm|K340< zf}K%XKaGPnFleJt-MUW=_cxt2270}f$M$k8ys68CCv@flXM#|D^o7fblsGs}^V!xK$&V@2tbeMv{!A5mV zW)FG*gqsVH$-`rU)Su)3{#a|_KmOxC{Mj&Wj!ra=0^6v_B^I z`q-lJ*p!W>afvJ`nL^|lPxd{+ORrnL_xoNpfgfW*{l{AG5`qTBF@NtQbnIyqp*?b-rvoJ>~sTLqRo$Q*PM@kZ5UcP?%M`dn$S zYo&4rs+ZVhz9q2iz+Mi!6ZYG%c4Tc^TgKKMpA5am;QJ&KB>>g597v=7P-YGdT4!7{ z-~IjFdqtJPB0=ULiZq0g>4wtSySY;A=7#Lgpz4tDWQe+UiizyWNO8r0ynj$#pN+G5N3im^@f0EsRdV|`UDfI+x@|-*g}n)<`6Xc`?N;u> z{usL?!bB{i5o=B6>)2A%G%8fZ*7Bw?6`Y7OJSiEcbBYz*4aRg(m7_{lJ*W}y=zv+} zZ}+Q;q&tBtHpUF*no%{!XmrP{#)RYEu|5&IWX9er1=Ts%ux@2!z@B3>fT;pnIoKg7 ztF5T#3$_%vglR2P-4$%a-ayV`H(A+eh3i`W**>{e9$Ji)^$LD^@?Y!zZ0y3F3MzB8 zvRNq~%-pa<>FfaWs#N>88SK7GfPW`EGQ)Ghhu^7S&}riozRtw*q_iHBlQRrB=w%ny z0(m|bbaxhIkeS;$mdRfo0PY$sm4H;bT7hXs)`4VkRBQw-`07RlVdQFHS(& z=oGSo`-*g9AnjR^0u`hl<5osvQi$-6lLX9KW@H<7^)Z|&OhFte!N2kS{R`i}9Jk+{ z?)AFrS_f&)3e3;SfIzjW>8^P)$4q(hInZeQ7=w>`UMK4)gozz0x=s$^@E*4Zld-d~ z;){ANMVGX#ymHXBewXoicKFeYslDl$hm>20`vOZ$v039r-D+iu$l}wT0=pFU)w~5c zVI}mRl@kJQtV~-~0hGnEXfR4JW%&#&ixFEmEnRHhc-*QnkRMpY+u+M}(V(*RasoHL z4MRm{H%EI#p0R3o3?nBCX15H1Jo)%&e-y8K(17VS*G-|W0FFTvjeUF z5+C!s@x3(g<2&y|(!Q}=_O;uoDhbEQrOnUD1b*Cu+-ttDrOj^vG;ocKCS}W1U2XG%dL$fW;~R>Hgp2`UM4a+TUYqO+-tRK24nm)bgXPmxQ|6>Y1YpAKm1Hp*uUN$SMD z;H33`^G?yi%TYno14d`sYwkB$#h>L7_joS3!h^QQ*VULg9YGf zUC3e&dTxK(Ft8CnTC$I_2A6}I8s7KS94$so8++LK&Htxe-|e9OM;iqR%Tsr57#0)m z-)iOcDTj}D5B-~U>3GSPc~|jA?2=A{J#{GdzSY6QUS{1s;dN>a()5x&>Lcv

u(` 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

#NEgIutJdo^{yc+sENn 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

FTQzQ%fAV-HIxG~w~@`K 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

$=bic_t}K+RuUR4F%TFvFw{FwLTh~5?Xv1!HQf_ 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