Merge branch 'develop' of github.com:simon-brooke/adl into develop

This commit is contained in:
Simon Brooke 2018-06-17 06:48:06 +01:00
commit 9d34005f9e
3 changed files with 132 additions and 98 deletions

View file

@ -281,7 +281,8 @@
" ||', '|| " " ||', '|| "
(compose-convenience-entity-field field entity application)) (compose-convenience-entity-field field entity application))
" AS " " AS "
(field-name field))) (field-name field)
"_expanded"))
(defn emit-convenience-view (defn emit-convenience-view
@ -290,59 +291,62 @@
[entity application] [entity application]
(let [view-name (safe-name (str "lv_" (:table (:attrs entity))) :sql) (let [view-name (safe-name (str "lv_" (:table (:attrs entity))) :sql)
entity-fields (filter entity-fields (filter
#(= (:type (:attrs %)) "entity") #(= (:type (:attrs %)) "entity")
(properties entity))] (properties entity))]
(s/join (s/join
"\n" "\n"
(remove (remove
nil? nil?
(flatten (flatten
(list (list
(emit-header (emit-header
"--" "--"
(str "convenience view " view-name " of entity " (:name (:attrs entity)) " for lists, et cetera")) (str "convenience view " view-name " of entity " (:name (:attrs entity)) " for lists, et cetera"))
(s/join (s/join
" " " "
(list "CREATE VIEW" view-name "AS")) (list "CREATE VIEW" view-name "AS"))
(str (str
"SELECT " "SELECT "
(s/join (s/join
",\n\t" ",\n\t"
(map (flatten
#(if (map
(= (:type (:attrs %)) "entity") #(if
(emit-convenience-entity-field % entity application) (= (:type (:attrs %)) "entity")
(str (safe-name entity) "." (field-name %))) (list
(filter (emit-convenience-entity-field % entity application)
#(not (= (:type (:attrs %)) "link")) (str (safe-name entity) "." (field-name %)))
(all-properties entity) )))) (str (safe-name entity) "." (field-name %)))
(str (filter
"FROM " (s/join ", " (set (compose-convenience-view-select-list entity application true)))) #(not (= (:type (:attrs %)) "link"))
(if (all-properties entity) )))))
(not (empty? entity-fields)) (str
(str "FROM " (s/join ", " (set (compose-convenience-view-select-list entity application true))))
"WHERE " (if
(s/join (not (empty? entity-fields))
"\n\tAND " (str
(map "WHERE "
(fn [f] (s/join
(let "\n\tAND "
[farside (child (map
application (fn [f]
#(and (let
(entity? %) [farside (child
(= (:name (:attrs %)) (:entity (:attrs f)))))] application
(str #(and
(safe-name (:table (:attrs entity)) :sql) (entity? %)
"." (= (:name (:attrs %)) (:entity (:attrs f)))))]
(field-name f) (str
" = " (safe-name (:table (:attrs entity)) :sql)
(safe-name (:table (:attrs farside)) :sql) "."
"." (field-name f)
(safe-name (first (key-names farside)) :sql)))) " = "
entity-fields)))) (safe-name (:table (:attrs farside)) :sql)
";" "."
(emit-permissions-grant view-name :SELECT (permissions entity application)))))))) (safe-name (first (key-names farside)) :sql))))
entity-fields))))
";"
(emit-permissions-grant view-name :SELECT (permissions entity application))))))))
(defn emit-referential-integrity-link (defn emit-referential-integrity-link

View file

@ -61,7 +61,10 @@
'defn 'defn
(symbol n) (symbol n)
(vector 'r) (vector 'r)
(list 'let (vector 'p (list :form-params 'r)) (list 'let (vector 'p (list :params 'r)) ;; TODO: we must take key params out of just params,
;; but we should take all other params out of form-params - because we need the key to
;; load the form in the first place, but just accepting values of other params would
;; allow spoofing.
(list (list
'l/render 'l/render
(list 'resolve-template (str n ".html")) (list 'resolve-template (str n ".html"))
@ -71,10 +74,12 @@
(case (:tag f) (case (:tag f)
(:form :page) (:form :page)
{:record {:record
(list 'if (list 'empty? (list 'remove 'nil? (list 'vals 'p))) []
(list (list
(symbol (symbol
(str "db/get-" (singularise (:name (:attrs e))))) (str "db/get-" (singularise (:name (:attrs e)))))
'p)} (symbol "db/*db*")
'p))}
:list :list
{:records {:records
(list (list

View file

@ -362,15 +362,40 @@
taken from this `application`. If `page` is nil, generate a default page taken from this `application`. If `page` is nil, generate a default page
template for the entity." template for the entity."
[page entity application] [page entity application]
;; TODO
) )
(defn compose-list-search-widget
[field entity]
(let [property (first
(children
entity
(fn [p] (and (= (:tag p) :property)
(= (:name (:attrs p)) (:property (:attrs field)))))))
input-type (case (:type (:attrs property))
("integer" "real" "money") "number"
("date" "timestamp") "date"
"time" "time"
"text")
base-name (:property (:attrs field))
search-name (if
(= (:type (:attrs property)) "entity")
(str base-name "_expanded") base-name)]
(hash-map
:tag :th
:content
[{:tag :input
:attrs {:id search-name
:type input-type
:name search-name
:value (str "{{ params." search-name " }}")}}])))
(defn- list-thead (defn- list-thead
"Return a table head element for the list view for this `list-spec` of this `entity` within "Return a table head element for the list view for this `list-spec` of this `entity` within
this `application`. this `application`."
TODO: where entity fields are being shown/searched on, we should be using the user-distinct
fields of the far side, rather than key values"
[list-spec entity application] [list-spec entity application]
{:tag :thead {:tag :thead
:content :content
@ -387,36 +412,32 @@
:content :content
(apply (apply
vector vector
(concat (concat
(map (map
(fn [f] #(compose-list-search-widget % entity)
(let [property (first (fields list-spec))
(children '({:tag :th
entity :content
(fn [p] (and (= (:tag p) :property) [{:tag :input
(= (:name (:attrs p)) (:property (:attrs f)))))))] :attrs {:type "submit"
(hash-map :id "search"
:tag :th :value "Search"}}]})))}]})
:content
[{:tag :input
:attrs {:id (:property (:attrs f))
:type (case (:type (:attrs property))
("integer" "real" "money") "number"
("date" "timestamp") "date"
"time" "time"
"text")
:name (:property (:attrs f))
:value (str "{{ params." (:property (:attrs f)) " }}")}}])))
(fields list-spec))
'({:tag :th
:content
[{:tag :input
:attrs {:type "submit"
:id "search"
:value "Search"}}]})))}]})
(defn- list-tbody (defn edit-link
[entity application parameters]
(str
(editor-name entity application)
"?"
(s/join
"&"
(map
#(str %1 "={{ record." %2 " }}")
(key-names entity)
parameters))))
(defn list-tbody
"Return a table body element for the list view for this `list-spec` of this `entity` within "Return a table body element for the list view for this `list-spec` of this `entity` within
this `application`." this `application`."
[list-spec entity application] [list-spec entity application]
@ -430,22 +451,26 @@
(concat (concat
(map (map
(fn [field] (fn [field]
{:tag :td :content [(str "{{ record." (:property (:attrs field)) " }}")]}) {:tag :td :content
(let
[p (first (filter #(= (:name (:attrs %)) (:property (:attrs field))) (all-properties entity)))
e (first
(filter
#(= (:name (:attrs %)) (:entity (:attrs p)))
(children-with-tag application :entity)))
c (str "{{ record." (:property (:attrs field)) " }}")]
(if
(= (:type (:attrs p)) "entity")
[{:tag :a
:attrs {:href (edit-link e application (list (:name (:attrs p))))}
:content [(str "{{ record." (:property (:attrs field)) "_expanded }}")]}]
[c]))})
(fields list-spec)) (fields list-spec))
[{:tag :td [{:tag :td
:content :content
[{:tag :a [{:tag :a
:attrs :attrs
{:href {:href (edit-link entity application (key-names entity))}
(str
(editor-name entity application)
"?"
(s/join
"&"
(map
#(let [n (:name (:attrs %))]
(str n "={{ record." n "}}"))
(children (first (filter #(= (:tag %) :key) (children entity)))))))}
:content ["View"]}]}]))} :content ["View"]}]}]))}
"{% endfor %}"]}) "{% endfor %}"]})