Fork me on GitHub
#hoplon
<
2016-12-15
>
jjttjj01:12:52

I think I'm missing something. Does anyone know why binding isn't working here at the end of the candlestick-chart function? That is, when *to-y* gets called inside candle it's still nil.

(def ^:dynamic *to-y* nil)
(defn candle [n ohlc]
  (j/cell-let [{:keys [open high low close]} ohlc]
   (let [x           (cell= (* n (+ candle-width candle-spacing)))
         wick-x      (cell= (+ x (/ candle-width 2)))
         body-height (cell= (max (- (max open close) (min open close)) 1))
         body-top    (cell= (*to-y* (if (> close open) close open)))
         border      {:stroke "black" :stroke-width 1 :shape-rendering "crispEdges"}]
     [(s/line :x1 wick-x :x2 wick-x
              :y1 (cell= (*to-y* high))
              :y2 (cell= (*to-y* low))
              border)
      (s/rect :x x :y body-top :width candle-width
              :height body-height
              :fill (cell= (if (< close open) "black" "white"))
              border)])))

(defelem candlestick-chart [{:keys [data] :as attrs} elems]
  (let [e                (s/svg (dissoc attrs :data))
        container-width  (cell= (.-offsetWidth  e)) 
        container-height ;(cell= (log/spy (.-offsetHeight e)))
        (:height attrs)
        data-high        (cell= (apply max (map :high data)))
        data-low         (cell= (apply min (map :low  data)))
        data-range       (cell= (- data-high data-low))]
    (binding [*to-y* (cell= #(* (/ (log/spy container-height) data-range)
                                (- data-high %)))]
      (e
       (for-tpl [[i ohlc]
                 (cell= (map-indexed vector data))]
         (candle i ohlc))))))

jjttjj01:12:54

I tried with hoplon.binding/binding and cljs.core/binding

alandipert01:12:09

@jjttjj what if you put the binding inside the for-tpl?

jjttjj01:12:36

@alandipert I tried that and it works, but doesn't that require a lot of extra work, when it should be a constant value for everything in the for-tpl loop? is that just unavoidable?

jjttjj01:12:48

by a lot of extra work i mean computationally

alandipert01:12:28

it just confirms my suspicion without me needing to test 🙂

alandipert01:12:44

the problem is that the body of a -tpl is turned into a thunk

alandipert01:12:53

so candle is called asynchronously, basically

jjttjj01:12:08

yeah i figured it was something like that

alandipert01:12:16

conferring here with micha

alandipert01:12:26

fix #1: make an arity of the candle function that takes the binding

alandipert01:12:31

err, takes a value

alandipert01:12:49

defeats dynamic binding to a degree of course, but in this particular case seems palatable

alandipert01:12:58

that's a preference anyway i guess, whether to pass or bind

alandipert01:12:03

fix #2 is the "real" fix

alandipert01:12:09

use hoplon.binding/bound-fn

alandipert01:12:20

to make a version of candle that uses the hoplon bound-fn magic to do what you're expecting

jjttjj01:12:08

ok awesome thanks i'll try the bound-fn way and failing that just pass the value!

alandipert02:12:02

whether or not it makes sense to go bound-fn to make the binding work i think depends on your goals for organizing the bigger thing that we don't see in your snippet

jjttjj02:12:51

gotcha. yeah I really need to get better at actually planning things out in general. thanks again

jumblerg02:12:53

@john_tollison: we've used both trigger and cordova successfully without issues.

jumblerg02:12:11

i doubt that javelin is the issue; that thing is rock-solid, in my experience.

jumblerg02:12:17

i can share some snippets from a mobile project i did with hoplon if you'd find them helpful.

john_tollison03:12:29

It's good to hear that javalin shouldn't be an issue. Code snippets may help. I should probably try to drill down a little more on specifically where things break down. I had this program I dropped in, all at once, and I was surprised when it sortof worked. I expected all or nothing. Let me do some more poking around and get back to you.

micha03:12:50

i've also used hoplon with http://trigger.io a couple of years ago

micha03:12:25

the only real issues i had was figuring out how to get the certs and signatures and stuff to work with the app store for ios

micha03:12:38

at the time http://trigger.io wasn't very well documented

micha03:12:00

but overall it was a pretty nice experience

micha03:12:25

