Really substantial progress in generating Selmer templates.
This commit is contained in:
parent
4d6bad7c2a
commit
fd9e65b7c7
|
@ -5,4 +5,5 @@
|
|||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||
:dependencies [[org.clojure/clojure "1.8.0"]
|
||||
[org.clojure/math.combinatorics "0.1.4"]
|
||||
[bouncer "1.0.1"]])
|
||||
[bouncer "1.0.1"]
|
||||
[hiccup "1.0.5"]])
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns="http://libs.cygnets.co.uk/adl/1.4/"
|
||||
xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
|
||||
xmlns="http://bowyer.journeyman.cc/adl/1.4/"
|
||||
xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
|
||||
xmlns:exsl="urn:schemas-microsoft-com:xslt"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
[clojure.string :as s]
|
||||
[clj-time.core :as t]
|
||||
[clj-time.format :as f]
|
||||
[adl.utils :refer [singularise is-link-table?]]))
|
||||
[adl.utils :refer [has-non-key-properties? has-primary-key? is-link-table? key-names singularise]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
|
@ -31,23 +31,6 @@
|
|||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn key-names [entity-map]
|
||||
(remove
|
||||
nil?
|
||||
(map
|
||||
#(:name (:attrs %))
|
||||
(vals (:content (:key (:content entity-map)))))))
|
||||
|
||||
|
||||
(defn has-primary-key? [entity-map]
|
||||
(> (count (key-names entity-map)) 0))
|
||||
|
||||
|
||||
(defn has-non-key-properties? [entity-map]
|
||||
(>
|
||||
(count (vals (:properties (:content entity-map))))
|
||||
(count (key-names entity-map))))
|
||||
|
||||
|
||||
(defn where-clause [entity-map]
|
||||
(let
|
||||
|
|
307
src/adl/to_selmer_templates.clj
Normal file
307
src/adl/to_selmer_templates.clj
Normal file
|
@ -0,0 +1,307 @@
|
|||
(ns ^{:doc "Application Description Language: generate RING routes for REST requests."
|
||||
:author "Simon Brooke"}
|
||||
adl.to-selmer-templates
|
||||
(:require [adl.utils :refer :all]
|
||||
[clojure.java.io :refer [file]]
|
||||
[clojure.math.combinatorics :refer [combinations]]
|
||||
[clojure.string :as s]
|
||||
[clojure.xml :as x]
|
||||
[clj-time.core :as t]
|
||||
[clj-time.format :as f]
|
||||
[hiccup.core :as h]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
;;;; adl.to-json-routes: generate RING routes for REST requests.
|
||||
;;;;
|
||||
;;;; 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) 2018 Simon Brooke
|
||||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(def ^:dynamic *locale* "en-GB")
|
||||
|
||||
(defn file-header []
|
||||
"{% extends \"templates/base.html\" %}\n{% block content %}")
|
||||
|
||||
(defn file-footer []
|
||||
"{% endblock %}")
|
||||
|
||||
|
||||
(defn prompt
|
||||
"Return an appropriate prompt for the given `field-or-property` taken from this
|
||||
`form` of this `entity` of this `application`, in the context of the current
|
||||
binding of `*locale*`. TODO: something more sophisticated about i18n"
|
||||
[field-or-property form entity application]
|
||||
(or
|
||||
(first
|
||||
(children
|
||||
field-or-property
|
||||
#(and
|
||||
(= (:tag %) :prompt)
|
||||
(= (:locale :attrs %) *locale*))))
|
||||
(:name (:attrs field-or-property))))
|
||||
|
||||
|
||||
(defn permission
|
||||
[property form entity application]
|
||||
(or
|
||||
(children property #(= (:tag %) :permission))
|
||||
(children entity :permission)))
|
||||
|
||||
|
||||
(defn visible?
|
||||
"Return `true` if this property is not `system`-distinct, and is readable
|
||||
to the `public` group; else return a list of groups to which it is readable,
|
||||
given these `permissions`."
|
||||
[property permissions]
|
||||
(let [attributes (attributes property)]
|
||||
(if
|
||||
(not
|
||||
(and
|
||||
;; if it's immutable and system distinct, the user should not need to see it.
|
||||
(= (:immutable attributes) "true")
|
||||
(= (:distinct attributes) "system")))
|
||||
(map
|
||||
#(if
|
||||
(some #{"read" "insert" "noedit" "edit" "all"} (:permission (:attrs %)))
|
||||
(:group (:attrs %)))
|
||||
permissions))))
|
||||
|
||||
|
||||
(defn csrf-widget
|
||||
"For the present, just return the standard cross site scripting protection field statement"
|
||||
[]
|
||||
"{% csrf-field %}")
|
||||
|
||||
|
||||
(defn save-widget
|
||||
"Return an appropriate 'save' widget for this `form` operating on this `entity` taken
|
||||
from this `application`."
|
||||
[form entity application]
|
||||
{:tag :p
|
||||
:attrs {:class "widget action-safe"}
|
||||
:content [{:tag :label
|
||||
:attrs {:for "save-button" :class "action-safe"}
|
||||
:content [(str "To save this " (:name (:attrs entity)) " record")]}
|
||||
{:tag :input
|
||||
:attrs {:id "save-button"
|
||||
:name "save-button"
|
||||
:class "action-safe"
|
||||
:type :submit
|
||||
:value (str "Save!")}}]})
|
||||
|
||||
|
||||
(defn delete-widget
|
||||
"Return an appropriate 'save' widget for this `form` operating on this `entity` taken
|
||||
from this `application`."
|
||||
[form entity application]
|
||||
{:tag :p
|
||||
:attrs {:class "widget action-dangerous"}
|
||||
:content [{:tag :label
|
||||
:attrs {:for "delete-button" :class "action-dangerous"}
|
||||
:content [(str "To delete this " (:name (:attrs entity)) " record")]}
|
||||
{:tag :input
|
||||
:attrs {:id "delete-button"
|
||||
:name "delete-button"
|
||||
:class "action-dangerous"
|
||||
:type :submit
|
||||
:value (str "Delete!")}}]})
|
||||
|
||||
|
||||
(defn get-options
|
||||
"Produce template code to get options for this `property` of this `entity` taken from
|
||||
this `application`."
|
||||
[property form entity application]
|
||||
(let
|
||||
[type (:type (:attrs property))
|
||||
farname (:entity (:attrs property))
|
||||
farside (application farname)
|
||||
farkey (or
|
||||
(:farkey (:attrs property))
|
||||
(:name (:attrs (first (children (children farside #(= (:tag %) :key))))))
|
||||
"id")]
|
||||
(str "{% for record in " farname " %}<option value='record." farkey "'>"
|
||||
(s/join
|
||||
" "
|
||||
(map
|
||||
#(str "{{record." (:name (:attrs %)) "}}")
|
||||
(children farside #(some #{"user" "all"} (:distinct %))))))
|
||||
"</option>%{ endfor %}"))
|
||||
|
||||
|
||||
(defn widget
|
||||
"Generate a widget for this `field-or-property` of this `form` for this `entity`
|
||||
taken from within this `application`."
|
||||
[field-or-property form entity application]
|
||||
(let
|
||||
[name (:name (:attrs field-or-property))
|
||||
property (if
|
||||
(= (:tag field-or-property) :property)
|
||||
field-or-property
|
||||
(first
|
||||
(children
|
||||
entity
|
||||
#(and
|
||||
(= (:tag %) :property)
|
||||
(= (:name (:attrs %)) (:property (:attrs field-or-property)))))))
|
||||
permissions (permission property form entity application)
|
||||
show? (visible? property permissions)
|
||||
is-select? false]
|
||||
;; TODO: deal with disabling/hiding if no permission
|
||||
(if
|
||||
show?
|
||||
{:tag :p
|
||||
:attrs {:class "widget"}
|
||||
:content [{:tag :label
|
||||
:attrs {:for name}
|
||||
:content [(prompt field-or-property form entity application)]}
|
||||
(if
|
||||
is-select?
|
||||
{:tag :select
|
||||
:attrs {:id name
|
||||
:name name}
|
||||
:content (get-options property form entity application)}
|
||||
{:tag :input
|
||||
:attrs {:id name
|
||||
:name name
|
||||
:type :text ;; TODO - or other things
|
||||
:value (str "{{record." name "}}")}})]}
|
||||
{:tag :input
|
||||
:attrs {:id name
|
||||
:name name
|
||||
:type :hidden
|
||||
:value (str "{{record." name "}}")}})))
|
||||
|
||||
|
||||
(defn form-to-template
|
||||
"Generate a template as specified by this `form` element for this `entity`,
|
||||
taken from this `application`. If `form` is nill, generate a default form
|
||||
template for the entity."
|
||||
[form entity application]
|
||||
(let
|
||||
[name (str (if form (:name (:attrs form)) "edit") "-" (:name (:attrs entity)))
|
||||
keyfields (children
|
||||
;; there should only be one key; its keys are properties
|
||||
(first (children entity #(= (:tag %) :key))))
|
||||
fields (if
|
||||
(and form (= "listed" (:properties (:attrs form))))
|
||||
;; if we've got a form, collect its fields, fieldgroups and verbs
|
||||
(flatten
|
||||
(map #(if (some #{:field :fieldgroup :verb} (:tag %)) %)
|
||||
(children form)))
|
||||
(children entity #(= (:key %) :property)))]
|
||||
{:tag :div
|
||||
:attrs {:id "content" :class "edit"}
|
||||
:content
|
||||
[{:tag :form
|
||||
:attrs {:action (str "{{servlet-context}}/" name)
|
||||
:method "POST"}
|
||||
:content (flatten
|
||||
(list
|
||||
(csrf-widget)
|
||||
(map
|
||||
#(widget % form entity application)
|
||||
(flatten
|
||||
(list keyfields fields)))
|
||||
(save-widget form entity application)
|
||||
(delete-widget form entity application)))}]}))
|
||||
|
||||
|
||||
|
||||
(defn page-to-template
|
||||
"Generate a template as specified by this `page` element for this `entity`,
|
||||
taken from this `application`. If `page` is nill, generate a default page
|
||||
template for the entity."
|
||||
[page entity application]
|
||||
)
|
||||
|
||||
(defn list-to-template
|
||||
"Generate a template as specified by this `list` element for this `entity`,
|
||||
taken from this `application`. If `list` is nill, generate a default list
|
||||
template for the entity."
|
||||
[list entity application]
|
||||
)
|
||||
|
||||
|
||||
(defn entity-to-templates
|
||||
"Generate one or more templates for editing instances of this
|
||||
`entity` in this `application`"
|
||||
[entity application]
|
||||
(let
|
||||
[forms (children entity #(= (:tag %) :form))
|
||||
pages (children entity #(= (:tag %) :page))
|
||||
lists (children entity #(= (:tag %) :list))]
|
||||
(if
|
||||
(and
|
||||
(= (:tag entity) :entity) ;; it seems to be an ADL entity
|
||||
(not (link-table? entity)))
|
||||
(merge
|
||||
(if
|
||||
forms
|
||||
(apply merge (map #(assoc {} (keyword (str "form-" (:name (:attrs entity)) "-" (:name (:attrs %))))
|
||||
(form-to-template % entity application))
|
||||
forms))
|
||||
{(keyword (str "form-" (:name (:attrs entity))))
|
||||
(form-to-template nil entity application)})
|
||||
(if
|
||||
pages
|
||||
(apply merge (map #(assoc {} (keyword (str "page-" (:name (:attrs entity)) "-" (:name (:attrs %))))
|
||||
(page-to-template % entity application))
|
||||
pages))
|
||||
{(keyword (str "page-" (:name (:attrs entity))))
|
||||
(page-to-template nil entity application)})
|
||||
(if
|
||||
lists
|
||||
(apply merge (map #(assoc {} (keyword (str "list-" (:name (:attrs entity)) "-" (:name (:attrs %))))
|
||||
(list-to-template % entity application))
|
||||
lists))
|
||||
{(keyword (str "list-" (:name (:attrs entity))))
|
||||
(form-to-template nil entity application)})))))
|
||||
|
||||
|
||||
(defn write-template-file
|
||||
[filename template]
|
||||
(spit
|
||||
filename
|
||||
(s/join
|
||||
"\n"
|
||||
(list
|
||||
(file-header)
|
||||
(with-out-str (x/emit-element template))
|
||||
(file-footer)))))
|
||||
|
||||
|
||||
(defn to-selmer-templates
|
||||
[application]
|
||||
(let
|
||||
[templates-map (reduce
|
||||
merge
|
||||
{}
|
||||
(map
|
||||
#(entity-to-templates % application)
|
||||
(children application #(= (:tag %) :entity))))]
|
||||
(doall
|
||||
(map
|
||||
#(if
|
||||
(templates-map %)
|
||||
(write-template-file (str (name %) ".html") (templates-map %)))
|
||||
(keys templates-map)))
|
||||
templates-map))
|
||||
|
||||
|
|
@ -1,11 +1,75 @@
|
|||
(ns adl.utils
|
||||
(:require [clojure.string :as s]))
|
||||
(:require [clojure.string :as s]
|
||||
[clojure.xml :as x]
|
||||
[adl.validator :refer [valid-adl? validate-adl]]))
|
||||
|
||||
|
||||
|
||||
(defn children
|
||||
"Return the children of this `element`; if `predicate` is passed, return only those
|
||||
children satisfying the predicate."
|
||||
([element]
|
||||
(if
|
||||
(keyword? (:tag element)) ;; it has a tag; it seems to be an XML element
|
||||
(:content element)))
|
||||
([element predicate]
|
||||
(remove ;; there's a more idionatic way of doing remove-nil-map, but for the moment I can't recall it.
|
||||
nil?
|
||||
(map
|
||||
#(if (predicate %) %)
|
||||
(children element)))))
|
||||
|
||||
|
||||
(defn singularise [string]
|
||||
(s/replace (s/replace (s/replace string #"_" "-") #"s$" "") #"ie$" "y"))
|
||||
|
||||
(defn is-link-table?
|
||||
[entity-map]
|
||||
(let [properties (-> entity-map :content :properties vals)
|
||||
|
||||
(defn link-table?
|
||||
"Return true if this `entity` represents a link table."
|
||||
[entity]
|
||||
(let [properties (children entity #(= (:tag %) :property))
|
||||
links (filter #(-> % :attrs :entity) properties)]
|
||||
(= (count properties) (count links))))
|
||||
|
||||
(defn read-adl [url]
|
||||
(let [adl (x/parse url)
|
||||
valid? (valid-adl? adl)]
|
||||
adl))
|
||||
;; (if valid? adl
|
||||
;; (throw (Exception. (str (validate-adl adl)))))))
|
||||
|
||||
(defn key-names [entity-map]
|
||||
(remove
|
||||
nil?
|
||||
(map
|
||||
#(:name (:attrs %))
|
||||
(vals (:content (:key (:content entity-map)))))))
|
||||
|
||||
|
||||
(defn has-primary-key? [entity-map]
|
||||
(> (count (key-names entity-map)) 0))
|
||||
|
||||
|
||||
(defn has-non-key-properties? [entity-map]
|
||||
(>
|
||||
(count (vals (:properties (:content entity-map))))
|
||||
(count (key-names entity-map))))
|
||||
|
||||
|
||||
(defn attributes
|
||||
"Return the attributes of this `element`; if `predicate` is passed, return only those
|
||||
attributes satisfying the predicate."
|
||||
([element]
|
||||
(if
|
||||
(keyword? (:tag element)) ;; it has a tag; it seems to be an XML element
|
||||
(:attrs element)))
|
||||
([element predicate]
|
||||
(remove ;; there's a more idionatic way of doing remove-nil-map, but for the moment I can't recall it.
|
||||
nil?
|
||||
(map
|
||||
#(if (predicate %) %)
|
||||
(:attrs element)))))
|
||||
|
||||
|
||||
|
||||
;; (read-adl "../youyesyet/stripped.adl.xml")
|
||||
|
|
|
@ -652,3 +652,8 @@
|
|||
entity-validations)]]})
|
||||
|
||||
|
||||
(defn valid-adl? [src]
|
||||
(b/valid? src application-validations))
|
||||
|
||||
(defn validate-adl [src]
|
||||
(b/validate src application-validations))
|
||||
|
|
630
yyy.adl.clj
Normal file
630
yyy.adl.clj
Normal file
|
@ -0,0 +1,630 @@
|
|||
{:tag :application,
|
||||
:attrs {:version "0.1.1", :name "youyesyet"},
|
||||
:content
|
||||
[{:tag :entity,
|
||||
:attrs {:name "electors"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "name", :name "name", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "name"},
|
||||
:content ["\nname\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "addresses",
|
||||
:column "address_id",
|
||||
:name "address_id",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "address_id"},
|
||||
:content ["\naddress_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "phone", :name "phone", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "phone"},
|
||||
:content ["\nphone\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "email", :name "email", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "email"},
|
||||
:content ["\nemail\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "addresses"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "address",
|
||||
:name "address",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "address"},
|
||||
:content ["\naddress\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "postcode", :name "postcode", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "postcode"},
|
||||
:content ["\npostcode\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "phone", :name "phone", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "phone"},
|
||||
:content ["\nphone\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "districts",
|
||||
:column "district_id",
|
||||
:name "district_id",
|
||||
:type "entity"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "district_id"},
|
||||
:content ["\ndistrict_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "latitude", :name "latitude", :type "real"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "latitude"},
|
||||
:content ["\nlatitude\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "longitude", :name "longitude", :type "real"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "longitude"},
|
||||
:content ["\nlongitude\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "visits"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "addresses",
|
||||
:column "address_id",
|
||||
:name "address_id",
|
||||
:type "integer",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "address_id"},
|
||||
:content ["\naddress_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "canvassers",
|
||||
:column "canvasser_id",
|
||||
:name "canvasser_id",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "canvasser_id"},
|
||||
:content ["\ncanvasser_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "date",
|
||||
:name "date",
|
||||
:type "timestamp",
|
||||
:default "",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "date"},
|
||||
:content ["\ndate\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "authorities"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "issues"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "url", :name "url", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "url"},
|
||||
:content ["\nurl\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "schema_migrations"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "intentions"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "visit_id",
|
||||
:name "visit_id",
|
||||
:farkey "id",
|
||||
:entity "visits",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "visit_id"},
|
||||
:content ["\nvisit_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "elector_id",
|
||||
:name "elector_id",
|
||||
:farkey "id",
|
||||
:entity "electors",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "elector_id"},
|
||||
:content ["\nelector_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "option_id",
|
||||
:name "option_id",
|
||||
:farkey "id",
|
||||
:entity "options",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "option_id"},
|
||||
:content ["\noption_id\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "canvassers"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs {:column "id", :name "id", :type "integer"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "username",
|
||||
:name "username",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "username"},
|
||||
:content ["\nusername\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "fullname",
|
||||
:name "fullname",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "fullname"},
|
||||
:content ["\nfullname\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "electors",
|
||||
:column "elector_id",
|
||||
:name "elector_id",
|
||||
:type "entity"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "elector_id"},
|
||||
:content ["\nelector_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "addresses",
|
||||
:column "address_id",
|
||||
:name "address_id",
|
||||
:type "integer",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "address_id"},
|
||||
:content ["\naddress_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "phone", :name "phone", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "phone"},
|
||||
:content ["\nphone\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "email", :name "email", :type "string"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "email"},
|
||||
:content ["\nemail\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "authorities",
|
||||
:column "authority_id",
|
||||
:name "authority_id",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "authority_id"},
|
||||
:content ["\nauthority_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "authorised", :name "authorised", :type "boolean"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "authorised"},
|
||||
:content ["\nauthorised\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "followuprequests"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "electors",
|
||||
:column "elector_id",
|
||||
:name "elector_id",
|
||||
:type "integer",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "elector_id"},
|
||||
:content ["\nelector_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "visits",
|
||||
:column "visit_id",
|
||||
:name "visit_id",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "visit_id"},
|
||||
:content ["\nvisit_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "issues",
|
||||
:column "issue_id",
|
||||
:name "issue_id",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "issue_id"},
|
||||
:content ["\nissue_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "followupmethods",
|
||||
:column "method_id",
|
||||
:name "method_id",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "method_id"},
|
||||
:content ["\nmethod_id\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "rolememberships"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "role_id",
|
||||
:name "role_id",
|
||||
:farkey "id",
|
||||
:entity "roles",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "role_id"},
|
||||
:content ["\nrole_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "canvasser_id",
|
||||
:name "canvasser_id",
|
||||
:farkey "id",
|
||||
:entity "canvassers",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "canvasser_id"},
|
||||
:content ["\ncanvasser_id\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "roles"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs {:column "id", :name "id", :type "integer"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "name", :name "name", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "name"},
|
||||
:content ["\nname\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "teams"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs {:column "id", :name "id", :type "integer"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "name", :name "name", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "name"},
|
||||
:content ["\nname\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "district_id",
|
||||
:name "district_id",
|
||||
:farkey "id",
|
||||
:entity "districts",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "district_id"},
|
||||
:content ["\ndistrict_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "latitude", :name "latitude", :type "real"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "latitude"},
|
||||
:content ["\nlatitude\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "longitude", :name "longitude", :type "real"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "longitude"},
|
||||
:content ["\nlongitude\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "districts"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "name", :name "name", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "name"},
|
||||
:content ["\nname\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "teamorganiserships"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "team_id",
|
||||
:name "team_id",
|
||||
:farkey "id",
|
||||
:entity "teams",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "team_id"},
|
||||
:content ["\nteam_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "canvasser_id",
|
||||
:name "canvasser_id",
|
||||
:farkey "id",
|
||||
:entity "canvassers",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "canvasser_id"},
|
||||
:content ["\ncanvasser_id\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "followupactions"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "integer", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "followuprequests",
|
||||
:column "request_id",
|
||||
:name "request_id",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "request_id"},
|
||||
:content ["\nrequest_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "canvassers",
|
||||
:column "actor",
|
||||
:name "actor",
|
||||
:type "integer",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "actor"},
|
||||
:content ["\nactor\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "date",
|
||||
:name "date",
|
||||
:type "timestamp",
|
||||
:default "",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "date"},
|
||||
:content ["\ndate\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "notes", :name "notes", :type "text"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "notes"},
|
||||
:content ["\nnotes\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs {:column "closed", :name "closed", :type "boolean"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "closed"},
|
||||
:content ["\nclosed\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "issueexpertise"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "canvassers",
|
||||
:column "canvasser_id",
|
||||
:name "canvasser_id",
|
||||
:type "integer",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "canvasser_id"},
|
||||
:content ["\ncanvasser_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "issues",
|
||||
:column "issue_id",
|
||||
:name "issue_id",
|
||||
:type "string",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "issue_id"},
|
||||
:content ["\nissue_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:farkey "id",
|
||||
:entity "followupmethods",
|
||||
:column "method_id",
|
||||
:name "method_id",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "method_id"},
|
||||
:content ["\nmethod_id\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "options"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "teammemberships"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "team_id",
|
||||
:name "team_id",
|
||||
:farkey "id",
|
||||
:entity "teams",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "team_id"},
|
||||
:content ["\nteam_id\n"]}]}
|
||||
{:tag :property,
|
||||
:attrs
|
||||
{:column "canvasser_id",
|
||||
:name "canvasser_id",
|
||||
:farkey "id",
|
||||
:entity "canvassers",
|
||||
:type "entity",
|
||||
:required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "canvasser_id"},
|
||||
:content ["\ncanvasser_id\n"]}]}]}
|
||||
{:tag :entity,
|
||||
:attrs {:name "followupmethods"},
|
||||
:content
|
||||
[{:tag :property,
|
||||
:attrs
|
||||
{:column "id", :name "id", :type "string", :required "true"},
|
||||
:content
|
||||
[{:tag :prompt,
|
||||
:attrs {:locale "en-GB", :prompt "id"},
|
||||
:content ["\nid\n"]}]}]}]}
|
Loading…
Reference in a new issue