diff --git a/reagent-reitit-demo/resources/public/datalog-demo.org b/reagent-reitit-demo/resources/public/datalog-demo.org deleted file mode 100644 index bb1fc3c..0000000 --- a/reagent-reitit-demo/resources/public/datalog-demo.org +++ /dev/null @@ -1,86 +0,0 @@ -#+TITLE: Minimal clojurescript project demoing datalog queries - -* Getting started -To work with the code interactively jack into the project in your IDE of choice select "figwheel-main" as the build tool and dev as the build. - -Alternatively start a repl from the command line with - -#+BEGIN_SRC sh -clojure -m figwheel.main --build dev --repl -#+END_SRC - -* Intro to datalog -First import datascript which is a client side version of datalog, see datomic crux datalevin and datahike for other datalog database. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs -(ns core.demo - (:require [datascript.core :as d])) -#+END_SRC - - -See the extensive comments in the src code for a working example, also watch / read these for a good intro. - -https://www.youtube.com/watch?v=oo-7mN9WXTw -http://www.learndatalogtoday.org/ -https://udayv.com/clojurescript/clojure/2016/04/28/datascript101/ - -Blog of the dev who makes datascript -https://tonsky.me/blog/the-web-after-tomorrow/ - - -** Creating a DATABASE -Datalog databases can be schema less but a lot of the power comes from creating a schema specifying uniqueness and relations on the stored fields. - -You can create a new database using create-conn as below then empty hash map is simply a blank schema, -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs - (def demo-conn (d/create-conn {})) -#+END_SRC - - -Using the connection we can just start inserting data, using standard hash maps and lists structures, we always specify the attribute and the value when transacting. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs -(d/transact! demo-conn [{:user/name "Brooke" :user/img "me.jpg"} {:user/name "Kalvin" :user/img "you.jpg"}]) -#+END_SRC - -*** Using a Schema -In this example we are saying name is unique and rooms has a many to one relationship, when we transact data will be inserted even if its not in the schema but rules stop things like duplicates from happening. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs - (def schema {:user/name {:db/unique :db.unique/identity} - :user/rooms {:db/cardinality :db.cardinality/many - :db/valueType :db.type/ref}}) - (def demo-conn (d/create-conn schema)) -#+END_SRC - -Transacting this data would mean Brooke would be inserted once but the image will be updated to =you.jpg= -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc - (d/transact! demo-conn [{:user/name "Brooke" :user/img "you.jpg"}]) -#+END_SRC - -** Querying the databases -There are three types of queries in datalog entity lookup's pulling a tree of data or querying with =d/q=. - -*** Looking up an entity -=d/entity= is used to find the entity id, using any unique piece of data for example the user =Brooke= exists once so the entity db/id will be returned which can be used for further queries. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc -(d/entity @demo-conn [:user/name "Brooke"]) -#+END_SRC - -*** Pull a tree of data -Pull is used with entity id's once you know the entity you can specify what data you want to view ='[*]= being the most common looking up all keys, you can also specify the attributes your interested in looking up including there relations to make a more specific view. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc -(d/pull @demo-conn '[*] 1) -(d/pull @demo-conn '[:user/name :user/rooms] 1) -#+END_SRC - -*** Querying your dataset -Querying in datalog is all about binding variables to your entities attributes and values which you can use in you conditions or to return in the result set. - -In this example we return the user-id and user/name in the find clause which we looked up in the where clause by finding all attributes =:user/name= the binding the entity id and username to variables on each match to display in the find clause. - -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc - (d/q '[:find ?user-entity ?user-name :where - [?user-entity :user/name ?user-name]] @demo-conn) -#+END_SRC - - - -Write some more as needed better examples in the src code. diff --git a/reagent-reitit-demo/resources/public/documents/datalog-demo.org b/reagent-reitit-demo/resources/public/documents/datalog-demo.org index 9114ff9..3af0eae 100644 --- a/reagent-reitit-demo/resources/public/documents/datalog-demo.org +++ b/reagent-reitit-demo/resources/public/documents/datalog-demo.org @@ -1,59 +1,73 @@ -#+TITLE: Minimal clojurescript project demoing datalog queries - -* Getting started -To work with the code interactively jack into the project in your IDE of choice select "figwheel-main" as the build tool and dev as the build. - -Alternatively start a repl from the command line with. - -#+BEGIN_SRC sh -clojure -m figwheel.main --build dev --repl -#+END_SRC +#+TITLE: Datalog DSL Guide * Intro to datalog -First import datascript which is a client side version of datalog, see datomic crux datalevin and datahike for other datalog database. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs -#_(ns core.demo - (:require [datascript.core :as d])) -#+END_SRC +This is a short guide on writing common datalog queries to allow you to query databases like datascript, datalevin, datahike datomic & xtdb. +These examples are all aimed at datascript which is a browser client side database allowing interactivity int the examples. -See the extensive comments in the src code for a working example, also watch / read these for a good intro. - -https://www.youtube.com/watch?v=oo-7mN9WXTw +You can find some further guides and information on the subject at these locations. +https://max-datom.com/ http://www.learndatalogtoday.org/ -https://udayv.com/clojurescript/clojure/2016/04/28/datascript101/ +https://www.youtube.com/watch?v=oo-7mN9WXTw Blog of the dev who makes datascript https://tonsky.me/blog/the-web-after-tomorrow/ +** Entities Attributes & values + +Before getting started with data log it vital to understand data is stored as a list of values, the entity id which is a way to look up and group related attributes, attributes are the name of the thing you want to store so =:user/name= for example and the value to store under this name, the entity id will be generated when inserting data. + +Sometimes the database may store other details like transaction time and revoked data dependant on the characteristics of the underlying database. + +This is an example of how a EAV triplet would be represented. +#+BEGIN EXAMPLE +[1 | :user/name | "Daisy"] +#+END_EXAMPLE + +This is an example of how a EAVT quadruplet would be represented, T in this instance is the Transaction ID if multiple values are inserted at once they would have the same transaction ID. +#+BEGIN EXAMPLE +[1 | :user/name | "Daisy" | 100] +#+END_EXAMPLE ** Creating a DATABASE Datalog databases can be schema less but a lot of the power comes from creating a schema specifying uniqueness and relations on the stored fields. You can create a new database using create-conn as below then empty hash map is simply a blank schema, -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljs (def demo-conn (d/create-conn {})) + +@demo-conn #+END_SRC Using the connection we can just start inserting data, using standard hash maps and lists structures, we always specify the attribute and the value when transacting. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljs (def demo-conn (d/create-conn {})) -(d/transact! demo-conn [{:user/name "Brooke" :user/img "me.jpg"} {:user/name "Kalvin" :user/img "you.jpg"}]) + +(d/transact! + demo-conn + [{:user/name "Brooke" :user/img "me.jpg"} + {:user/name "Kalvin" :user/img "you.jpg"}]) + +@demo-conn #+END_SRC -*** Using a Schema -In this example we are saying name is unique and rooms has a many to one relationship, when we transact data will be inserted even if its not in the schema but rules stop things like duplicates from happening. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljs +*** Creating a Schema +Not all datalog databases let you create a schema, but datascript does this allows us to add constraints and relations between the stored data. + +In this example we are saying =:user/name= is unique and =:user/rooms= has a many to one relationship, when we later transact data it will use the constraints to stop things like duplicates from being created. +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljs (def schema {:user/name {:db/unique :db.unique/identity} :user/rooms {:db/cardinality :db.cardinality/many :db/valueType :db.type/ref}}) (def demo-conn (d/create-conn schema)) #+END_SRC + +** Transacting data Transacting this data would mean Brooke would be inserted once but the image will be updated to =you.jpg= -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc - (d/transact! demo-conn [{:user/name "Brooke" :user/img "you.jpg"}]) +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljc + (str (d/transact! demo-conn [{:user/name "Brooke" :user/img "you.jpg"}])) #+END_SRC ** Querying the databases @@ -61,13 +75,13 @@ There are three types of queries in datalog entity lookup's pulling a tree of da *** Looking up an entity =d/entity= is used to find the entity id, using any unique piece of data for example the user =Brooke= exists once so the entity db/id will be returned which can be used for further queries. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljc (d/entity @demo-conn [:user/name "Brooke"]) #+END_SRC *** Pull a tree of data Pull is used with entity id's once you know the entity you can specify what data you want to view ='[*]= being the most common looking up all keys, you can also specify the attributes your interested in looking up including there relations to make a more specific view. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljc (d/pull @demo-conn '[*] 1) (d/pull @demo-conn '[:user/name :user/rooms] 1) #+END_SRC @@ -77,7 +91,7 @@ Querying in datalog is all about binding variables to your entities attributes a In this example we return the user-id and user/name in the find clause which we looked up in the where clause by finding all attributes =:user/name= the binding the entity id and username to variables on each match to display in the find clause. -#+BEGIN_SRC clojurescript :tangle ./src/test.cljc +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/test.cljc (d/q '[:find ?user-entity ?user-name :where [?user-entity :user/name ?user-name]] @demo-conn) #+END_SRC diff --git a/reagent-reitit-demo/resources/public/documents/honey-sql-demo.org b/reagent-reitit-demo/resources/public/documents/honey-sql-demo.org index 48279e8..d46eba8 100644 --- a/reagent-reitit-demo/resources/public/documents/honey-sql-demo.org +++ b/reagent-reitit-demo/resources/public/documents/honey-sql-demo.org @@ -11,7 +11,7 @@ One nice way to write HoneySQL queries is to use the =->= threading macro. The = Here is an example of how to use the =->= macro to build a simple SQL query: -#+BEGIN_SRC clojure :eval string +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users) (sql/format {:pretty true}) @@ -20,7 +20,7 @@ Here is an example of how to use the =->= macro to build a simple SQL query: The equivalent code with out a threading macros looks like this. -#+BEGIN_SRC clojure :eval string +#+BEGIN_SRC clojure :results verbatim (first (sql/format (sqlh/from @@ -34,7 +34,7 @@ Using HoneySQL you can incrementally build up our queries, they do not need to b The example below will produce a select for a couple of fields passing the resulting data into format to create an SQL string we can send to the database, we call first because the result is a vector containing and SQL and any values need none in this instance. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/select :first_name :last_name :email) (sql/format {:pretty true}) (first)) @@ -42,7 +42,7 @@ The example below will produce a select for a couple of fields passing the resul We can extend the example above to include the =FROM= part of the SQL statement to give us something more complete. How ever it's much nicer for readability to use the threading macro -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users) (sql/format {:pretty true}) @@ -50,7 +50,7 @@ How ever it's much nicer for readability to use the threading macro #+END_SRC The functions understand SQL statement ordering so the order you call the functions does not matter. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/from :users) (sqlh/select :first_name :last_name :email) (sql/format {:pretty true}) @@ -59,7 +59,7 @@ The functions understand SQL statement ordering so the order you call the functi We can extend the query to add in limiting & ordering. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users) (sqlh/order-by :first_name) @@ -68,11 +68,18 @@ We can extend the query to add in limiting & ordering. (first)) #+END_SRC +Now is a good time to explain aliasing, basically the values to select become wrapped in vectors with the second value being the alias so [:first_name :fn] to alias the column =first_name= to =fn= we can aliases columns tables sub select's same as standard SQL. +#+BEGIN_SRC clojure :results verbatim + (-> base-sql + (sqlh/select [:first_name :fn] [:last_name :ln] [:email :e]) + (sql/format {:pretty true}) + (first)) +#+END_SRC ** Basic SQL filtering Filtering is just as simple and support the usual operators like = < > we pass them in as keywords so =:== =:<>= =:<= =:.= would be the equivalents. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users) (sqlh/where [:= :first_name "spot"] @@ -81,10 +88,10 @@ Filtering is just as simple and support the usual operators like = < > we pass t (first)) #+END_SRC -Often we want to conditionally filter, this is nice and simple with the knowledge that where will short circuit given a nil value this means we can use =when= and =if= functions inside our sql generations. +Often we want to conditionally filter, this is nice and simple with the knowledge that the =where= function will short circuit given a nil value this means we can use =when= and =if= functions inside our sql generations. -So below no where will not be appended because true is not false so the when return nil which removes the where in the final query. -#+BEGIN_SRC clojure +So below the SQL where will not be appended because true is not false so the when returns nil removing the where in the generated query. +#+BEGIN_SRC clojure :results verbatim (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users) (sqlh/where (when (true? false) [:= :first_name "spot"])) @@ -92,15 +99,32 @@ So below no where will not be appended because true is not false so the when ret (first)) #+END_SRC +We can use similar technique to switch between matching a single and multiple values. +#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/core.cljs +(defn conditional-where [id] + (-> (sqlh/select :*) + (sqlh/from [:company]) + (sqlh/where (if (sequential? id) [:in :id id] [:= :id id])))) + +(clojure.string/join + "\n" + [(-> (conditional-where [1 2 3]) + (sql/format {:pretty true}) + (first)) + + (-> (conditional-where 1) + (sql/format {:pretty true}) + (first))]) +#+END_SRC ** Composing SQL queries and performing joins For all the standard fn's like select and where there are equivalent merge fn's the merge versions append in place of replacing. A good strategy is to build basic queries extending them when needed, so create a base select then create a function which build on the query adding in the conditions, this allow you to run the base queries in the REPL or the extended version making it easier to find query related issues by testing parts in isolation. -we can use =if= =when= =when-let= =cond->= to help build these, in the example below you can see that we switch if we search for first last or both name based on the provided map. +we can use =if= =when= =when-let= =cond->= among other functions to help build these, in the example below you can see the where part of the query is modified based on what values are provided in the map. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (def base-sql (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users))) @@ -130,17 +154,10 @@ we can use =if= =when= =when-let= =cond->= to help build these, in the example b (first))]) #+END_SRC -Now is a good time to explain aliasing, basically keywords become vectors so :first_name would become [:first_name :fn] to alias the column first_name to fn we can aliases columns tables sub select the lot like in standard sql. -#+BEGIN_SRC clojure - (-> base-sql - (sqlh/select [:first_name :fn] [:last_name :ln] [:email :e]) - (sql/format {:pretty true}) - (first)) -#+END_SRC We can also do joins to other table's -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (def base-sql (-> (sqlh/select :first_name :last_name :email) (sqlh/from :users))) @@ -154,7 +171,7 @@ We can also do joins to other table's or group by's and sql functions like =count= =max= =min= these can be used by appending :%name to the selected column. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (def base-group-sql (-> base-sql (sqlh/select :first_name [:%count.first_name :count_name]) @@ -165,7 +182,7 @@ or group by's and sql functions like =count= =max= =min= these can be used by ap ** Larger query This is how I like to compose queries, and shows a larger query being generated. -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (def big-base-sql (-> (sqlh/select :users.* :address.* :products.*) (sqlh/from :users) @@ -207,7 +224,7 @@ Don't forget its just data, if you don't use sql/format it just returns a data s When all else fails you have a few options, check to see if there is a honeysql db specific library or break out =sql/raw= or extending honey sql. Say we want to get people added in the last 14 days this is a bit more tricky -#+BEGIN_SRC clojure +#+BEGIN_SRC clojure :results verbatim (def base-last-14-days-sql (-> base-sql (sqlh/where [:> @@ -221,43 +238,6 @@ Say we want to get people added in the last 14 days this is a bit more tricky * Basic statements -#+BEGIN_SRC clojurescript :tangle ./src/core.cljs -#_(ns core.demo - (:require - [honey.sql :as sql] - [honey.sql.helpers :as sqlh])) -#+END_SRC - -#+BEGIN_SRC clojurescript :tangle ./src/core.cljs -(clojure.core/into [:a] [1 2 3 4]) -#+END_SRC - -** Simple table select, with filtering and sorting applied -#+BEGIN_SRC clojurescript -(-> (sqlh/select :*) - (sqlh/from :company) - (sqlh/where [:= :id 1]) - str) -#+END_SRC - -#+BEGIN_SRC clojurescript :tangle ./src/core.cljs -(str (sqlh/select :*)) -#+END_SRC - - -** Dynamic where clauses - -*** where value exists -=sqlh/where= will only be applied to the query if it has a value so nil on its own will not applied -#+BEGIN_SRC clojurescript :tangle ./src/core.cljs -(defn conditional-where [id] - (-> (sqlh/select :*) - (sqlh/from [:company]) - (sqlh/where (when id [:= :id id])))) - -(first (sql/format (conditional-where 1) {:pretty true})) -#+END_SRC - *** Switch between singular or multiple values in condition #+BEGIN_SRC clojurescript :tangle ./src/core.cljs diff --git a/reagent-reitit-demo/resources/public/documents/test.org b/reagent-reitit-demo/resources/public/documents/test.org deleted file mode 100644 index a05442a..0000000 --- a/reagent-reitit-demo/resources/public/documents/test.org +++ /dev/null @@ -1,3 +0,0 @@ -#+title: title - -lorem diff --git a/reagent-reitit-demo/src/clojure_demo/core.cljs b/reagent-reitit-demo/src/clojure_demo/core.cljs index c18748a..97a76c5 100644 --- a/reagent-reitit-demo/src/clojure_demo/core.cljs +++ b/reagent-reitit-demo/src/clojure_demo/core.cljs @@ -7,12 +7,8 @@ ["@codemirror/theme-one-dark" :refer [oneDark]] ["@nextjournal/lang-clojure" :refer [clojure]] ["@codemirror/legacy-modes/mode/yaml" :refer [yaml]] - [reagent.core :as reagent] [ajax.core :refer [GET raw-response-format]] - ;[demo.org :refer [parse->to-hiccup parse-flat]] - ;[cljs.js :as cljs] - ;[cljs.repl :as repl] [clojure.set :refer [rename-keys]] [cl-eorg.parser :as o :refer [parse parse-flat]] [cl-eorg.html :refer [org->replacements]] @@ -20,16 +16,12 @@ [reitit.frontend :as rf] [reitit.frontend.easy :as rfe] [reitit.coercion.spec :as rss] - ;; interactive + ;; interactive [sci.core :as sci] [sci.configs.reagent.reagent :as sci-reagent] [sci.configs.tonsky.datascript :as sci-datascript] - ;;[klipse.run.plugin.plugin] - ;;[klipse.plugin :as klipse-plugin] - ;[hiccup.core :as h] [honey.sql :as sql] [honey.sql.helpers :as sqlh] - ;[datascript.core :as d] [spec-tools.data-spec :as ds])) @@ -38,10 +30,8 @@ "yaml" {:mode "yaml"}}) (def yaml-mode (LanguageSupport. (.define StreamLanguage yaml) )) - ;const yaml = new LanguageSupport(StreamLanguage.define(yamlMode.yaml)); ;; https://github.com/babashka/sci.configs -;(def hc-ns (sci/create-ns 'hiccup.core nil)) (def rf-ns (sci/create-ns 'reitit.frontend nil)) (def rfe-ns (sci/create-ns 'reitit.frontend.easy nil)) (def rss-ns (sci/create-ns 'reitit.coercion.spec nil)) @@ -52,7 +42,7 @@ {:namespaces {'reagent sci-reagent/reagent-namespace ;'h {'html (sci/copy-var h/html hc-ns)} - 'd sci-datascript/core-ns + 'd sci-datascript/core-namespace 'sql {'format (sci/copy-var sql/format sql-ns) #_#_'raw (sci/copy-var sql/raw sql-ns)} 'sqlh {'select (sci/copy-var sqlh/select sqlh-ns) @@ -85,7 +75,7 @@ transactions)) (defn code-editor - [{:keys [class eval-mode]} content] + [{:keys [class results]} content] (let [language class editor (atom nil) evaled-result (reagent/atom nil) @@ -127,21 +117,15 @@ [:div.ba.ma0.f5.b--black-05.pa2.overflow-auto.editor {:ref #(reset! editor %)}] [:pre.ba.ma0.f6.code.b--black-05.pa2.pl4.overflow-auto {:style {:white-space "pre-line"}} - (case eval-mode - "string" (str @evaled-result) - "hiccup" @evaled-result + ;; See org mode :results key + (case results + "verbatim" (str @evaled-result) + "value" (str @evaled-result) + "output" @evaled-result + "silent" "" @evaled-result) ]])}))) - -#_(defn code-snippet [settings content] - (let [snippet (reagent/atom nil) - ;;evaled (sci/eval-string* sci-ctx content ) - ;;evaled (sci/eval-form sci-ctx content ) - ] - [:div (str settings) - [code-editor (:class settings) (str content)]])) - (defn link-handler [v _] (prn v) (prn (conj [:a] v #_(second v))) @@ -171,22 +155,20 @@ {:homepage {:intro "Clojure tutorials examples and exploration"} :lorem "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." :demos - {:sci-demo - {:file "documents/sci-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :dsl-demo - {:file "documents/dsl-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :datalog-demo - {:file "documents/datalog-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :honey-sql-demo - {:file "documents/honey-sql-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :reagent-demo - {:file "documents/reagent-reitit.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :clojure-basics - {:file "documents/clojure-basics.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :ci-demo - {:file "documents/ci-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} - :containers - {:file "documents/containers.org" :git-link "https://github.com/atomjuice/containers"}}}) + {:dsl-demo + {:file "documents/dsl-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} + :datalog-demo + {:file "documents/datalog-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} + :honey-sql-demo + {:file "documents/honey-sql-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} + :reagent-demo + {:file "documents/reagent-reitit.org" :git-link "https://github.com/atomjuice/dsl-demo"} + :clojure-basics + {:file "documents/clojure-basics.org" :git-link "https://github.com/atomjuice/dsl-demo"} + :ci-demo + {:file "documents/ci-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} + :containers + {:file "documents/containers.org" :git-link "https://github.com/atomjuice/containers"}}}) ;; Store site state (defonce site-state (reagent/atom {})) @@ -259,10 +241,7 @@ {:title "Clojure Demos" :body (-> site-data :homepage :intro) :articles - [{:title "Sci Example" - :link (rfe/href ::demo {:page "sci-demo"}) - :img-src "https://clojure.org/images/clojure-logo-120b.png"} - {:title "Clojure Basics" + [{:title "Clojure Basics" :description "Getting started with clojure syntax datatype's sequences conditions" :link (rfe/href ::demo {:page "clojure-basics"}) :img-src "https://clojure.org/images/clojure-logo-120b.png"} @@ -270,9 +249,6 @@ :description "Clojure in a CI pipeline" :link (rfe/href ::demo {:page "ci-demo"}) :img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"} - {:title "Datalog Demo" - :link (rfe/href ::demo {:page "datalog-demo"}) - :img-src "https://raw.githubusercontent.com/tonsky/datascript/master/extras/logo.svg"} {:title "Reagent Demo" :description "React application using reagent" :link (rfe/href ::demo {:page "reagent-demo"}) @@ -284,13 +260,15 @@ {:title "Clojure Demos" :body (-> site-data :homepage :intro) :articles - [ - {:title "Hiccup HTML Demo" + [{:title "Hiccup HTML Demo" :link (rfe/href ::demo {:page "dsl-demo"}) :img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"} {:title "Honey SQL Demo" :link (rfe/href ::demo {:page "honey-sql-demo"}) - :img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"}]}]]) + :img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"} + {:title "Datalog Demo" + :link (rfe/href ::demo {:page "datalog-demo"}) + :img-src "https://raw.githubusercontent.com/tonsky/datascript/master/extras/logo.svg"}]}]]) ;; form two component render demo (defn demo-page [route]