hoplon

The :hoplon: ClojureScript Web Framework - http://hoplon.io/
Josh Horwitz 2018-07-28T02:42:19.000004Z

So I went through the getting started on the website, are there any other resources to follow to learn more, such as a more detailed tutorial? I’m going to start by making a simple website for my non-profit

vigilancetech 2018-07-28T03:12:03.000020Z

@joshua.d.horwitz there's the demos

vigilancetech 2018-07-28T05:28:39.000050Z

is there any reason why my javelin cells would work after a boot-reload where they wouldn't work after clicking the reload button?

Josh Horwitz 2018-07-28T16:39:10.000010Z

Thanks @jjttjj, I’m coming from writing React on the front end for a long time so it’s hard for me to step away from that and into Hoplon if that makes sense

2018-07-28T16:49:42.000075Z

the nice thing about hoplon is it's really just a wrapper on the native browser element api (as that article I linked demonstrates)

2018-07-28T16:50:30.000061Z

so whereas react is kind of separate system to learn

2018-07-28T16:51:08.000017Z

i recently did the opposite, had to dabble a bit in react for the first time coming from a hoplon background

2018-07-28T16:54:42.000053Z

i haven't really fully formulated any "big takeaways" from the experience regarding hoplon vs react. but in many ways they share a similar goal, which is "just write html with the changeable state just directly in line"

2018-07-28T16:54:59.000042Z

and have the changes be "automagic"

2018-07-28T16:56:03.000086Z

in hoplon you don't have to worry about all the lifecycle stuff of react

2018-07-28T16:56:21.000003Z

and you end up with plain js html elements

2018-07-28T17:01:54.000055Z

react is definitely a more complicated abstraction. both approaches have their own pros and cons

Josh Horwitz 2018-07-28T17:15:38.000090Z

I can see that. I guess since I know React so well it’s hard going the other way, but I really like the community and like Hoplon a lot

vigilancetech 2018-07-28T17:52:51.000013Z

best I've been able to extract, here's the code where the javelin cells won't operate until a boot-reload happens:

(defonce hist (cell #queue[]))

(when-not @conn
  (-> (s/connect URL)
      (.then  #(reset! conn (s/bind-sensors! (with-let [conn %] (s/get-ui-state conn)) data ui-state error 1000 120)))
      (.catch #(.log js/console "error: " %))))

(def data  (cell= (-> hist last) #(swap! hist (fn [h] (conj (if (> (count h) 180) (pop h) h) %)))))

(defn- mkremote [tag & keys]
  (fn [conn & vals]
    (let [data (zipmap keys vals)]
      (->> {:tag tag :data data} (clj->js) (.stringify js/JSON) (.send @conn)))))

(defn bind-sensors! [conn state ui error & [poll-freq hist-max]]
  (let [cljs #(js->clj % :keywordize-keys true)
        parse #(-> % .-data js/JSON.parse cljs)]
    (with-let [_ conn]
      (cell= (set! (.-onmessage conn)
                   ~(fn [e] (let [d (parse e)]
                              (when (re-find (re-pattern (:tag d)) "sensors ui_state")
                                #_(prn :data (:data d))
                                (if (= (:tag d) "ui_state")
                                  (do #_(println "ui_state found")
                                      (reset! ui (:data d)))
                                  (reset! state (data (:data d)))))))))
      (cell= (set! (.-onerror   conn) ~(fn [e] (reset! error e))))
      ((mkremote "get_sensors") conn))))

(defn n-device-records [type] [:lights sp/ALL #(= (:type %) type)])

(defn effects [d type] (sp/select  [(n-device-records type) :effect] d))

(defn fan-effects [d] (sp/select [:lights sp/ALL #(= (:type %) :fan) :effect] d))

(defc= any-fans-lit?   (with-let [z (not-every? #(= "none" %) (doall (fan-effects data)))] (prn "f-e=" z)))

vigilancetech 2018-07-28T17:55:11.000056Z

even if fans are lit, any-fans-lit? returns false until after a boot-reload, then it returns true. Is there some kind of initialization I'm supposed to do manually (that boot-reload does)?

2018-07-28T18:00:51.000030Z

i have a feeling the problem doesn't actually realate to boot reload but something to do with your own state initialization. I could be wrong. But I've had similar initializing issues that were usually something i was doing wrong to init things

2018-07-28T18:01:45.000028Z

do you declare data before the when-not @conn form? because you reference data in it but data isn't defed until after

vigilancetech 2018-07-28T18:06:11.000062Z

yes, its above it in the actual program

vigilancetech 2018-07-28T18:09:28.000040Z

right after clicking the reload button I get this in the repl:

d/any-any-lit?
#<Cell: false>
cljs.user> (not-every? #(= "none" %) (doall (d/fan-effects @d/data)))
true

then when change the source code and it recompiles/boot-reloads:
d/any-any-lit?
#<Cell: true>
cljs.user> 

vigilancetech 2018-07-28T18:10:02.000053Z

maybe its a lazy/eager issue, but damned if I can see it

vigilancetech 2018-07-28T18:11:10.000089Z

best I can tell the cell formula just refuses to fire off

vigilancetech 2018-07-28T18:13:38.000026Z

I've even tried expanding the javelin macros and plugging them into the source code. Still no love.

(def any-fans-lit?
  ((javelin.core/formula
    (fn*
     ([G__55208 G__55206 G__55205 G__55207 G__55204]
      (G__55204
       (fn* ([p1__55202#] (G__55205 "none" p1__55202#)))
       (G__55206 (G__55207 G__55208))))))
   data
   doall
   =
   fan-effects
   not-every?))

vigilancetech 2018-07-28T18:17:42.000074Z

fan effects right after hitting the reload button:

(d/fan-effects @d/data)
["none" "none" "cpu_temp" "none" "none" "none"]

2018-07-28T18:41:27.000054Z

is there a brief moment in time during pageload where the d argument passed to fan effects is nil?

2018-07-28T18:42:11.000038Z

would adding the (when data ... here help?

(defc= any-fans-lit?  (when data (with-let [z (not-every? #(= "none" %) (doall (fan-effects data)))] (prn "f-e=" z))))

😀 1
2018-07-28T18:42:47.000055Z

(i know these are very low hanging fruit things i'm throwing out there)

vigilancetech 2018-07-28T18:54:48.000046Z

ah, it doesn't seem like it would be so because when I do it by hand in the repl data has already been flowing for a while, plus why does it do it when I do by hand the non-javelin/formula part? Seems its definitely something to do with javelin. Either hoplon is missing some initialization upon first load or boot-reload is re-initializing something that wouldn't be found in a virgin page load

vigilancetech 2018-07-28T18:56:00.000050Z

@micha would you have any idea? You wrote boot, didn't you?

flyboarder 2018-07-28T20:11:18.000054Z

@vigilancetech is this an issue of authentication? What is the data source?

flyboarder 2018-07-28T20:11:41.000058Z

I often see that cells fail to fire initially because of some websockets auth issues

vigilancetech 2018-07-28T21:38:01.000037Z

@flyboarder the data source is a c# server program. Doesn't seem likely its an auth issue:

cljs.user> d/any-fans-lit?
#<Cell: nil>
cljs.user> (d/fan-effects @d/data)
["none" "cpu_load" "none" "none" "none" "none"]
cljs.user> (not-every? #(= "none" %) (doall (d/fan-effects @d/data)))
true
cljs.user> ;; using UI to change which fan is lit
cljs.user> d/any-fans-lit?
#<Cell: nil>
cljs.user> (d/fan-effects @d/data)
["none" "none" "none" "static_color" "none" "none"]
cljs.user> (not-every? #(= "none" %) (doall (d/fan-effects @d/data)))
true
cljs.user> ;; doing boot-reload here
cljs.user> d/any-fans-lit?
#<Cell: true>
cljs.user> (not-every? #(= "none" %) (doall (d/fan-effects @d/data)))
true
cljs.user> (d/fan-effects @d/data)
["none" "none" "none" "static_color" "none" "none"]
cljs.user> 

flyboarder 2018-07-28T21:39:47.000017Z

Are you storing any state globally?

vigilancetech 2018-07-28T21:41:39.000021Z

can you be more specific? The server stores the state. When the UI changes anything its sent to the server then the reflected back changes are displayed by the UI

vigilancetech 2018-07-28T21:45:15.000062Z

the boot-reload does something to get the javelin formulas to fire off then they're fine after that. I've tried building other similar sample programs employing specter searches where I poke the data in from the repl rather than clicking and they work just fine.

vigilancetech 2018-07-28T21:49:08.000013Z

best I can tell the only source code involved I pasted above.

vigilancetech 2018-07-28T21:50:00.000028Z

you see anything I missed?

vigilancetech 2018-07-28T21:53:16.000035Z

here's one thing I missed:

(defonce conn (atom nil))