Fork me on GitHub
#untangled
<
2016-06-13
>
juno16:06:16

Hello. First of all, I would like to thank everyone for making this awesome framework available. I’m currently prototyping an app for a startup and committed to using untangled for our project. For past few days, I’ve been stuck with getting the nested tab interface working. I using the tabbed-interface cookbook recipe and trying to embedded another tabs component in the one of the tab. The query returns the following data Root {:current-tab {:which-tab :main, :main-content Main tab, :current-inner-tab {}}}. What I’m expecting is that the :current-inner-tab will be populated with the inner tab union component query and it’s not working. Here is the gist for it https://gist.github.com/jichon/1bf901b95a9d0562900e816ce4cd95f7. Help would be greatly appreciated. Thank you.

cjmurphy17:06:14

Would you describe your problem as when switching from one tab to another you want the panel below the tab to show?

cjmurphy17:06:43

In the cookbook recipe it just loads data from some URL iirc. Instead you want to show a local component that is backed by local data?

juno17:06:45

When I switch b/w the top level tabs I’m getting Root {:current-tab {:which-tab :main, :main-content Main tab, :current-inner-tab {:tab-data-query {:text This is a value from the server}}}} and inner tabs are not getting rendered

cjmurphy17:06:18

I found that I needed to have a mutation that gets called whenever the user changes tabs. This mutation changes app state so that what is supposed to be under the tab is in fact there.

juno17:06:15

Thank you. for the quick response. Let me give that a shot.

cjmurphy17:06:39

I was thinking of submitting a cookbook recipe request for this, as it wasn't that easy to work out in the first place.

juno17:06:32

that would be awesome. I’m a noobie to om.next and untangled. If you have time to provide that that would be really helpful

cjmurphy17:06:58

For now I'll just put up a gist.

juno17:06:33

sweet. I’ve should of talk to you guys when I had this issue. I’ve spent few days chasing a wild goose 😃

cjmurphy17:06:46

I'm not sure this will help. A proper cookbook thing will be a lot better and a lot simpler. st/GasQueryGrid - that's actually a number!

juno17:06:56

ok i’ll play with the gist. Thank you again

cjmurphy17:06:52

This is how it is called: `(defn change-tab-mutation [component which-tab-kw] (om/transact! component [(nav/load-tab {:target ~which-tab-kw})]))

juno17:06:35

I guess with this approach, it can’t utilize the union query to have the inner tabs component decide which to render based on the ident

jasonjckn18:06:38

@tony.kay: passing the same parameter twice doesn't get the output I was looking for. I guess om works like this intentially, but i was expecting the last example to work by giving output

[{:foo 3}]
, example set
;; singletons work whether ident or not
(om/db->tree `[:foo] [:link 1] {:link {1 {:foo 3}}}) => {:foo 3}
(om/db->tree `[:foo] {:foo 3} {}) => {:foo 3}

;; lists work only in ident
(om/db->tree `[:foo] [[:link 1]] {:link {1 {:foo 3}}}) => [{:foo 3}]
(om/db->tree `[:foo] [{:foo 3}] {}) => [{}]

tony.kay18:06:59

(om.next/db->tree [:foo] {:foo 2} {:foo 2})

jasonjckn18:06:19

yah that's the singleton case

jasonjckn18:06:25

i'm trying to do lists in the 2nd set

jasonjckn18:06:46

(om/db->tree `[:foo] [{:foo 3} {:foo 4}] {}) => [{} {}]

jasonjckn18:06:54

that output seems garbage [{} {}]

tony.kay18:06:04

oh, I think there is an open issue in Om that data must be normalized for this query to work right...

jasonjckn18:06:16

yah it works when normalized

jasonjckn18:06:25

that's great there's an issue for it

jasonjckn18:06:53

i thought it might have been intentional because it's not in database format

tony.kay18:06:23

Yeah, it is sometimes hard to tell, because the Om docs don't explicitly say what they should do in all cases

tony.kay18:06:21

the joys of alpha 😉

anmonteiro18:06:13

@jasonjckn: actually the docs are clear for db->tree

anmonteiro18:06:18

"Given a query, some data in the default database format, and the entire
   application state in the default database format, return the tree where all
   ident links have been replaced with their original node values.”

anmonteiro18:06:31

it does mention the default database format twice 🙂

jasonjckn18:06:51

nods yah i'm actually surprised there's an issue for it

jasonjckn18:06:56