we were also able to use a commercial jquery widget library that was pretty good

micha03:12:38

made nice controls for mobile

micha03:12:52

saved us a good amount of time probably

john_tollison03:12:37

yes, I found out about http://trigger.io from a post you made on the discourse board, so I figured it shouldn't be too bad.

micha03:12:10

i haven't looked at it lately, are they still in business?

micha03:12:31

things seemed like they might have been a little shaky back then, not sure if they survived

micha03:12:03

they were the simplest one i could find

john_tollison03:12:29

Yes, they appear to be doing ok.

john_tollison03:12:20

I am seeing some action with cells now. I jumped to bad conclusions. Hopefully, I'll be able to work through other problems I'm seeing.

onetom05:12:10

@flyboarder: as the local firebase expert, I hope you might know if there is any solution for developing offline or integration testing firebase. I saw there is https://github.com/katowulf/mockfirebase and https://github.com/urish/firebase-server but how can I deal with the storage or the auth clients?

onetom05:12:13

For storage minio might work somehow...?

piotrek09:12:14

Hello, could you suggest any hoplon app examples handling authorisation (hiding functionality) to different parts of the application depending on the user role? It would be perfect if it would also show how to provide some parts as available without logging in

thedavidmeister10:12:20

@piotrek i guess it depends how secure you need it to be

thedavidmeister10:12:37

ultimately the hoplon side is JS so someone can always edit values to be whatever they want

thedavidmeister10:12:49

the only way to truly protect data is to not send it to the browser at all

thedavidmeister10:12:07

for that, i’ve had some success grabbing JWT tokens from auth0 and adding them to the headers that get sent to the server

thedavidmeister10:12:33

JWT has the nice properties of being stateless and immutable, so it’s a reasonably natural fit

piotrek11:12:25

Thanks @thedavidmeister. Yes, I am aware that user has full access to JS app code/state. That’s why I wrote “hiding functionality”. I am interested how to systematically solve that instead of sprinkling ifs everywhere. I know backend security area much better and yes JWT with buddy looks like a good solution

thedavidmeister11:12:10

oh, if you just want to hide things visually then cell= is certainly the way to go

thedavidmeister11:12:41

the higher up the DOM heirarchy you put the cell, the less if statements you’ll need

thedavidmeister11:12:21

@piotrek when you say “different parts of the application”, do you mean routes/pages?

thedavidmeister11:12:32

or individual elements?

piotrek11:12:35

individual elements

piotrek11:12:46

e.g. logged in users should see some additional content

piotrek11:12:36

but it’s also about top level routes - some “pages” shouldn’t be visible at all (and when accessed should display an error message)

thedavidmeister11:12:34

i tend to split out elements to have a single concern and pass in all the cells they need to render

thedavidmeister11:12:08

so I’d just pass in a logged-in? cell or similar

thedavidmeister11:12:18

@piotrek are you using something like bidi to handle routing?

thedavidmeister11:12:04

@piotrek fyi though, you don’t need if to visually hide something :toggle my-cell? will show/hide based on the truthyness of my-cell?

thedavidmeister11:12:21

again though, that’s even less secure

thedavidmeister11:12:25

it’s just a matter of css at that point

piotrek11:12:44

That’s ok as the backend will prevent unauthorised actions

piotrek11:12:13

It’s rather to not show what might end up with authz error

piotrek11:12:46

So the user doesn’t have possibility to even try to invoke something that will complete with HTTP 403

thedavidmeister11:12:58

(button :toggle auth? “Click me”)

thedavidmeister11:12:17

if you want something more sophisticated, you could extend do!

thedavidmeister11:12:49

to invent something like (button :admin roles “click me”)

thedavidmeister11:12:40

toggle is implemented like this

thedavidmeister11:12:42

(defmethod do! :toggle
  [elem _ v]
  (style/setElementShown elem (boolean v)))

thedavidmeister11:12:47

you could do like

thedavidmeister11:12:23

(defmethod do! :admin
  [elem _ rs]
  (style/setElementShown elem (contains? rs :admin)))

thedavidmeister11:12:00

i dunno, what were you expecting @piotrek ?

piotrek11:12:49

Hmm, extending do! looks interesting @thedavidmeister

piotrek11:12:16

I could define :required-permissions attribute and define checking the actual available permissions in one place (my defmethod for that keyword)

