nice looking tags, moar specs, tag creating

integration-tests
Josha von Gizycki 5 years ago
parent 833347b198
commit fe9c48f405

@ -8,7 +8,7 @@ indent_style = space
indent_size = 4
tab_width = 4
trim_trailing_whitespace = true
max_line_length = 120
max_line_length = 80
[*.clj]
indent_size = 2
indent_size = 2

@ -153,6 +153,10 @@ img, svg {
}
}
}
.quick-edits {
margin-top: 7rem;
}
}
aside {
@ -293,3 +297,18 @@ table {
margin-right: @element-margin;
}
}
.tag-list {
margin: 0;
padding: 0;
list-style-type: none;
}
.tag-list li {
display: inline-block;
margin-right: .5rem;
border: 1px solid @ci-color;
border-left: .5rem solid @ci-blue;
border-radius: .5rem;
padding: .1rem .4rem;
}

@ -47,15 +47,21 @@
params))
(qry session params)))
(spec/def ::tuple-query-list
(spec/coll-of
(spec/tuple fn? map?)))
(defn exec-queries! [& tuples]
{:pre [(spec/assert ::tuple-query-list tuples)]}
(db/with-transaction @conn tx
(doseq [tuple tuples]
(println tuple)
(let [qry (first tuple)
params (second tuple)]
(devmode/send-to-bar
(str (butiful-query qry)
"<br>---Params---<br>"
params))
(spec/assert map? params)
(qry tx params)))))
(defn now-str []

@ -49,6 +49,14 @@
"CREATE CONSTRAINT ON (n:link)
ASSERT n.uuid IS UNIQUE")
(db/defquery ver-1-tag-name
"CREATE CONSTRAINT ON (n:tag)
ASSERT n.name IS UNIQUE")
(db/defquery ver-1-tag-uuid
"CREATE CONSTRAINT ON (n:tag)
ASSERT n.uuid IS UNIQUE")
(defn init-version-0 []
(neo4j/exec-query! ver-0-schema-uuid {})
(neo4j/exec-query! ver-0-attribute-uuid {})
@ -57,8 +65,13 @@
(neo4j/exec-query! ver-0-user-uuid {})
(neo4j/exec-query! ver-0-link-uuid {}))
(defn init-version-1 []
(neo4j/exec-query! ver-1-tag-name {})
(neo4j/exec-query! ver-1-tag-uuid {}))
(def migrations
[init-version-0])
[init-version-0
init-version-1])
(defn run-migrations! []
(neo4j/exec-query! init-config {:now (neo4j/now-str)})

@ -16,6 +16,7 @@
[wanijo.attribute.routes :as attr-routes]
[wanijo.instance.routes :as instance-routes]
[wanijo.visualisation.routes :as vis-routes]
[wanijo.tag.routes :as tag-routes]
[wanijo.framework
[auth :as auth]
[devmode :as devmode]
@ -35,7 +36,8 @@
user-routes/routes
attr-routes/routes
instance-routes/routes
vis-routes/routes))
vis-routes/routes
tag-routes/routes))
(route/not-found "Not Found"))
(def standalone-app

@ -168,8 +168,10 @@
(i)-[cb:created_by]->(:user)
OPTIONAL MATCH
(p:property)-[pc:of]->(i),
(p)-[pac:of]->(a:attribute)
DELETE pac, pc, cb, ic, p, i")
(p)-[pac:of]->(a:attribute),
(i)-[lt:link_to]->(),
(i)<-[lf:link_from]-()
DELETE pac, pc, cb, ic, p, lt, lf i")
(defn delete! [uuid]
(neo4j/exec-query! delete {:uuid uuid}))

@ -5,6 +5,7 @@
[ring.util.anti-forgery :refer [anti-forgery-field]]
[markdown.core :as md]
[formulare.core :as form]
[wanijo.tag.view :as view-tag]
[wanijo.instance.domain :as domain]
[wanijo.visualisation.viz :as viz]
[wanijo.framework
@ -91,9 +92,7 @@
"Explore from here"]]]
(when (seq (:tags instance))
[:section.tags
[:ul
(for [tag (:tags instance)]
[:li (:name tag)])]])
(view-tag/tag-list (:tags instance))])
(when (seq (:properties instance))
[:section.properties
[:h2 "Properties"]
@ -159,15 +158,20 @@
{:schema-uuid (:uuid schema)})}
(h (:name schema))]]
[:td (prettify-dt (:created_at link))]])]]])
[:section.link-instance
[:h2 "Link Instance with Instance of Schema..."]
[:ul
(for [schema schemas]
[:li
[:a {:href (path :instance-link-selection
{:uuid (:uuid instance)
:schema-uuid (:uuid schema)})}
(h (:name schema))]])]]]))
[:section.quick-edits
[:h2 "Quick edits"]
[:section.link-instance
[:h3 "Link Instance with Instance of Schema..."]
[:ul
(for [schema schemas]
[:li
[:a {:href (path :instance-link-selection
{:uuid (:uuid instance)
:schema-uuid (:uuid schema)})}
(h (:name schema))]])]]
[:section.tag-instance
[:h3 "Add or create Tags"]
(view-tag/new-tag-form instance)]]]))
(defn edit! [instance form form-data schemas req]
(view/layout!

@ -13,3 +13,5 @@
(spec/def ::attribute_uuid ::neo4j/uuid)
(spec/def ::now ::neo4j/date-str)
(spec/def ::uuid ::neo4j/uuid)
(spec/def ::user_uuid ::neo4j/uuid)
(spec/def ::no-whitespace #(not (re-matches #".*\s.*" %)))

@ -3,17 +3,57 @@
[wanijo.specs :as specs]
[wanijo.framework.neo4j :as neo4j]))
(spec/def ::name ::specs/req-name)
(spec/def ::name
(spec/and ::specs/name
::specs/no-whitespace))
(spec/def ::tag
(spec/keys :req-un [::specs/uuid
::specs/created_at
::name]))
(neo4j/defquery tags-by-instance
"MATCH (i:instance {uuid:{uuid}})-[:has]->(t:tag)
"MATCH (i:instance {uuid:{uuid}})-[:tagged_with]->(t:tag)
RETURN t
ORDER BY t.name")
(defn tags-by-instance! [instance-uuid]
{:post [(spec/assert (spec/coll-of ::tag) %)]}
(neo4j/exec-query! tags-by-instance
{:uuid instance-uuid}))
(map :t
(neo4j/exec-query! tags-by-instance
{:uuid instance-uuid})))
(neo4j/defquery merge-tag
"MATCH (i:instance {uuid:{instance_uuid}}),
(u:user {uuid:{user_uuid}})
MERGE (t:tag {name:{name}})-[:created_by]->(u)
ON CREATE SET t.uuid = {uuid},
t.created_at = {now}
MERGE (i)-[:tagged_with]->(t)")
(spec/def ::merge-tag-tuple
(spec/keys :req-un [::specs/instance_uuid
::name
::specs/uuid
::specs/now
::specs/user_uuid]))
(defn merge-tag-tuples [tags instance-uuid user-uuid]
{:pre [(spec/assert (spec/coll-of string?) tags)]
:post [(spec/assert (spec/coll-of (spec/tuple fn? ::merge-tag-tuple))
%)]}
(map (fn [tag-name]
[merge-tag
{:instance_uuid instance-uuid
:name tag-name
:uuid (neo4j/uuid)
:now (neo4j/now-str)
:user_uuid user-uuid}])
tags))
(comment
(merge-tag-tuples (list "a" "b")
(neo4j/uuid)
(neo4j/uuid))
(spec/explain (spec/coll-of (spec/tuple fn? ::merge-tag-tuple))
(merge-tag-tuples (list "a" "b")
(neo4j/uuid)
(neo4j/uuid))))
(defn merge-tags [tags instance-uuid user-uuid]
(apply neo4j/exec-queries!
(merge-tag-tuples tags instance-uuid user-uuid)))

@ -0,0 +1,24 @@
(ns wanijo.tag.forms
(:require [clojure.spec.alpha :as spec]
[clojure.string :refer [split trim]]))
(defn contains-whitespace? [s]
(re-matches #".*\s.*" s))
(defn tag-names-from-input [s]
(->> (split s #",")
(map trim)))
(defn any-tag-name-contains-whitespace [s]
(some contains-whitespace? (tag-names-from-input s)))
(spec/def ::new-names
(spec/and string?
(complement empty?)
(complement any-tag-name-contains-whitespace)))
(def new-tag
{:fields {:newnames {:label "Tag Name(s)"
:required true
:spec ::new-names
:from-req tag-names-from-input}}})

@ -0,0 +1,32 @@
(ns wanijo.tag.routes
(:require [compojure.core :refer [defroutes POST]]
[ring.util.response :as resp]
[formulare.core :as form]
[wanijo.framework.routing :refer [register! path]]
[wanijo.schema.domain :as domain-schema]
[wanijo.instance
[view :as view-instance]
[domain :as domain-instance]]
[wanijo.tag
[domain :as domain]
[forms :as forms]]))
(defn create-tag! [instance-uuid req]
(let [{new-names :newnames} (form/form-data forms/new-tag req)
user-uuid (-> req :session :uuid)]
(if (form/valid? forms/new-tag req)
(do
(domain/merge-tags new-names
instance-uuid
user-uuid)
(resp/redirect (path :instance-show
{:uuid instance-uuid})))
(view-instance/show!
(domain-instance/full-instance-by-uuid! instance-uuid)
(domain-schema/accessible-schemas! user-uuid)
req))))
(defroutes routes
(POST (register! :tag-create "/tag/:instance-uuid")
[instance-uuid :as req]
(create-tag! instance-uuid req)))

@ -0,0 +1,21 @@
(ns wanijo.tag.view
(:require [hiccup.form :as hform]
[hiccup.core :refer [h]]
[ring.util.anti-forgery :refer [anti-forgery-field]]
[formulare.core :as form]
[wanijo.tag.forms :as forms]
[wanijo.framework.routing :refer [path]]))
(defn tag-list [tags]
[:ul.tag-list
(for [tag tags]
[:li
[:code ":" (h (:name tag))]])])
(defn new-tag-form [{uuid :uuid}]
(list
(hform/form-to [:post (path :tag-create {:instance-uuid uuid})]
(form/render-widgets forms/new-tag {} {})
(hform/submit-button "Tag!"))
[:small (str "Comma separate each tag. "
"Tag names must not contain whitespace.")]))
Loading…
Cancel
Save