Fork me on GitHub
#untangled
<
2016-06-15
>
ethangracer17:06:55

released untangled server 0.6.0 β€” this is a breaking change release, see complete changelog in the repo

ethangracer17:06:21

some of the changelog: - :authorized-routes => :unsecured-routes - should be a bidi route map to :ok handlers (enforced on system start) - top level files are always unsecured - root route "/" is also always unsecured - to unsecure a whole sub-route (eg: the js folder) use bidi's catch-all routes, eg: {"/js" {true :ok}} - Open id mock will now deal with multiple users. "user" can be passed as a query param to the open id mock endpoint. - Fixing heisenbugs wrt datomic not sorting & protocol-testing randomly failing - Adding invalid-token-handler to the :openid config - Takes a request whenever an invalid token is passed to a secured-route (ie: not an unsecured-route) and should return whether the request should be allowed to flow through the handler stack (defaults to false)

mahinshaw17:06:19

@ethangracer: Is that on clojars?

ethangracer17:06:38

good point, probably not yet, will need @tony.kay to do that

ethangracer17:06:47

unless someone else has access

mahinshaw17:06:01

I don’t think so

jasonjckn18:06:34

(defui B

    static IQuery
    (query [this]
      `[:which-tab
        {[:link-a :global] ~(get-query A)}])

    static Constructor
    (initial-state [_ _]
      {:which-tab :messages})
    )

jasonjckn18:06:08

Is there a way to to initialize state of A here, or just use merge-state! ?

tony.kay19:06:06

0.6.0 server on clojars

tony.kay19:06:44

@jasonjckn: If it is a root level thing, compose it into root component state

tony.kay19:06:58

it doesn't "belong" to B

tony.kay19:06:02

B just uses it

tony.kay19:06:41

it doens't really belong to Root either...but I see no problem with putting it there

adambrosio19:06:19

@mahinshaw: should probably elaborate on how to upgrade to use your change of [:openid :sub] to [:openid :users] in the config

mahinshaw19:06:35

@adambros: I was hoping that you would do that πŸ™‚

tony.kay19:06:46

@jasonjckn: Actually, since there is no query to normalize that global thing (which could be nested), it does make more sense to use merge-state! in the started-callback of the app construction.

jasonjckn19:06:12

hm, ok, that's what you recommended in tabbed example

tony.kay19:06:30

yeah, just in the middle of several things...not thinking clearly

jasonjckn19:06:44

no sweat, appreciate the advice

tony.kay19:06:19

If it's a singleton that you query with a link like [:thing '_] then it'd be ok to put it in Root (assuming that it had no nested content that needed normalization)

tony.kay19:06:44

But because of those restrictions, you're probably better off just merging the state in at startup if it meets the "global singleton" criteria

tony.kay19:06:35

since the merge function will normalize it and such

tony.kay19:06:17

I'm expanding the merge-state internals a bit soon. At the moment it isn't compliant with how it should work in corner cases...e.g. I'm not doing the mark/sweep step and merging with something that might pre-exist

jasonjckn19:06:27

i'm trying to convert that example now to use the auto normalization ,

jasonjckn19:06:47

static IQuery
    (query [this]
      `[:which-tab
        {[:link-a :global] ~(get-query A)}]) to  
  static IQuery
    (query [this]
      `[:which-tab
        {:link-a ~(get-query A)})

tony.kay19:06:44

oh, well, at that point it isn't top-level state anymore, and can go in your cnostructor

tony.kay19:06:07

also note you really don't need the syntax quote

tony.kay19:06:19

most queries don't need quoting at all

jasonjckn19:06:43

i'll keep that in mind, i'm trying to keep the syntax as regular as possible for my team

jasonjckn19:06:50

to us all these clojure things are intuitive

tony.kay19:06:02

erm, they're going to have to understand quoting...might as well bite the bullet

jasonjckn19:06:17

well if I can make all queries without quotes i'll do that

jasonjckn19:06:23

i just want it regular

tony.kay19:06:44

In Untangled you don't use query parameters or mutations in queries. You should not need quoting at all

tony.kay19:06:50

which simplifies things quite a bit

tony.kay19:06:56

mutations: those need quoting

jasonjckn19:06:58

you do need them in mutations

tony.kay19:06:21

unless you want to write [(list 'app/a)]

tony.kay19:06:34

which you could alias to invoke

tony.kay19:06:46

[(invoke 'app/a)]

jasonjckn19:06:50

that would make it easier for them

tony.kay19:06:51

then you don't need to teach unquote

jasonjckn19:06:56

:onSelect #(transact! T [(! app/choose-tab {:tab (keyword %)}) :ui/react-key])}

jasonjckn20:06:04

(defmacro ! [action-name & params]
  {:pre [(symbol? action-name)]}
  `(list (quote ~action-name) ~@params))

jasonjckn20:06:37

excellent, no more quote education πŸ™‚

jasonjckn20:06:29

before you comment on :ui/react-key, it's on my todo list to remove it πŸ˜‰

adambrosio20:06:08

can you have multiple params? eg: [(app/a :foo :bar)]

noonian20:06:56

afaik params have to be a map, so just just add more keys if need more data e.g. [(app/a {:foo β€œfoo”, :bar β€œbar”})]

adambrosio20:06:48

right so that ! macro should be

(defmacro ! [action-name params]
  {:pre [(symbol? action-name)]}
  `(list (quote ~action-name) ~params))

jasonjckn21:06:57

there's some bug in merge-state! or i'm using it wrong

jasonjckn21:06:18

(defui B
    static om/Ident
    (ident [_ _] [:link-b :global])
    static om/IQuery
    (query [this] [:title])
    static Constructor
    (initial-state [_ _] {:title "foo"}))

(defui A
    static om/IQuery
    (query [this] [{:b (om/get-query B)}])
    static Constructor
    (initial-state [_ _] {:b (initial-state B nil)}))

(defui D
    static om/IQuery
    (query [this] [:some-data])
    static Constructor
    (initial-state [_ _] {:some-data 3}))

(defui TabUnion2
    static om/Ident
    (ident [_ _] [:link-a :global])
    static om/IQuery
    (query [this] {:link-a (om/get-query A)
                   :link-d (om/get-query D)})
    static Constructor
    (initial-state [_ _] (initial-state A nil)))

jasonjckn21:06:05

so if I don't call merge state I get the following global state

jasonjckn21:06:27

:current-tab2 [:link-a :global],  :link-b {:global {:title "foo"}},
 :link-a {:global {:b [:link-b :global]}}},  :search-results2 {:global {:page-size 10, :type "message"}}

jasonjckn21:06:35

all this is expected

tony.kay21:06:44

your union cannot possibly work right the way you've written it

tony.kay21:06:53

you're ident function has to reutnr the right ident for the thing in state

tony.kay21:06:26

which means you have to add state to A and D to distinguish them programatically

jasonjckn21:06:40

i was trying to simplify the code that was having an issue, the original code had a proper ident

jasonjckn21:06:52

i'll fix that, see if I can still reproduce in a smaller example

jasonjckn21:06:00

ok it still reproduces

(defui B
    static om/Ident
    (ident [_ _] [:link-b :global])
    static om/IQuery
    (query [this] [:title])
    static Constructor
    (initial-state [_ _] {:title "foo"}))

(defui A
    static om/IQuery
    (query [this] [{:b (om/get-query B)}])
    static Constructor
    (initial-state [_ _] {:link-type :link-a
                          :b (initial-state B nil)}))

(defui D
    static om/IQuery
    (query [this] [:some-data])
    static Constructor
    (initial-state [_ _] {:link-type :link-d
                          :some-data 3}))

(defui TabUnion2
    static om/Ident
    (ident [_ {:keys [link-type]}] [link-type :global])
    static om/IQuery
    (query [this] {:link-a (om/get-query A)
                   :link-d (om/get-query D)})
    static Constructor
    (initial-state [_ _] (initial-state A nil)))
here's the initial state
:link-a {:global {:link-type :link-a, :b [:link-b :global]}},
 :link-d {:global {:link-type :link-d, :b {:title "foo"}, :some-data 3}},
 :current-tab2 [:link-a :global],
 :link-b {:global {:title "foo"}}}
in my core.cljs i have
(uc/merge-state! app ui/TabUnion2 (uc/initial-state ui/D nil))

jasonjckn21:06:31

some how :link-d contains denormalized data about B even though D never mentions B anywhere

tony.kay21:06:53

is that merge done in started-callback?

tony.kay21:06:27

makes no sense...possibly something else in your app you're not showing?

jasonjckn21:06:52

yah i mean there's other code around, i can try to reduce it to a simple git repo for you

tony.kay21:06:15

So, I'm working on merge-state right now. I'll keep an eye out

tony.kay21:06:31

The code you're showing is very close to my example, which works perfectly

tony.kay21:06:50

so I cannot see how mine could work and yours not, unless you've got something somewhere else messing it up

jasonjckn21:06:41

@tony.kay: still reproduces it

tony.kay21:06:41

thanks...I'll take a look in a bit...working on this function at the moment

jasonjckn21:06:46

kk, brb lunch break

jasonjckn22:06:05

you merge inintial state of TabUnion2 with D's object data

tony.kay22:06:33

TabUnion2 has no representation in state. It is either A or D

tony.kay22:06:59

it is a switch that has no rep of it's own

jasonjckn22:06:07

(uc/merge-state! app ui/TabUnion2 (uc/initial-state ui/D nil)) ui/TabUnion2 is bound to parameter component, who's initial state is read into let binding empty-object

jasonjckn22:06:19

empty-object is merged with object-data at L133

tony.kay22:06:52

yeah, let me look at that...that's part of the thing I'm rewriting

tony.kay22:06:33

but you're right, that logic isn't right for unions...but it wasn't right in general either πŸ˜‰

jasonjckn22:06:04

cool, glad we're on the same page

tony.kay23:06:57

Pushed untangled spec 0.3.7. Fixes rendering issues that started with latest React and Om

tony.kay23:06:08

specifically, diffs were not working right

tony.kay23:06:28

@jasonjckn: Pushed untangled client 0.5.3-SNAPSHOT to clojars with the work in progress. I'm done for the day, and the new version is "more correct", and mostly tested. I put a union fix in, but that's the bit I have not yet tested

jasonjckn23:06:50

much appreciated

tony.kay23:06:52

I expanded the API so that one can access the ident integration code as a stand-alone function

tony.kay23:06:07

and can do appends/prepends/replace as many times as you want (maybe I already had that)

tony.kay23:06:22

Also does dupe checking on vectors, and mark-and-sweep

tony.kay23:06:33

(of missing data)

jasonjckn23:06:49

it's doing garbage collection?

jasonjckn23:06:55

not sure what you mean by mark and sweep

tony.kay23:06:14

it's an underdocumented, but important, feature of Untangled merge

tony.kay23:06:27

I talk about it in at least one talk and the tutorial

jasonjckn23:06:54

which tutorial?

tony.kay23:06:00

The Untangled Tutorial

jasonjckn23:06:03

ok i'll check it out

tony.kay23:06:59

The bit about data merge

jasonjckn23:06:00

oh btw if it wasn't clear we're moving ahead with untangled for our app πŸ™‚

tony.kay23:06:35

The data merge stuff uses a mark-and-sweep algorithm to implement the behavior of data merge descritbe in that tutorial page

tony.kay23:06:52

The merge-state! function adopts that as well to ensure consistency...that's the bit I forgot on the first pass

jasonjckn23:06:08

ok, excellent

jasonjckn23:06:51

the data merging looks super useful

jasonjckn23:06:03

i've used it a tiny bit so far, and it's great

jasonjckn23:06:12

I was also considering posh & datascript

jasonjckn23:06:19

but so much boilerplate around maitaining that and merging

tony.kay23:06:42

The new merge function is really mostly targeted at server push and startup. That's part of the reason I split out the ident integration code as a utility function.

tony.kay23:06:09

Responses from teh server are already merged properly (except for peppering about the idents)

jasonjckn23:06:11

kk, potentially we'll be doing server push in v2

tony.kay23:06:26

I may split it out a bit more...at present the ident editing requires a reconciler, which isn't right

tony.kay23:06:28

for use in mutations

tony.kay23:06:41

So probably need two versions

tony.kay23:06:56

The one I wanted here queues re-renders, since on server push you'll want that

tony.kay23:06:41

So, still a bit more cleanup to do before releasing as an official part of the API

jasonjckn23:06:34

cool, i'm going to handle all the difficult parts and compatibility changes for the app, just need to get people productive with render functions, and simpler parts

tony.kay23:06:01

Nice thing is: there aren't many non-simple parts πŸ™‚

jasonjckn23:06:44

yah and, they're already react/javascript engineers, and om.next/untangled doesn't try to abstract react

jasonjckn23:06:47

like reagent does

tony.kay23:06:58

nice for you

tony.kay23:06:33

I think the constructor addition really cleans things up quite a bit. Our devs are really happy with the improvement

jasonjckn23:06:57

yah i got rid of passing in hand normalized data, so far so good

jasonjckn23:06:29

i like it, would be interesting if I never had to called merge-state! for example with TabUnion, but i can't think of any better designs

tony.kay23:06:47

I can, but I'm not sure it's fully general

tony.kay23:06:55

there's a to-many and to-one case

tony.kay23:06:58

for unions: to one

tony.kay23:06:05

for hetero lists: to many

tony.kay23:06:23

Not had time to think it through

jasonjckn23:06:04

"Constructor" is going to confuse java/javascript people

tony.kay23:06:06

It probably makes sense to require the constructor to return a map of data

tony.kay23:06:25

oh right...might not be the best name

tony.kay23:06:28

I'm open to suggestions

tony.kay23:06:33

InitialState?

jasonjckn23:06:38

that's definitely better

jasonjckn23:06:47

i'll let you know if I come up with something