thedavidmeister11:12:28

i recommend that if you implement anything that “dials out” to a global state, implement that as fallback behaviour

thedavidmeister11:12:34

it will make testing much easier

piotrek12:12:28

yeah, passing user details or permissions (or referring it directly from global var) in all the components would be a bad idea; using do! adds a level of indirection and decouples components

flyboarder14:12:30

@onetom: hey, I haven't used either of those before

flyboarder14:12:06

Usually because firebase is entirely hosted, there is no offline mode

flyboarder14:12:50

It wasn't designed for offline first usage

onetom15:12:37

they have offline mode support since may 2015 https://firebase.googleblog.com/2015/05/announcing-mobile-offline-support_93.html they went as far as saying: > Built from the Beginning for Offline

onetom15:12:01

but what i really meant is a solution for local development and for automated integration testing. the guy who wrote firebase-server actually wrote it to speed up his test suite by 40%. https://firebase.googleblog.com/2015/04/end-to-end-testing-with-firebase-server_16.html

onetom15:12:42

ok, i see the latest github issue is exactly this question: https://github.com/urish/firebase-server/issues/69

onetom15:12:54

it's a bit scary for me not being able to dev offline... 😕 even for the whole google app engine, google provided an api compatible locally runnable solution... aws provides local dynamo db too. they don't provide local sqs or s3, but luckily there are open source solutions for that too.

flyboarder16:12:51

@onetom: since firebase was a separate company before, I don't think it will ever get a local version unless it's open sourced

flyboarder16:12:08

@onetom: what are you evaluating firebase for? Have you looked into parse server? Or feathers.js?

flyboarder16:12:44

After building the last version of our prototype with firebase we moved to feathers for the production version current underway

jjttjj16:12:31

somehow when i fire up boot dev on my project, for one of my hoplon pages it's insisting on serving up an old version of the page. despite numerous boot restarts. When i alter the file and save again, boot-reload re-compiles everything correctly and everything is correct. but then when i refresh the page it's back to the old version. somehow an old .html.js file seems to be sticking around. Does this sound familiar to anyone?

onetom16:12:47

@flyboarder no, i havent even heard about feathers.js. parse as i remember was closed down or something, no?

onetom16:12:57

im looking for some good authentication solution actually

onetom16:12:21

i tried auth0 before but i was not satisfied with them at the end

onetom16:12:49

stormpath seems like another potential one but they are not very developer friendly

onetom16:12:05

plus im not very stoked about managing a python solution

jjttjj16:12:25

@onetom I haven't tried it at all yet but I have a vague thought to give Amazon Cognito (their user auth service) a try eventually. Is that one on your radar?

onetom16:12:03

yes, but cognito is quite complicated, that's why im looking into alternatives

flyboarder16:12:09

@onetom: that was also my main concern I would suggest feathers

flyboarder16:12:25

Parse went OpenSource and closed the hosted company

flyboarder16:12:02

I'm working on a complete cljs framework for feathers.js called featherscript

onetom16:12:01

@jjttjj in the past ~3 years im managing infrastructures with cloudformation, so im rather familiar with aws but it feels a bit too low-level for a lot of use cases.

onetom17:12:53

@flyboarder thanks! i will dig into it very soon. is there any reason then to still use firebase instead of feathers?

flyboarder17:12:12

If you want better mobile platform integration, firebase has crash reports for android iOS, the feathers mobile clients are a little behind right now

flyboarder17:12:08

@onetom: here are the features and the supported platform for firebase https://firebase.google.com/docs/

flyboarder17:12:45

Everything under grow and earn are mobile (iOS / android) only

flyboarder17:12:17

I wanted auth and db on cljs, feathers let's me build everything in cljs from there, I also really like how the client mirrors the server

onetom17:12:10

how do u do cljs backend?

onetom17:12:34

with that node or npm boot task or what was that?

flyboarder17:12:51

@onetom: right now, I'm using electron as my app is cross platform but I'll be using the boot-nodejs task for the demo app I'm building for ClojureRemote

onetom17:12:28

boot-nodejs? not boot-npm?

onetom17:12:54

google hasn't found anything on boot-nodejs

flyboarder18:12:53

I need to do some updates to it now that the new boot-cljs includes my edn generator

flyboarder18:12:09

Ugh so much to document lol