Updated reagent info.
continuous-integration/drone/push Build encountered an error
Details
continuous-integration/drone/push Build encountered an error
Details
This commit is contained in:
parent
f8a3f544a4
commit
0dbb44be12
4
deps.edn
4
deps.edn
|
@ -6,8 +6,8 @@
|
|||
cljs-ajax/cljs-ajax {:mvn/version "0.8.1"}
|
||||
|
||||
;; react
|
||||
reagent/reagent {:mvn/version "1.1.1"}
|
||||
reagent-utils/reagent-utils {:mvn/version "0.3.3"}
|
||||
reagent/reagent {:mvn/version "1.2.0"}
|
||||
reagent-utils/reagent-utils {:mvn/version "0.3.6"}
|
||||
olymk2/cl-org {:git/url "https://gitlab.com/olymk2/cl-org.git"
|
||||
:sha "528e8125afcac5d7664aac80f7fbba12dd0f5d98"}
|
||||
;;routing
|
||||
|
|
|
@ -7,11 +7,89 @@ Reagent is a popular react wrapper in the clojurescript it greatly simplify buil
|
|||
The basis of any react app is components these are small snippets of html which can be composed to build up a page,
|
||||
reagent provides 3 main ways to create components dependant on the complexity needed most of the time you will create form 1 and form 2 components.
|
||||
|
||||
#+BEGIN_SRC html :results silent :exports none :tangle resources/public/index.html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Clojure demos</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/tachyons@4.12.0/css/tachyons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
App loading here
|
||||
</div>
|
||||
<script src="/cljs-out/main_bundle.js" type="application/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
#+END_SRC
|
||||
|
||||
|
||||
#+BEGIN_SRC edn :results silent :tangle deps.edn
|
||||
{:paths ["src" "resources"]
|
||||
:deps
|
||||
{org.clojure/clojure {:mvn/version "1.10.0"}
|
||||
org.clojure/clojurescript {:mvn/version "1.11.60"}
|
||||
reagent/reagent {:mvn/version "1.2.0"}
|
||||
thheller/shadow-cljs {:mvn/version "2.24.0"}}
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
#+BEGIN_SRC edn :results silent :tangle shadow-cljs.edn
|
||||
{:deps {:aliases [:dev]}
|
||||
:dev-http {8080 ["resources/public/" "classpath:public"]}
|
||||
:source ["src" "../../components"]
|
||||
:builds {:app {:output-dir "resources/public/cljs-out/"
|
||||
:asset-path "/cljs-out"
|
||||
:target :browser
|
||||
:compiler-options {:infer-externs :auto
|
||||
:externs ["datascript/externs.js"]
|
||||
:output-feature-set :es6}
|
||||
:modules {:main_bundle {:init-fn clojure-demo.core/startup!}}
|
||||
:devtools {:after-load app.main/reload!}}}}
|
||||
#+END_SRC
|
||||
|
||||
|
||||
#+BEGIN_SRC json :results silent :tangle package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"shadow-cljs": "^2.23.3",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
}
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
#+BEGIN_SRC text :results silent :tangle readme.org
|
||||
#+TITLE: Getting started
|
||||
|
||||
* Install the npm requirements.
|
||||
|
||||
npx install
|
||||
|
||||
* Launch shadow-cljs watch for source code changes
|
||||
npx shadow-cljs watch app
|
||||
#+END_SRC
|
||||
|
||||
|
||||
#+BEGIN_SRC json :tangle src/clojure_demo/core.cljs
|
||||
(ns clojure-demo.core
|
||||
(:require
|
||||
["react-dom/client" :refer [createRoot]]
|
||||
[reagent.core :as reagent]))
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Form 1 components
|
||||
Form one components are the most basic simply rendering some html with values that are not going to change.
|
||||
|
||||
In the example below the function just returns some hiccup with the parameters inserted, you need to specify =:key= when dynamically repeating the elements and these should be reproducible unique id's where possible not randomly generated or indexed numbers if the data is unordered.
|
||||
#+BEGIN_SRC clojure :tangle "src/core.cljs"
|
||||
|
||||
#+BEGIN_SRC clojure :tangle src/clojure_demo/core.cljs
|
||||
(defn navbar-link [{:keys [href title text] :or {text nil title nil}}]
|
||||
[:a.link.dim.dib.mr3 {:key href :href href :title title} text])
|
||||
|
||||
|
@ -19,7 +97,7 @@ In the example below the function just returns some hiccup with the parameters i
|
|||
#+END_SRC
|
||||
|
||||
|
||||
#+BEGIN_SRC clojure
|
||||
#+BEGIN_SRC clojurescript :results output :tangle src/clojure_demo/core.cljs
|
||||
(defn product-card
|
||||
[{:keys [title amount description link]}]
|
||||
[:article.br2.ba.dark-gray.b--black-10.ma2.w-100.w-50-m.w-25-l.mw5
|
||||
|
@ -46,31 +124,50 @@ In the example below the function just returns some hiccup with the parameters i
|
|||
** Form 2 components
|
||||
Form two components are used so we can track local state of a component, this is appropriate any time we need to react to change forms and user click event's being simple examples.
|
||||
|
||||
#+BEGIN_SRC clojurescript
|
||||
|
||||
#+BEGIN_SRC clojurescript :results output :tangle src/clojure_demo/core.cljs
|
||||
(defn my-component [title starting-value]
|
||||
(let [local-state (reagent/atom starting-value)]
|
||||
(fn [title]
|
||||
[:h1 {:class (when @local-state "hide")
|
||||
:on-click (fn [] (swap! local-state inc))}
|
||||
:on-click (fn [e]
|
||||
(prn (-> e .-target))
|
||||
(swap! local-state inc))}
|
||||
(str title " " @local-state)])))
|
||||
|
||||
[my-component "Clickable component" 1]
|
||||
#+END_SRC
|
||||
|
||||
#+BEGIN_SRC clojurescript
|
||||
(defn update-form-data [form-data name value]
|
||||
(swap! form-data assoc [name] value))
|
||||
#+BEGIN_SRC clojurescript :results output :tangle src/clojure_demo/core.cljs
|
||||
(defn update-form-data [form-data ^js event]
|
||||
(prn "test here")
|
||||
(prn @form-data)
|
||||
;;(prn (.dir js/console event))
|
||||
(prn (-> event))
|
||||
(prn (-> event .-currentTarget))
|
||||
(prn (-> event .-target ))
|
||||
(prn (-> event .-target .-value))
|
||||
(swap! form-data assoc
|
||||
(keyword (-> event .-target .-name))
|
||||
(-> event .-target .-value)))
|
||||
|
||||
(defn my-address-form []
|
||||
(let [form-data (r/atom {})]
|
||||
(fn []
|
||||
[:form
|
||||
[:input {:name "address-line-1" :on-change :placeholder "Address Line 1"}]
|
||||
[:input {:name "address-line-2" :placeholder "Address Line 2"}]
|
||||
[:input {:name "address-line-3" :placeholder "Address Line 3"}]
|
||||
[:input {:name "city" :placeholder "City"}]
|
||||
[:input {:name "postcode" :placeholder "Postcode / Zipcode"}]
|
||||
]))
|
||||
(let [form-data (reagent/atom {})
|
||||
form-change (partial update-form-data form-data)]
|
||||
(fn []
|
||||
[:div
|
||||
(str @form-data)
|
||||
[:form {:on-submit prn}
|
||||
[:input {:type "text"
|
||||
:default-value (str (:test @form-data))
|
||||
:name "address-line-1"
|
||||
:on-change form-change :placeholder "Address Line 1"}]
|
||||
[:input {:type "text" :name "address-line-2" :on-change form-change :placeholder "Address Line 2"}]
|
||||
[:input {:name "address-line-3" :on-change form-change :placeholder "Address Line 3"}]
|
||||
[:input {:name "city" :on-change form-change :placeholder "City"}]
|
||||
[:input {:name "postcode" :on-change form-change :placeholder "Postcode / Zipcode"}]]])))
|
||||
|
||||
[:div [my-address-form]]
|
||||
#+END_SRC
|
||||
|
||||
|
||||
|
@ -96,7 +193,7 @@ usually this form of component is only needed when rendering graphics or things
|
|||
* Fetching a html element reference
|
||||
If we wish to capture a node we can use =:ref= and store the result in an atom, we can then de reference the atom and call a method on the node using =aget=.
|
||||
|
||||
#+BEGIN_SRC clojurescript :results output
|
||||
#+BEGIN_SRC clojurescript :results output :tangle src/clojure_demo/core.cljs
|
||||
(defn example-ref-component [title]
|
||||
(let [local-ref (reagent/atom nil)]
|
||||
(fn [title]
|
||||
|
@ -108,6 +205,21 @@ If we wish to capture a node we can use =:ref= and store the result in an atom,
|
|||
#+END_SRC
|
||||
|
||||
|
||||
#+BEGIN_SRC json :tangle src/clojure_demo/core.cljs
|
||||
|
||||
(defn current-page [])
|
||||
|
||||
(defn mount-root-page []
|
||||
;; this select the main node from the html file and injects your page content
|
||||
(.render
|
||||
(createRoot (.getElementById js/document "app"))
|
||||
(reagent/as-element [err-boundary [current-page]])))
|
||||
|
||||
(def launch (do (startup!) true))
|
||||
|
||||
#+END_SRC
|
||||
|
||||
|
||||
* Further reading
|
||||
|
||||
https://github.com/reagent-project/reagent
|
||||
|
|
|
@ -25,11 +25,12 @@
|
|||
[sci.core :as sci]
|
||||
[spec-tools.data-spec :as ds]))
|
||||
|
||||
(def languages {"clojure" {:mode "clojure"}
|
||||
"clojurescript" {:mode "clojure"}
|
||||
"yaml" {:mode "yaml"}})
|
||||
(def languages
|
||||
{"clojure" {:mode "clojure"}
|
||||
"clojurescript" {:mode "clojure"}
|
||||
"yaml" {:mode "yaml"}})
|
||||
|
||||
(def yaml-mode (LanguageSupport. (.define StreamLanguage yaml) ))
|
||||
(def yaml-mode (LanguageSupport. (.define StreamLanguage yaml)))
|
||||
|
||||
;; https://github.com/babashka/sci.configs
|
||||
(def rf-ns (sci/create-ns 'reitit.frontend nil))
|
||||
|
@ -56,22 +57,22 @@
|
|||
'rfe {'start! (sci/copy-var rfe/start! rfe-ns)
|
||||
'href (sci/copy-var rfe/href rfe-ns)}}}))
|
||||
|
||||
|
||||
;(def sci-ctx (sci/empty-environment))
|
||||
(sci/alter-var-root sci/print-fn (constantly *print-fn*))
|
||||
|
||||
(defn slugify [s]
|
||||
(str "toc"
|
||||
(-> s
|
||||
(clojure.string/lower-case)
|
||||
(clojure.string/replace #"[^\w]+" "-")
|
||||
(clojure.string/replace #"^-\\|-\\-$" ""))))
|
||||
(when s
|
||||
(str ;;"toc"
|
||||
(-> s
|
||||
(clojure.string/lower-case)
|
||||
(clojure.string/replace #"[^\w]+" "-")
|
||||
(clojure.string/replace #"^-\\|-\\-$" "")))))
|
||||
|
||||
(defn fetch-selected-text
|
||||
"Get the users selected text"
|
||||
[updated-view transactions]
|
||||
(reduce (fn [text t]
|
||||
(if (= "select.pointer" (str (.annotation t (.-userEvent Transaction) )))
|
||||
(if (= "select.pointer" (str (.annotation t (.-userEvent Transaction))))
|
||||
(conj text
|
||||
(.sliceDoc
|
||||
^EditorState (.-state updated-view)
|
||||
|
@ -101,7 +102,7 @@
|
|||
(first selected-text)
|
||||
(.-doc (.-state view-update)))]
|
||||
(reset! evaled-result (sci/eval-string* sci-ctx
|
||||
(.toString eval-code) ))
|
||||
(.toString eval-code)))
|
||||
(prn "updated delayed"))) 1000)))))
|
||||
start-state
|
||||
(.create EditorState
|
||||
|
@ -119,12 +120,12 @@
|
|||
;:mode "yaml"
|
||||
:mode "clojure"
|
||||
:updateListener prn
|
||||
:parent @editor })))))
|
||||
:parent @editor})))))
|
||||
:component-will-unmount (fn [_] (.destroy @view))
|
||||
:reagent-render (fn []
|
||||
[:div.mb2
|
||||
[:div.ba.ma0.f5.b--black-05.pa2.overflow-auto.editor {:ref #(reset! editor %)}]
|
||||
(when @evaled-result
|
||||
(when @evaled-result
|
||||
[:pre.ba.ma0.f6.code.b--black-05.pa2.pl4.overflow-auto
|
||||
{:style {:white-space "pre-line"}}
|
||||
;; See org mode :results key
|
||||
|
@ -135,24 +136,21 @@
|
|||
"silent" ""
|
||||
@evaled-result)])])})))
|
||||
|
||||
|
||||
(defn link-handler [v _]
|
||||
(prn v)
|
||||
(prn (conj [:a] v #_(second v)))
|
||||
(if (-> v second :img)
|
||||
(conj [:img] (dissoc (rename-keys (second v) {:href :src}) :img))
|
||||
(conj (conj [:a] v #_(second v)) (or (when-not (clojure.string/blank? (last v)) (last v))
|
||||
(:href (second v))
|
||||
(:title (second v))))))
|
||||
|
||||
(:href (second v))
|
||||
(:title (second v))))))
|
||||
|
||||
(defn link-handler4 [v _]
|
||||
(if (-> v second :img)
|
||||
(conj [:img] (dissoc (rename-keys (second v) {:href :src}) :img))
|
||||
(conj [:a] (second v) #_(or (when-not (clojure.string/blank? (last v)) (last v))
|
||||
{:href (:href (second v))}
|
||||
(:title (second v))))))
|
||||
|
||||
{:href (:href (second v))}
|
||||
(:title (second v))))))
|
||||
|
||||
(def theme
|
||||
(merge tachyon-theme
|
||||
|
@ -168,15 +166,15 @@
|
|||
{:HEADER1 (fn [v _] [:li [:a {:href (str "#" (slugify v))}
|
||||
[:span.f4.fw6.f3-ns.lh-title.mt0.mb2 v]]])
|
||||
:HEADER2 (fn [v _] [:li.ml2 [:a {:href (str "#" (slugify v))}
|
||||
[:span.f4.fw6.f4-ns.lh-title.mt0.mb2 v]]])
|
||||
[:span.f4.fw6.f4-ns.lh-title.mt0.mb2 v]]])
|
||||
:HEADER3 (fn [v _] [:li.ml4 [:a {:href (str "#" (slugify v))}
|
||||
[:span.f5.fw6.f5-ns.lh-title.mt0.mb2 v]]])
|
||||
[:span.f5.fw6.f5-ns.lh-title.mt0.mb2 v]]])
|
||||
:HEADER4 (fn [v _] [:li.ml6 [:a {:href (str "#" (slugify v))}
|
||||
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])
|
||||
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])
|
||||
:HEADER5 (fn [v _] [:li.ml8 [:a {:href (str "#" (slugify v))}
|
||||
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])
|
||||
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])
|
||||
:HEADER6 (fn [v _] [:li.ml10 [:a {:href (str "#" (slugify v))}
|
||||
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])}))
|
||||
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])}))
|
||||
|
||||
;; put constant data here
|
||||
(def site-data
|
||||
|
@ -215,7 +213,7 @@
|
|||
|
||||
;; form one component to render article tiles
|
||||
(defn articles [{:keys [title body articles]}]
|
||||
[:section.mw7.center.avenir
|
||||
[:section.mw7.center.avenir
|
||||
[:h2.baskerville.fw1.ph3.ph0-l title]
|
||||
(when body [:p body])
|
||||
(map (fn [{:keys [title author link description img-src img-alt]}]
|
||||
|
@ -245,7 +243,6 @@
|
|||
(defn circle [{:keys [img alt]}]
|
||||
[:div.pa4.tc [:img.br-100.ba.h3.w3.dib {:src img :alt alt}]])
|
||||
|
||||
|
||||
;; form one component to render a nav link
|
||||
(defn navbar-link [{:keys [href title text key] :or {text nil title nil}}]
|
||||
[:a.link.dim.white.dib.mr3 {:key (or key href) :href href :title title} text])
|
||||
|
@ -261,7 +258,6 @@
|
|||
{:target "_blank" :href "https://matrix.to/#/@oly:matrix.org"}
|
||||
"Contact me"]])
|
||||
|
||||
|
||||
;; form2 component notice the render function takes the same param as the component function
|
||||
;; this is important, you can hit issues if you forget this in form 2 components.
|
||||
(defn my-component [title value]
|
||||
|
@ -324,16 +320,17 @@
|
|||
(defn build-file-tar [code-blocks]
|
||||
(tarts (clj->js (mapv (fn [block] {:name (str (:tangle (second block)))
|
||||
:content (str (last block))})
|
||||
code-blocks ))))
|
||||
code-blocks))))
|
||||
|
||||
(defn build-file-tar-hm [code-blocks]
|
||||
(tarts (clj->js code-blocks )))
|
||||
(tarts (clj->js code-blocks)))
|
||||
|
||||
(defn build-tarts-map [blocks]
|
||||
(->> blocks
|
||||
(group-by (fn [block] (:tangle (second block))))
|
||||
(reduce (fn [m [k v]] (conj m {:name (str k)
|
||||
:content (str (concat (mapv last v)))})) [])))
|
||||
(reduce (fn [m [k v]]
|
||||
(conj m {:name (str k)
|
||||
:content (str (clojure.string/join "" (mapv last v)))})) [])))
|
||||
|
||||
(defn org->split2
|
||||
"Split out meta and body"
|
||||
|
@ -343,6 +340,34 @@
|
|||
:code (filter (fn filter-code [tag] (org-code (first tag))) dsl)
|
||||
:body (filter (fn filter-body [tag] (body (first tag))) dsl)})
|
||||
|
||||
(defn update-form-data [form-data ^js event]
|
||||
(prn "test here")
|
||||
(prn @form-data)
|
||||
;;(prn (.dir js/console event))
|
||||
(prn (-> event))
|
||||
(prn (-> event .-currentTarget))
|
||||
(prn (-> event .-target))
|
||||
(prn (-> event .-target .-value))
|
||||
(swap! form-data assoc
|
||||
(keyword (-> event .-target .-name))
|
||||
(-> event .-target .-value)))
|
||||
|
||||
(defn my-address-form []
|
||||
(let [form-data (reagent/atom {})
|
||||
form-change (partial update-form-data form-data)]
|
||||
(fn []
|
||||
[:div
|
||||
(str @form-data)
|
||||
[:form {:on-submit prn}
|
||||
[:input {:type "text"
|
||||
:default-value (str (:test @form-data))
|
||||
:name "address-line-1"
|
||||
:on-change form-change :placeholder "Address Line 1"}]
|
||||
[:input {:type "text" :name "address-line-2" :on-change form-change :placeholder "Address Line 2"}]
|
||||
[:input {:name "address-line-3" :on-change form-change :placeholder "Address Line 3"}]
|
||||
[:input {:name "city" :on-change form-change :placeholder "City"}]
|
||||
[:input {:name "postcode" :on-change form-change :placeholder "Postcode / Zipcode"}]]])))
|
||||
|
||||
;; form two component render demo
|
||||
;;(h/org->split (parse document1))
|
||||
(defn demo-page [route]
|
||||
|
@ -358,6 +383,7 @@
|
|||
org->split2
|
||||
(reset! content)))})
|
||||
(fn [route]
|
||||
<<<<<<< HEAD
|
||||
[:main.mt4.mw7.center.avenir
|
||||
|
||||
[:h1.f3.f2-ns (:content (last (first (:header @content))))]
|
||||
|
@ -375,7 +401,30 @@
|
|||
"Download Code"]
|
||||
[:div.mw7.center.avenir
|
||||
(into [:div] (org->replacements theme (:body @content)))]])))
|
||||
=======
|
||||
(if @content
|
||||
[:main.mt4.mw7.center.avenir
|
||||
[my-address-form]
|
||||
(slugify (:content (last (first (:header @content)))))
|
||||
[:h1.f3.f2-ns (:content (last (first (:header @content))))]
|
||||
[:div.mw7.center.avenir
|
||||
(into [:ol] (org->replacements theme-toc (:toc @content)))]
|
||||
[:p "The code in these examples is evaluated when modified, you can highlight a partial expression to evalute the selection, You can also download the code as a tar if you like and use it in your favourite editor."]
|
||||
[:a.f6.link.dim.ph3.pv2.mb2.dib.white.bg-dark-blue
|
||||
{:download (str (slugify (:content (last (first (:header @content))))) ".tar")
|
||||
:title (:content (last (first (:header @content))))
|
||||
:href (.createObjectURL
|
||||
js/URL
|
||||
(js/Blob. #js [(build-file-tar-hm
|
||||
(build-tarts-map
|
||||
(:code @content)))]
|
||||
{:type "application/tar"}))}
|
||||
"Download Code"]
|
||||
[:div.mw7.center.avenir
|
||||
(into [:div] (org->replacements theme (:body @content)))]]
|
||||
>>>>>>> a6c9ed1 (Updated reagent info.)
|
||||
|
||||
[:<>]))))
|
||||
|
||||
;; form one render about page component
|
||||
(defn about-page []
|
||||
|
@ -462,8 +511,7 @@
|
|||
;; this select the main node from the html file and injects your page content
|
||||
(.render
|
||||
(createRoot (.getElementById js/document "app"))
|
||||
(reagent/as-element [err-boundary [current-page]])
|
||||
))
|
||||
(reagent/as-element [err-boundary [current-page]])))
|
||||
|
||||
(defn ^:after-load render-site []
|
||||
;; this select the main node from the html file and injects your page content
|
||||
|
@ -478,15 +526,14 @@
|
|||
:ignore-anchor-click?
|
||||
(fn [router e el uri]
|
||||
;; Add additional check on top of the default checks\
|
||||
(and
|
||||
(ignore-anchor-click? router e el uri)
|
||||
(and
|
||||
(ignore-anchor-click? router e el uri)
|
||||
(not (let [href (or (.-href el) "")
|
||||
result (clojure.string/includes? href "#")]
|
||||
#_(when result
|
||||
#_(when result
|
||||
;(.preventDefault e)
|
||||
#_(js/console.log "will prevent by href" href))
|
||||
result))))
|
||||
})
|
||||
#_(js/console.log "will prevent by href" href))
|
||||
result))))})
|
||||
(render-site))
|
||||
|
||||
;; we defonce the startup so that hot reloading does not reinitialize the state of the site
|
||||
|
|
Loading…
Reference in New Issue