but glad there is one..

anmonteiro18:06:57

we opened that issue exclusively for tracking

jasonjckn18:06:03

because the semantics are clear for sure

anmonteiro18:06:07

It’s not clear if that’s going to be fixed or not

anmonteiro18:06:16

or if it even deserves to be fixed

tony.kay18:06:42

@anmonteiro: it is an interesting question. The default database format does not require that everything be normalized, per se

tony.kay18:06:54

unless you define it that way...Ident is not a required interface on UI

anmonteiro18:06:07

yeah, that’s why we opened the issue

jasonjckn18:06:18

i think my 4 examples illustrate that you already support unnormalized singletons and I see a lot of om.next code using singletons

anmonteiro18:06:36

it’s also not clear if: 1) we should support both cases in db->tree 2) that we can even distinguish between them

tony.kay18:06:54

To me, if (2) then (1)

anmonteiro18:06:05

@jasonjckn: but singletons are already normalized 🙂

anmonteiro18:06:18

because there’s only one of them

anmonteiro18:06:33

@tony.kay: the question is also one of performance

jasonjckn18:06:37

my use case is a subquery that's passed onto the remote backend, `[{:search-results [:name :address]}] i don't want to normalize the search results because they're so ephemeral and giving identity to a particular search result is difficult

jasonjckn18:06:58

