From 3fd100daf1f4c3c57d40d1914581b0aa150eb243 Mon Sep 17 00:00:00 2001 From: Oly Date: Tue, 3 Sep 2019 14:25:11 +0100 Subject: [PATCH] Clojurescript interface. --- deps.edn | 15 +++++ dev.cljs.edn | 7 +++ figwheel-main.edn | 5 ++ readme.org | 11 ++++ resources/public/index.html | 13 ++++ src/DEMOAPP/core.cljs | 122 ++++++++++++++++++++++++++++++++++++ src/cards/core.cljs | 5 ++ 7 files changed, 178 insertions(+) create mode 100644 deps.edn create mode 100644 dev.cljs.edn create mode 100644 figwheel-main.edn create mode 100644 resources/public/index.html create mode 100644 src/DEMOAPP/core.cljs create mode 100644 src/cards/core.cljs diff --git a/deps.edn b/deps.edn new file mode 100644 index 0000000..57d7950 --- /dev/null +++ b/deps.edn @@ -0,0 +1,15 @@ +{:deps {org.clojure/clojure {:mvn/version "1.10.0"} + org.clojure/clojurescript {:mvn/version "1.10.520"} + + reagent {:mvn/version "0.8.1"} + reagent-utils {:mvn/version "0.3.3"} + cljs-ajax {:mvn/version "0.8.0"} + pez/clerk {:mvn/version "1.0.0"} + metosin/reitit {:mvn/version "0.3.1"} + venantius/accountant {:mvn/version "0.2.4"} + + devcards {:mvn/version "0.2.6"} + com.bhauman/figwheel-main {:mvn/version "0.2.1-SNAPSHOT"} + cider/piggieback {:mvn/version "0.4.0"} + com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}} + :paths ["resources" "src"]} \ No newline at end of file diff --git a/dev.cljs.edn b/dev.cljs.edn new file mode 100644 index 0000000..b4bbca5 --- /dev/null +++ b/dev.cljs.edn @@ -0,0 +1,7 @@ +^{:extra-main-files {:devcards {:main cards.core}}} +{:output-to "resources/public/cljs-out/dev-main.js" + :optimizations :none + :pretty-print true + :source-map true + :devcards true + :main DEMOAPP.core} \ No newline at end of file diff --git a/figwheel-main.edn b/figwheel-main.edn new file mode 100644 index 0000000..27841fc --- /dev/null +++ b/figwheel-main.edn @@ -0,0 +1,5 @@ +{ + :target-dir "resources" + :watch-dirs ["src"] + :css-dirs ["resources/public/css"] +} \ No newline at end of file diff --git a/readme.org b/readme.org index a803685..e0d8f47 100644 --- a/readme.org +++ b/readme.org @@ -8,3 +8,14 @@ pip install esptool esptool -p /dev/ttyUSB0 make sure to set the spiffs size in the arduino before uploading to allocate space for files + + + +# Build with defaults shows default figwheel dev page +clojure -m figwheel.main + +# build with our custom figwheel-main options +clojure -m figwheel.main --build dev --repl + +http://localhost:9500/ +http://localhost:9500/figwheel-extra-main/devcards diff --git a/resources/public/index.html b/resources/public/index.html new file mode 100644 index 0000000..00a6a10 --- /dev/null +++ b/resources/public/index.html @@ -0,0 +1,13 @@ + + + + + + + + + +
Loading
+ + + diff --git a/src/DEMOAPP/core.cljs b/src/DEMOAPP/core.cljs new file mode 100644 index 0000000..792bb71 --- /dev/null +++ b/src/DEMOAPP/core.cljs @@ -0,0 +1,122 @@ +(ns DEMOAPP.core + (:require [accountant.core :as accountant] + [ajax.core :refer [GET]] + [clojure.spec.alpha :as s] + [reagent.core :as reagent :refer [atom]] + [reagent.session :as session] + [reitit.frontend :as reitit])) + +(enable-console-print!) +(defonce form-data (atom {:device-id "" :wifi-ssid "" :wifi-key ""})) + +(def device-id-regex #"[A-Za-z0-9]{4}") +(def ssid-regex #"^[!#;].|[+\[\]\"\t\s].*$") +(s/def ::wifi-ssid-type (s/and string? #(re-matches ssid-regex %))) +(s/def ::device-id-type (s/and string? #(re-matches device-id-regex %))) +(s/def ::wifi-key-type string?) + +; page routes +(def router + (reitit/router + [["/" :index] + ["/404" :about]])) + +; link builder +(defn path-for [route & [params]] + (if params + (:path (reitit/match-by-name router route params)) + (:path (reitit/match-by-name router route)))) + +; simple input form +(defn config-form [] + [:article.black-80.db.tc.black.ba.w-100.bg-light-green.br2 + [:form.ma3 {:action "sign-up_submit" :method "get" :accept-charset "utf-8"} + [:fieldset#sign_up.ba.b--transparent.ph0.mh0 + [:legend.ph0.mh0.fw6 "Device Setup"] + + [:div.mt3.dim + [:label.db.fw4.lh-copy.f6 {:for "device-id"} "Device Unique ID"] + [:input#wifi-ssid.pa2.input-reset.ba.bg-near-white.w-100.measure.b--silver + {:type "text" :name "device-id" :placeholder "AAAA" :autofocus "true" + :on-change #(swap! form-data assoc :device-id (-> % .-target .-value)) + :value (:device-id @form-data)}] + [:p (if (and (not-empty (:device-id @form-data)) + (s/explain-data + ::device-id-type + (:device-id @form-data))) + "Invalid identifier, should be alphanumeric and 4 characters long.")]] + + [:div.mt3.dim + [:label.db.fw4.lh-copy.f6 {:for "wifi-ssid"} "WIFI SSID"] + [:input#wifi-ssid.pa2.input-reset.ba.bg-near-white.w-100.measure.b--silver + {:type "text" :name "wifi-ssid" :placeholder "" + :on-change #(swap! form-data assoc :wifi-ssid (-> % .-target .-value)) + :value (:wifi-ssid @form-data)}] + [:p (if (and (not-empty (:device-id @form-data)) + (s/explain-data + ::device-id-type + (:device-id @form-data))) + "Invalid SSID, should be no more than 32 characters and must not start with !, #, or ;.")]] + + [:div.mt3.dim + [:label.db.fw4.lh-copy.f6 {:for "wifi-password"} "WIFI Password"] + [:input#password.pa2.input-reset.ba.bg-near-white.w-100.measure.b--silver + {:type "password" :name "wifi-password" + :on-change #(swap! form-data assoc :wifi-key (-> % .-target .-value)) + :value (:wifi-key @form-data)}] + [:p (if (and (not-empty (:wifi-key @form-data)) + (s/explain-data + ::wifi-ssid-type + (:wifi-key @form-data))) + "No password set.")]]] + [:div.mt3 + [:input.b.ph3.pv2.input-reset.ba.b--black.bg-transparent.grow.pointer.f6.br2 + {:type "submit" :value "Save"}]]]]) + +(defn home-page [] + [:div.w-25 + [:img {:src "logo.png"}] + (config-form)]) + +(defn success-page [] + [:div + [:div [:h1.m-4 "Settings saved"] + [:p "Device will reboot in a few seconds and connect to your wifi."]]]) + +(defn about-page [] + [:div + [:div [:h1.m-4 "About Page"] + [:p "Sample app, demoing using ajax calls and reagent to render the page with some simple route from reitit, basically enought to get you started on your clojurescript journey."] + + [:a.navbar-item {:href (path-for :index)} "Home Page"]]]) + +(defn page-for [route] + "Map your route keys to pages here" + (case route + :index #'home-page + :about #'about-page)) + +; default page wrapper +(defn current-page [] + (fn [] + (let [page (:current-page (session/get :route))] + [:div.bg-green.flex.justify-center.items-center.h-100 [page]]))) + +(defn startup [] + (accountant/configure-navigation! + {:nav-handler + (fn [path] + (let [match (reitit/match-by-path router path) + current-page (:name (:data match)) + route-params (:path-params match)] + (session/put! :route {:current-page (page-for current-page) + :route-params route-params}))) + + :path-exists? + (fn [path] + (boolean (reitit/match-by-path router path)))}) + (accountant/dispatch-current!) + + (reagent/render [current-page] (.getElementById js/document "app"))) + +(startup) diff --git a/src/cards/core.cljs b/src/cards/core.cljs new file mode 100644 index 0000000..931d75c --- /dev/null +++ b/src/cards/core.cljs @@ -0,0 +1,5 @@ +(ns cards.core + (:require + [devcards.core] + [DEMOAPP.core])) +(devcards.core/start-devcard-ui!) \ No newline at end of file