...
 
Commits (2)
......@@ -398,6 +398,11 @@
"randomfill": "^1.0.3"
}
},
"date-fns": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.11.0.tgz",
"integrity": "sha512-8P1cDi8ebZyDxUyUprBXwidoEtiQAawYPGvpfb+Dg0G6JrQ+VozwOmm91xYC0vAv1+0VmLehEPb+isg4BGUFfA=="
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
......
......@@ -8,6 +8,7 @@
"dependencies": {
"@rdfjs/data-model": "^1.1.2",
"create-react-class": "^15.6.3",
"date-fns": "^2.11.0",
"leaflet": "^1.6.0",
"n3": "^1.3.5",
"rdf-parse": "^1.2.1",
......
......@@ -4,7 +4,6 @@
(:require [rdf.core :as rdf]
[rdf.graph.map :as rdf-graph]
[rdf.logic :as rdf-logic]
[rdf.description :as rdf-description]
[rdf.ns :as ns]
[cljs.core.logic :as l]
[geopub.ns :refer [as rdfs]]
......@@ -29,11 +28,11 @@
(rdf-logic/graph-typeo graph id activity-type)))]
(->> activity-ids
(map #(rdf-description/description % graph))
(map #(rdf/description % graph))
(sort-by
;; get the as:published property and cast to js/Date
(fn [description]
(->> (rdf-description/description-get description (as "published"))
(->> (rdf/description-get description (as "published"))
(first)
(rdf/literal-value)
(new js/Date)))
......@@ -58,10 +57,10 @@
(run* [label]
(l/conda
;; use preferredUsername
((rdf-description/description-tripleo object (as "preferredUsername") label))
((rdf-logic/description-tripleo object (as "preferredUsername") label))
;; use name
((rdf-description/description-tripleo object (as "name") label))
((rdf-logic/description-tripleo object (as "name") label))
;; Fall back to using the subject IRI as label
((l/== (rdf-description/description-subject object) label))))))
((l/== (rdf/description-subject object) label))))))
......@@ -2,7 +2,6 @@
"Helpers to deal with ontologies (RDFS and OWL)"
(:require [rdf.core :as rdf]
[rdf.logic :as rdf-logic]
[rdf.description :as rdf-description]
[cljs.core.logic :as l]
[geopub.data.rdf])
(:require-macros [cljs.core.logic :refer [run*]]
......@@ -17,10 +16,10 @@
(run* [label]
(l/conda
;; use rdfs label
((rdf-description/description-tripleo object (rdfs "label") label))
((rdf-logic/description-tripleo object (rdfs "label") label))
;; Fall back to using the subject IRI as label
((l/== (rdf-description/description-subject object) label))))))
((l/== (rdf/description-subject object) label))))))
(defmethod geopub.data.rdf/description-label-term
(rdfs "Class")
......
(ns geopub.data.rdf
"Helpers for displaying RDF data"
(:require [rdf.core :as rdf]
[rdf.description :refer [description-get
description-subject]]
[rdf.ns :as rdf-ns]
[rdf.n3 :as n3]
[rdf.parse :as rdf-parse]
......@@ -153,7 +151,7 @@
"Helper to get type of subject being described. This defines what multimethod is used to render the description."
[object & [opts]]
;; TODO the described object can have multiple types. Currently we use the first type. Allow a preference to be given.
(first (description-get object (rdf-ns/rdf :type))))
(first (rdf/description-get object (rdf-ns/rdf :type))))
(defmulti description-label-term
"Returns an appropriate short label for the description."
......@@ -164,11 +162,11 @@
(defmethod description-label-term
:default
[object & [opts]]
(description-subject object))
(rdf/description-subject object))
(defn description-label-component [object & [opts]]
(let
[subject (description-subject object)
[subject (rdf/description-subject object)
label-term (description-label-term object opts)]
(if
......@@ -179,7 +177,7 @@
(rdf/iri? subject))
;; then make the component a clickable link
[:a {:href (iri-href (description-subject object))}
[:a {:href (iri-href (rdf/description-subject object))}
[rdf-term-component (description-label-term object opts)]]
;; else just display as rdf-term
......
......@@ -2,7 +2,6 @@
"Helpers to deal with the schema.org ontology."
(:require [rdf.core :as rdf]
[rdf.logic :as rdf-logic]
[rdf.description :as rdf-description]
[cljs.core.logic :as l]
[geopub.data.rdf]
[geopub.ns :refer [schema]])
......@@ -14,10 +13,10 @@
(run* [label]
(l/conda
;; use rdfs label
((rdf-description/description-tripleo object (schema "name") label))
((rdf-logic/description-tripleo object (schema "name") label))
;; Fall back to using the subject IRI as label
((l/== (rdf-description/description-subject object) label))))))
((l/== (rdf/description-subject object) label))))))
(defmethod geopub.data.rdf/description-label-term
(schema "Event")
......
......@@ -23,43 +23,57 @@
description-label-component]]
[geopub.data.activity :as activity]
[rdf.core :as rdf]
[rdf.description :as rd]
[rdf.ns :as ns]
[rdf.graph.map]))
[rdf.graph.map]
["date-fns" :as date-fns]))
(defn published-component [activity]
(let [published (new js/Date (-> activity
(rdf/description-get (as "published"))
(first)
(rdf/literal-value)))
]
[:span (.formatDistance date-fns published (new js/Date)
(clj->js {:addSuffix true}))]))
(defn activity-component [activity]
(let
[object (rd/description-move
[object (rdf/description-move
activity
(first (rd/description-get activity (as "object"))))
actor (rd/description-move
(first (rdf/description-get activity (as "object"))))
actor (rdf/description-move
activity
(first (rd/description-get activity (as "actor"))))
(first (rdf/description-get activity (as "actor"))))
activity-type (rd/description-move
activity-type (rdf/description-move
activity
(first (rd/description-get activity (ns/rdf :type))))
(first (rdf/description-get activity (ns/rdf :type))))
]
[:div.activity
;; render object
;; (for
;; [object
;; (map (partial rd/description-move activity)
;; (rd/description-get activity (as :object)))]
;; (map (partial rdf/description-move activity)
;; (rdf/description-get activity (as :object)))]
;; ^{:key (prn-str (rd/description-subject object))}
;; ^{:key (prn-str (rdf/description-subject object))}
;; [description-component object])
[:span.actor [description-label-component actor]]
[:span.activity-type [description-label-component activity-type]]
[:span.object [description-label-component object]]
[published-component activity]
;; [:span [description-label-component activity]]
;; [:div.meta
;; [iri-component (rd/description-get activity (as :actor))]
;; [iri-component (rdf/description-get activity (as :actor))]
;; [:br]
;; [iri-component (rd/description-get activity (ns/rdf :type))]]
;; [iri-component (rdf/description-get activity (ns/rdf :type))]]
]))
(defn sidebar []
[:div.sidebar
[:nav
......
(ns geopub.ui.browse
(:require [rdf.core :as rdf]
[rdf.description :as rdf-description]
[reagent.core :as r]
[goog.string]
[geopub.state]
......@@ -55,8 +54,6 @@
(goog.string.urlDecode)
(rdf/iri)))
(defn toolbar [state]
[:div.toolbar
......@@ -68,12 +65,13 @@
{:on-click
#(geopub.state/add-rdf-graph!
state
(geopub.data.rdf/get-rdf (rdf/iri-value (get-iri state))))}
(geopub.data.rdf/get-rdf (rdf/iri-value (get-iri state))
{:with-credentials? false}))}
"Fetch more data"]])
(defn description-view [state]
(let [iri (get-iri state)
description (r/track #(rdf-description/description iri (:graph @state)))]
description (r/track #(rdf/description iri (:graph @state)))]
[:div.ui-page
[sidebar]
......@@ -93,7 +91,7 @@
[graph type]
;; TODO implement RDFs subClass
(map
#(rdf-description/description % graph)
#(rdf/description % graph)
(run* [subject] (rdf-logic/graph-typeo graph subject type))))
(defn browse-view [state]
......@@ -109,6 +107,6 @@
^{:key (hash desc)}
[:tr
[:td [rdf-term-component
(rdf-description/description-subject desc)]]]
(rdf/description-subject desc)]]]
)]]
]]]))
......@@ -7,7 +7,6 @@
[geopub.ns :refer [geo]]
[rdf.core :as rdf]
[rdf.logic :as rl]
[rdf.description :as rd]
[cljs.core.logic :as l]))
......@@ -31,7 +30,7 @@
(defn get-geo-object [state]
"Returns a list of activities that have a latitude and longitude"
;; TODO only store the relevant subgraph in the description
(map #(rd/description % (:graph @state))
(map #(rdf/description % (:graph @state))
(run* [s]
(fresh [x y]
(rl/graph-tripleo (:graph @state) (rdf/triple s (geo "long") x))
......@@ -40,12 +39,12 @@
(defn get-location [object]
(let
[lat (-> object
(rd/description-get (geo "lat"))
(rdf/description-get (geo "lat"))
(first)
(rdf/literal-value))
long (-> object
(rd/description-get (geo "long"))
(rdf/description-get (geo "long"))
(first)
(rdf/literal-value))]
[lat long]))
......@@ -68,7 +67,7 @@
:attribution copy-osm}]
(for [geo-object (get-geo-object state)]
^{:key (prn-str (rd/description-subject geo-object))}
^{:key (prn-str (rdf/description-subject geo-object))}
[geo-object-component geo-object])
]])
(ns rdf.core
"RDF in Clojure")
"RDF in Clojure"
(:require [clojure.core.logic :as l]))
;; IRI
......@@ -12,7 +13,12 @@
(defrecord IRI [value]
IIRI
(iri-value [x] (:value x)))
(iri-value [x] (:value x))
IComparable
(-compare [x y] (-compare
(:value x)
(:value y))))
(defn iri? [x] (instance? IRI x))
......@@ -42,7 +48,12 @@
ILiteral
(literal-value [x] (:value x))
(literal-language [x] (:language x))
(literal-datatype [x] (:datatype x)))
(literal-datatype [x] (:datatype x))
IComparable
(-compare [x y]
;; TODO sort by datatype, then by language and then by value
(-compare (:value x) (:value y))))
(defn literal? [x] (instance? Literal x))
......@@ -179,3 +190,42 @@
(graph-merge [x y] "Merge two graphs.")
(graph-delete [x triple] "Delete a triple from the graph."))
;; Description
;; A description is a pointer to a specific subject in a graph. This is very useful when talking about a certain subject but still allowing full graph accessability. In particular it allows easier relative queries.
(defrecord Description [subject graph]
ITripleSeq
(triple-seq [description]
(graph-match
(:graph description)
(triple (:subject description) (l/lvar) (l/lvar)))))
(defn description
"Make a new description"
[subject graph]
(->Description subject graph))
(defn description-subject
"Get the subject of a description"
[description]
(:subject description))
(defn description-graph
"Get the underlying graph of a description"
[description]
(:graph description))
(defn description-move
"Make a new description pointing to a new-subject with the same graph"
[description new-subject]
(->Description new-subject (description-graph description)))
(defn description-get
"Get objects for given predicate. This always returns a sequence of objects."
[description predicate]
(map triple-object
(graph-match
(:graph description)
(triple (:subject description) predicate (l/lvar)))))
(ns rdf.description
"A graph with a starting point.
Having a starting point allows lookup of like for a map.
"
(:require-macros [clojure.core.logic :refer [run*]])
(:require [rdf.core :as rdf]
[rdf.logic :as rl]
[clojure.core.logic :as l]))
(defrecord Description [subject graph]
rdf/ITripleSeq
(triple-seq [description]
(run* [t]
(rl/graph-collecto (:graph description) 1 (:subject description) t))))
(defn description [subject graph]
(->Description subject graph))
(defn description-subject [description]
(:subject description))
(defn description-graph [description]
(:graph description))
(defn description-move [description new-subject]
(->Description new-subject (:graph description)))
(defn description-tripleo
[desc p o]
(rl/graph-tripleo (description-graph desc)
(rdf/triple (description-subject desc) p o)))
(defn description-get [description key]
(run* [o]
(description-tripleo description key o)))
(defn description-predications [description]
(run* [p o]
(description-tripleo description p o)))
......@@ -185,3 +185,8 @@
(graph-collecto graph (dec n) o t))])
l/fail))
(defn description-tripleo
[desc p o]
(graph-tripleo (rdf/description-graph desc)
(rdf/triple (rdf/description-subject desc) p o)))