Fork me on GitHub
#hoplon
<
2016-04-05
>
leontalbot02:04:17

@flyboarder: I don't know. Have you seen https://github.com/crisptrutski/matchbox The author of this library, @crisptrutski, even though I am not sure he knows hoplon, is really kind and could maybe help you...

leontalbot02:04:59

@micha Did you get the chance to play around with the state machine tonight 😉

flyboarder03:04:38

@leontalbot: i was playing with matchbox, but went for a homegrown approach instead 😕 playing with the firebase promises is working so far

leontalbot04:04:03

@micha. Couldn't make the "state machine" work yet...

micha13:04:58

@leontalbot: i didn't have a chance to do it last night, did you make any progress on the lens approach?

micha13:04:22

seems like the lens could work pretty well

micha14:04:10

the miracle happened

jumblerg14:04:34

hell froze over.

leontalbot15:04:04

@jumblerg: Was looking at https://github.com/hoplon/ui/blob/master/tst/hoplon/ui-test-app.cljs.hl to see an example of hoplon/ui. This is pretty cool!

jumblerg15:04:25

ty! it’s buggy, atm, but i think the most annoying problems are solvable. at a minimum, i hope the ideas it introduces help to move things forward.

leontalbot15:04:50

I love the simplicity of the definition of the routing

jumblerg15:04:36

in my production app those attrs are bound to cells, which update from the model

jumblerg15:04:10

the idea is that the window component provides you everything you need to interface with the browser itself

dm315:04:37

boot test doesn't work though

dm315:04:48

as the README says

jumblerg15:04:08

uh, oh. try boot run… forgot to update it.

jumblerg15:04:41

hopefully run/test will ultimately hook into some selenium tests.

jumblerg15:04:18

i’m currently working on applying the same box model to the body elem returned by the window fn that all the other elements use. that will eliminate the need for the outer elem used in the test-app.

jumblerg15:04:53

should be able to pass :ah :center :av :middle directly to window as well

leontalbot15:04:01

can I add custom html-meta

leontalbot15:04:26

for instance og metas for social media?

jumblerg15:04:04

i haven't considered that case, but should be able to support it easily enough.

jumblerg15:04:38

should be able to accept meta attributes the same way link and script attributes are used to generate tags.

jumblerg15:04:07

@leontalbot: could you paste me a list of the sample meta tags you’d normally add to your html?

jumblerg15:04:42

i’ll add that feature in a bit, since i’m currently working on the window fn

leontalbot15:04:32

these could be automated

leontalbot15:04:46

(meta {:property "og:title", :content page-title})
(meta {:property "og:description", :content page-desc})
(meta {:property "og:type", :content "website"})

leontalbot15:04:27

other possibility

(def metas-og
  [(meta {:property "og:url", :content ""})
   (meta {:name "image_src", :content ""})
   (meta {:property "og:image", :content ""})
   (meta {:property "og:image:width", :content "180"})
   (meta {:property "og:image:height", :content "110"})
   (meta {:property "og:image", :content ""})
   (meta {:property "og:image:width", :content "250"})
   (meta {:property "og:image:height", :content "250"})
   (meta {:content "text/html; charset=UTF-8", :http-equiv "content-type"})])

leontalbot15:04:11

og:url could also be automated and charset too. The rest would be add manually I guess

leontalbot15:04:24

I haven't study the evolution of og tags since 2014 though...

leontalbot15:04:37

May be outdated... not sure

micha16:04:29

@leontalbot: is the lens approach looking like it will work for you?

micha16:04:11

i can't really think of a simpler solution given that it's all totally dynamic

micha16:04:51

the one thing i would probably do on the UI side is make an element that uses cond-tpl or something to be polymorphic on the schema

micha16:04:05

like for checkbox vs select or whatever

micha16:04:28

the *-tpl things are ideal for that

micha16:04:38

since you're basically filling a template from data

leontalbot16:04:31

cool, i had something like :

