Fork me on GitHub
#hoplon
<
2018-07-28
>
Josh Horwitz02:07:19

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

vigilancetech05:07:39

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 Horwitz16:07:10

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

jjttjj16:07:42

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

jjttjj16:07:30

so whereas react is kind of separate system to learn

jjttjj16:07:08

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

jjttjj16:07:42

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"

jjttjj16:07:59

and have the changes be "automagic"

jjttjj16:07:03

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

jjttjj16:07:21

and you end up with plain js html elements

jjttjj17:07:54

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

Josh Horwitz17:07:38

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

vigilancetech17:07:51

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)))

vigilancetech17:07:11

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)?

jjttjj18:07:51

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

jjttjj18:07:45

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

vigilancetech18:07:11

yes, its above it in the actual program

vigilancetech18:07:28

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> 

vigilancetech18:07:02

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

vigilancetech18:07:10

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

vigilancetech18:07:38

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?))

vigilancetech18:07:42

fan effects right after hitting the reload button:

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

jjttjj18:07:27

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

jjttjj18:07:11

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))))

😀 4
jjttjj18:07:47

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

vigilancetech18:07:48

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

vigilancetech18:07:00

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

flyboarder20:07:18

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

flyboarder20:07:41

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

vigilancetech21:07:01

@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> 

flyboarder21:07:47

Are you storing any state globally?

vigilancetech21:07:39

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

vigilancetech21:07:15

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.

vigilancetech21:07:08

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

vigilancetech21:07:00

you see anything I missed?

vigilancetech21:07:16

here's one thing I missed:

(defonce conn (atom nil))