so I could have an opaque query `[:search-results] but I wanted to communicate to the backend what data I needed

anmonteiro18:06:01

if we allow for state not to be fully normalized, then people won’t bother normalizing and apps will be slow as hell

anmonteiro18:06:25

@jasonjckn: do you even need to call db->tree then?

tony.kay18:06:27

ah, but optimization should be something they can do...not something we enforce. It doesn't affect correctness

jasonjckn18:06:45

@anmonteiro: i'm using untangled so I can't write a read parser

tony.kay18:06:11

I'm not even sure I agree with your assessment that they'd be slow. why would that be? It is still just map traversal

tony.kay18:06:44

they would often be incorrect, in that if you leave it as a tree, you cannot share data across the UI

tony.kay18:06:05

but that would be a self-correcting problem: they would normalize it to get it to work

tony.kay18:06:46

traversing idents seems technically the slower route to me (it adds one more loop to the recursion, along with conditional logic to find out if there is an ident)

tony.kay18:06:06

on mutations: ok, maybe you're mucking with a deeper data structure, but those happen on a low-frequency time-scale in general, and updating a tree really isn't that much different on these small operations. So, again, I can argue you want normalization for correctness and ease of re-rendering shared data...but I have trouble seeing why we care if they choose to leave some blob of unshared data denormalized.

tony.kay18:06:33

shouldComponentUpdate will still short-circuit based on reference compares...

tony.kay18:06:04

yeah, not seeing the reason...other than the case you mentioned of not being able to detect if a 2-tuple vector is an ident...that is a challenge...or is that even the case that's hard?

tony.kay18:06:16

where can one have a vector that contains a keyword but is not an ident in the db format? Oh, I guess if it is a blob of data, you might have a vector of keywords...if you tried to query that it could cause a problem.

tony.kay18:06:32

Do I follow that, or do I return it

tony.kay18:06:58

which then begs the question if idents themselves shouldn't at least have metadata markers on them

jasonjckn18:06:45

or it's own type

jasonjckn18:06:50

(Ident. :foo)
instead of
`[:foo ~'_]

jasonjckn18:06:20

or ^:ident [:foo] works

tony.kay18:06:26

I wouldn't make an API change like that...the query language need not change at all

tony.kay18:06:03

The db normalization process could just mark the idents it places in app state with metadata during the normalize process.

tony.kay18:06:25

so that vectors that represent idents are marked as they're placed in the db. Nothing changes in the public API at all.

tony.kay18:06:44

just like get-query marks query bits with the component they come from

tony.kay18:06:58

get-ident could hang metadata marking the vector as an ident

tony.kay18:06:26

all internal, no API changes. Anyone hand-normalizing initial state would have to hand-mark idents

tony.kay18:06:46

but as I've recently shown with Untangled's Constructor addition, this should never be necessary

jasonjckn18:06:11

sounds good, maybe you want to add this to the issue?

tony.kay18:06:17

(or you could call get-ident instead of manually adding it)

tony.kay18:06:58

I was trying to see if @anmonteiro wanted to discuss it more here...my intention is to see if I'm missing something before adding to the issue

tony.kay18:06:16

I seem to even remember earlier versions of db->tree working in this case...I think it regressed at some point due to other additions or expansions/realizations.

jasonjckn18:06:35

isn't EDN suppose to help with this sort of thing #guid "..." vs #ident [ ]

tony.kay18:06:37

I wrote the original tutorial, and I know it used to work for the non-normalized data.

anmonteiro18:06:41

@tony.kay: not sure if it was ever supported

anmonteiro18:06:17

re: slow apps, the problem is if you don’t normalize you lose the ability to do incremental queries

tony.kay18:06:19

Oh, I agree it may not have been intended...just saying it was confusing because it did work that way for a while

tony.kay18:06:32

you mean path optimization?

tony.kay18:06:41

starting from an ident

anmonteiro18:06:22

not only path optimization

anmonteiro18:06:28

also calling db->tree with an ident

anmonteiro18:06:44

that’s also an example of a query running incrementally

tony.kay18:06:59

Sure, I agree...but where are the definitions of "slow"? We talking s, ms, micro, nano? If I happen to leave a single blob somewhere for convenience and want to query into it, and the rest of my db is normalized, does it really hurt anything? If my app is slow because I make such a choice, then it seems I have the power to correct it. Why narrow the ability of the API?

anmonteiro18:06:06

@tony.kay: yea, we should probably do more work on it

anmonteiro18:06:39

TBH I’m not a fan of metadata in idents

tony.kay18:06:30

I have a slight bit of resistance to it as well...it does complicate the mutations.

tony.kay18:06:56

Yep. exactly

tony.kay18:06:58

but it seems like the only solution is to mark these things somehow...either metadata or a new type...both are going to break existing apps.

anmonteiro18:06:30

definitely not a fan of adding more syntax

tony.kay18:06:37

but in alpha seems to be the time to do it

anmonteiro18:06:21

@tony.kay: not sure if it’s even needed

anmonteiro18:06:45

I think it’s probably just a problem that needs to be looked at again

anmonteiro18:06:03

definitely not something like (Ident. …)

anmonteiro18:06:21

that wouldn’t be data, and queries need to be data

jasonjckn18:06:50

if the database format only limits itself to 2-3 types [] {} etc, there's only so much you can represent with this without having to start conflating different things

jasonjckn18:06:59

that's why they introduced EDN tags

tony.kay18:06:14

@anmonteiro: perhaps checking to see if the thing that looks like an ident resolves to nil?

tony.kay18:06:26

if it resolves to nil, return the ident instead of nil?

anmonteiro18:06:41

look at that, that might just work!

tony.kay18:06:03

or maybe even better...only consider it an ident if the keyword resolves to an existing table

anmonteiro18:06:28

see, several ideas, we just need to keep thinking about it 🙂

tony.kay18:06:37

that's why I wasn't touching issues yet 😉

anmonteiro18:06:40

that wouldn’t even need new metadata etc

anmonteiro18:06:16

I’m happy to work on a patch for that if you don’t have time

anmonteiro18:06:21

once we figure out a sound design

jasonjckn18:06:42

+1 ".only consider it an ident if the keyword resolves to an existing table"

tony.kay18:06:47

all you my friend..I'm unfortunately swamped 🙂

tony.kay19:06:01

in fact....gotta go. Let me know if I can help on decisions related to db->tree...I'll respond later

grzm19:06:18

I'm working on a bare bones untangled server instance to learn how it's put together. I'm not requiring taoensso.timbre anywhere in the code, so I don't have it in my project dependencies. When starting up lein repl, I get the following error:

> lein repl
Exception in thread "main" java.lang.ExceptionInInitializerError
	at clojure.main.<clinit>(main.java:20)
Caused by: java.io.FileNotFoundException: Could not locate io/aviso/exception__init.class or io/aviso/exception.clj on classpath., compiling:(taoensso/timbre.clj:1:1)
When I add com.taoensso/timbre as a dependency, the error goes away. I can run lein repl and start the server just fine. I see that navis/untangled-server (included in my project) includes com.taonesso/timbre as a dependency, so I'm confused as to why I'm seeing this error

jasonjckn19:06:29

thanks for the help tony

anmonteiro19:06:31

@tony.kay: happy to see what we discussed captured in the issue

tony.kay19:06:59

@anmonteiro: I can write that up later

anmonteiro19:06:05

no rush, thx