(form-group :css (let [x1 (path [:visible-if-id])
                            x2 (path [:visible-if-any])
                            x3 (path [:visible-if-none])
                            x4 (path [:visible-if-values])
                            x5 (path [:visible-unless-values])
                            v  (path-cell n-questions [@x1 :answer])
                            h  (path [:hide])]
                        ((formula
                          #(cond
                             %7 hide
                             (empty? %1) show
                             %2 (if (empty? %6) hide show)
                             %3 (if (empty? %6) show hide)
                             %4 (if (some (into #{} %6) %4) show hide)
                             %5 (if (some (into #{} %6) %5) hide show)))
                         x1 x2 x3 x4 x5 v h))

                 (question (:question @item))
                 (sub-question (:sub-question @item))
                 (little-question (:little-question @item))
                 (p :css {:color "#777"} (:precisions @item))
                 (case @(path [:type])
                   "checkbox"
                   (form-list-buttons
                    :checkbox true
                    :cell (path [:answer])
                    :selected-color (:selected-color static-content)
                    (:choices @item))
                   "radio"
                   (form-list-buttons
                    :cell (path [:answer])
                    :selected-color (:selected-color static-content)
                    (:choices @item))
                   "textarea"
                   (vpc-input
                    :cell (path [:answer])
                    :type "textarea")
                   "select"
                   (form-select
                    :cell (path [:answer])
                    (:choices @item))
                   "input"
                   (vpc-input
                    :cell (path [:answer])
                    :type "text")
                   ""))

leontalbot16:04:11

is it where I should use cond-tpl?

dm316:04:22

if your (path [:type]) is a cell

leontalbot16:04:56

oups sorry here is the complete fn :

(defelem vpc-question [{:keys [id] :as attrs}]
  (let [item (path-cell n-questions [id])
        path (fn [k-vec] (path-cell item k-vec))
        show {:display "block"}
        hide {:display "none"}]
    (div
     (form-group :css (let [x1 (path [:visible-if-id])
                            x2 (path [:visible-if-any])
                            x3 (path [:visible-if-none])
                            x4 (path [:visible-if-values])
                            x5 (path [:visible-unless-values])
                            v  (path-cell n-questions [@x1 :answer])
                            h  (path [:hide])]
                        ((formula
                          #(cond
                             %7 hide
                             (empty? %1) show
                             %2 (if (empty? %6) hide show)
                             %3 (if (empty? %6) show hide)
                             %4 (if (some (into #{} %6) %4) show hide)
                             %5 (if (some (into #{} %6) %5) hide show)))
                         x1 x2 x3 x4 x5 v h))

                 (question (:question @item))
                 (sub-question (:sub-question @item))
                 (little-question (:little-question @item))
                 (p :css {:color "#777"} (:precisions @item))
                 (case @(path [:type])
                   "checkbox"
                   (form-list-buttons
                    :checkbox true
                    :cell (path [:answer])
                    :selected-color (:selected-color static-content)
                    (:choices @item))
                   "radio"
                   (form-list-buttons
                    :cell (path [:answer])
                    :selected-color (:selected-color static-content)
                    (:choices @item))
                   "textarea"
                   (vpc-input
                    :cell (path [:answer])
                    :type "textarea")
                   "select"
                   (form-select
                    :cell (path [:answer])
                    (:choices @item))
                   "input"
                   (vpc-input
                    :cell (path [:answer])
                    :type "text")
                   "")))))

leontalbot16:04:40

n-question is the global state cell

micha16:04:50

i think the case analysis you have there is where you could use case-tpl, no?

micha16:04:14

that way you could load different question sets into the same elements

micha16:04:24

and they would just reactively swap out the elements

leontalbot16:04:31

didn't know about case-tpl, is it the same

micha16:04:38

but with all the benefits of static allocation and so on

micha16:04:43

yea it's in master

micha16:04:12

(case-tpl some-cell
  :a (div ...)
  :b (span ...)
  (p ...))

micha16:04:30

it's like loop-tpl

micha16:04:34

but for a conditional

micha16:04:02

there is also if-tpl, when-tpl, cond-tpl

micha16:04:52

@dm3 suggested multimethod tpl, which we can toatlly do, too

micha16:04:57

but isn't in there at this time

jumblerg16:04:54

@leontalbot: i’m wondering if the open graph protocol should have it’s own attribute and representation. http://ogp.me/

leontalbot16:04:38

yeah good idea

jumblerg16:04:02

not sure yet, general metadata can be cleanly represented with a simple map, but the ogp uses custom “property” keys instead. i wonder how many other cases there are like this i’m not aware of.

jumblerg16:04:31

eg (window :metadata {“image_src”, "} (elem “stuff”)) -> <meta name=“image_src” content=“http…”> reading up on RDFa, which is used by OGP, Dublin Core, FOAF, and whatnot.

leontalbot17:04:54

@micha regarding the "state machine" I am stuck here :

leontalbot17:04:05

Uncaught Error: [object Object] is not ISeqable at line 22

leontalbot17:04:40

I get this when I toggle a checkbox.

micha18:04:21

creating formulas inside a formula seems dangerous

micha18:04:50

oh wait nm

micha18:04:56

sorry i misread

micha18:04:22

why does show-only-ids return a cell?

micha18:04:57

you can deref c there

micha18:04:00

the reason for that error is that so-ids is a cell

micha18:04:07

and cells are not seqable

micha18:04:31

but, i think on line 21 you can just have show-only-ids return data, not formula

micha18:04:51

i.e. show-only-ids is just a regular function of data->data

micha18:04:23

line 21 ... (show-only-ids @c)

micha18:04:44

actually i think you can probably use c* there instead of @c even

micha18:04:07

basically your function (fn [c*] ... there takes the value the user wants to set the cell to, and modifies it

micha18:04:16

then the function sets c to be the modified value

micha18:04:25

via reset! or swap!

micha18:04:45

and in that function c* will not be a cell

micha18:04:49

it's just the new value

micha18:04:01

the value that the user is attempting to set the cell to

micha18:04:18

the lens takes two arguments, the formula and the callback

micha18:04:38

the formula provides the value when you deref the lens or make a formula that depends onit

micha18:04:58

the callback is evaluated for side effects only, whenever the user calls swap! or reset! on the lens

micha18:04:23

that callback can do anything, and it gets one argument: the new value that the user wants to set the lens to

micha18:04:33

in the callback you can swap or reset other cells

micha18:04:13

it's sort of like a watch, but it preserves the dependency graph correctly

leontalbot18:04:52

@micha: Thanks... I now getting No protocol method IDeref.-deref defined for type cljs.core/PersistentHashMap

micha18:04:11

yeah just use c* there

micha18:04:23

(show-only-ids c*)

micha18:04:41

and remove the cell= from the show-only-ids function

leontalbot18:04:13

actually I did @c* and not @c

micha18:04:21

c* isn't a cell

micha18:04:31

so you want to change the places where you swap or rest that

micha18:04:45

you want to have your callback compute the real value for c

micha18:04:08

and then call (reset! c (new-value c*)) basically

micha18:04:43

where new-value is a plain function that given c* computes what c should correctly be (i.e. adding the hide info)

micha18:04:55

here is a simpler example:

leontalbot18:04:43

ok, trying...

micha18:04:04

(let [c (cell 0)]
  (defc= state {:value c :even? (even? c)}
    (fn [c*] (reset! c (:value c*)))))
    
@state                                 ;=> {:value 0 :even? true}
(swap! state update-in [:value] inc)   ;=> {:value 1 :even? false}

micha18:04:34

notice how i'm doing the work in the formula

micha18:04:58

the callback part of the lens is really just ignoring the parts of the input that will be recomputed in the formula

micha18:04:19

notice how the c cell doesn't contain any derived or computed state

micha18:04:29

only the raw data that you need

micha18:04:10

in other words, the c cell contains all the actual data we need. the rest of the stuff in the map can be computed from that in a formula

micha18:04:51

the :even? key in my example seems to be similar to the :hide property in your thing

leontalbot19:04:57

if you have big state, will you call even to every map of map?

micha19:04:42

how do you mean?

micha19:04:01

the formula will be recomputed, is that what you mean?

leontalbot20:04:29

@micha, ok I solve the problem. Thanks a lot for your advices and help.

leontalbot20:04:56

For the record, here are the correct fns :

leontalbot20:04:50

I feel really wasted and would need a 🍺 tonight before I can read back your last advice here https://clojurians.slack.com/archives/hoplon/p1459882504003536 and understand it correctly 😄

micha20:04:37

sure, it looks great!