untangled

NEW CHANNEL: #fulcro
pedroteixeira 2017-06-17T00:01:35.654663Z

hi @tony.kay, I was browsing the dev guide from master [awkay/untangled] and noticed something odd in /guide.html#!/untangled_devguide.L_Internationalization:

Unknown app state mutation. Have you required the file with your mutations?:
ui/change-locale 
when trying to click on the buttons 👇

tony.kay 2017-06-17T00:04:29.671510Z

um…try develop

tony.kay 2017-06-17T00:04:32.671841Z

I thought I fixed that

tony.kay 2017-06-17T00:04:37.672315Z

the mutation name changed namespaces

tony.kay 2017-06-17T00:05:41.678509Z

I went ahead and merged develop. technically I use master for releases, but I haven’t done one yet from this repo. develop is what I’m working on

tony.kay 2017-06-17T00:05:45.678882Z

@pedroteixeira

tony.kay 2017-06-17T00:06:16.681780Z

it is fixed in both now

👍 1
tony.kay 2017-06-17T00:06:21.682159Z

thanks for looking 🙂

pedroteixeira 2017-06-17T00:07:22.687642Z

ok, thanks! will test from develop then. I've been prototyping with Om.Next and Untagled the past few weeks - I guess I had to struggle myself a bit with recursive parsing first, but I will probably just stick with Untangled 🙂 I better appreaciate some of the design decisions now

pedroteixeira 2017-06-17T00:09:10.697450Z

thanks for all the work. specially upgrading the cljs dependencies now

tony.kay 2017-06-17T00:09:23.698685Z

Yeah, it is good to understand the base library. It is one of the struggles of adoption. I’m concerned that ppl will think Om Next too hard, then not even look at Untangled.

tony.kay 2017-06-17T00:09:52.701275Z

but the combo of Om Next’s concepts with some good concrete decisions is pretty nice

tony.kay 2017-06-17T00:10:26.704317Z

Any cheerleading you can do on #om is nice 😉 I try not to do too much of that.

pedroteixeira 2017-06-17T00:10:27.704365Z

I really wanted to use the idea of routing to remote on the parser, but still was not very happy with overall complexity - even trying to leverage specter, etc

tony.kay 2017-06-17T00:11:23.709296Z

Yeah, that was my problem with the parser concept as well. In theory it is great. In practice, not as much.

pedroteixeira 2017-06-17T00:11:52.711843Z

right now, I ended up using a webworker as a remote with datascript, and the normalized db state in the main thread ui.. but still not sure about the architecture, I have a deadline in the next couple months, will let you know about progress

tony.kay 2017-06-17T00:12:15.713872Z

The load stuff is pretty much what you end up writing in your own parser…do a mutation to set a marker so that your parser knows to ask for it…but lots of indirect paths to trace when it goes wrong.

tony.kay 2017-06-17T00:13:03.718268Z

why datascript? Needing to do complex queries on the client?

pedroteixeira 2017-06-17T00:13:32.720698Z

yes, because my backend is python, going to end up doing most of logic in the webworker, backend is mainly persistence

tony.kay 2017-06-17T00:13:57.722831Z

so you’re kinda kicking all the data to the client, and eliminating most remoting?

pedroteixeira 2017-06-17T00:15:20.730136Z

yes.. because there are some requirements for the web app to work offline, so most things will work with local storage, then sync to server

tony.kay 2017-06-17T00:15:35.731503Z

cool

pedroteixeira 2017-06-17T00:15:35.731554Z

the actual http remote is very simple, just some persistence of facts/tuples (and hability to get deltas)

tony.kay 2017-06-17T00:15:51.733200Z

so your untangled networking really just talks to your local datascript db?

pedroteixeira 2017-06-17T00:16:24.736251Z

yes, I was really happy to see your example with rest network 🙂 it came really handy for me as an example

tony.kay 2017-06-17T00:16:36.737241Z

cool! I was just about to suggest that 🙂

tony.kay 2017-06-17T00:17:04.739467Z

it’s actually even easier than that. See the MockNetwork I use in some parts of the devguide

tony.kay 2017-06-17T00:17:42.742674Z

src/cards/untangled/client/load_cards.cljs

tony.kay 2017-06-17T00:17:55.743859Z

is a decent example , I think

tony.kay 2017-06-17T00:18:08.744918Z

then again, that’s probably all you’re doing

pedroteixeira 2017-06-17T00:18:15.745490Z

hm, ok - didn't see it before.

tony.kay 2017-06-17T00:18:58.749201Z

It’s just what I say in REST, but without any networking

tony.kay 2017-06-17T00:19:08.750109Z

I do that when I want to demo full-stack without writing a server

tony.kay 2017-06-17T00:19:36.752410Z

also nice for playing with a component or app that normally talks to a remote in a devcard, without needing the real server.

tony.kay 2017-06-17T00:21:09.760352Z

This one hooks up to a multimethod: https://github.com/awkay/untangled/blob/develop/src/devguide/untangled_devguide/A_Quick_Tour.cljs#L129

tony.kay 2017-06-17T00:21:29.761905Z

with a full-blown parser

tony.kay 2017-06-17T00:22:31.767208Z

I still need to update the docs, but the getting started guide shows a new untangled parser for the server that has 3 macros for writing server-side stuff. Makes client/server things like defmutation look identical

tony.kay 2017-06-17T00:22:41.768083Z

Not in the devguide yet

tony.kay 2017-06-17T00:23:05.770280Z

anyway…feel free to ask questions. I’m hacking like mad on various things trying to get to a nice 1.0 release

👍 3
tony.kay 2017-06-17T00:25:15.780583Z

(just noticed that the stats are i’ve added 6k lines in the past week…mostly bootstrap and docs)

2017-06-17T11:53:55.732149Z

I’m still looking on how to get access to app state from the UntangledNetwork/send, still no success. To recap: looking at https://github.com/awkay/untangled-getting-started/blob/master/src/main/app/rest.cljs#L73 , I assume that (assoc this :complete-app app) in start means I can then use complete-app in send to get reconciler first, then state. However, that does not work, complete-app is nil in send. And while my Clojure- and defrecord-fu is rather weak, that makes sense for me, becase initialize https://github.com/awkay/untangled/blob/develop/src/main/untangled/client/core.cljc#L139 calls start just for the side effect and throws the return value away.

2017-06-17T11:55:02.735116Z

Am I missing something here? Or is there a bug in initialize and it should collect stuff returned from start(s)? @tony.kay, please?

claudiu 2017-06-17T14:19:04.177066Z

@bbktsk What do you get in send ?

2017-06-17T14:21:39.185377Z

@claudiu (prn complete-app) at the beginning of send prints just nil.

claudiu 2017-06-17T14:22:23.187713Z

yep, but if there is a reconciler in the params you can get the state from it

2017-06-17T14:24:08.193516Z

send‘s signature is (send [this edn ok-fn error-fn] - this is UntangledNetwork, edn is the query, ok-fn and error-fn are callbacks, no reconciler there.

claudiu 2017-06-17T14:39:29.247170Z

ooh

tony.kay 2017-06-17T15:28:30.422633Z

@bbktsk you do not have access to the app State in send. Technically at this level of om next, you don't even know the database format. What you have is a call back that is essentially merge. It takes two arguments. The tree of data, and query to help merge that data and normalize it.

2017-06-17T15:52:34.510304Z

@tony.kay My problem is this: I need to load some additional data to an entity that is already in the local database. I create a remote mutation, call df/load-action with ident and class of that entity, in send request the data from a legacy REST api, receive the result. So far, so good. But, to correctly parse the result and pass it to the callback to have it merged, I need other data from that entity, not just the ident. So I was planning to just look into local state and grab the entire entity using its ident. But now I am a little bit lost… any advice, please?

tony.kay 2017-06-17T15:54:17.516777Z

“to parse the result I need other data”

tony.kay 2017-06-17T15:54:21.517093Z

why?

tony.kay 2017-06-17T15:59:11.535474Z

and have you read the section “Data Merge” in devguide section H_Server_Interactions

2017-06-17T15:59:29.536675Z

Sub-items in the response do not have correct keys, or, have “keys” that need to be fixed using data already in the database.

tony.kay 2017-06-17T16:00:18.541133Z

keys? Those should just be renamed with set/rename-keys. They are stable things, not data.

tony.kay 2017-06-17T16:00:48.543542Z

perhaps a short example?

tony.kay 2017-06-17T16:14:56.597551Z

Go ahead with the example, but I can say this: since you’re using Untangled, there is no need to be an Om purist here. If you’ve saved your app off in an atom, you can pull the app state from the app via that global.

2017-06-17T16:17:05.606331Z

Each Object has several SubObjects with Id, Name and ExtraData. I have defui-ed components for both Object and SubObject, use Id for the SubObject’s ident . Initial query that loads Objects also loads all SubObjects, however, it loads only Id and Name for these. The REST API for ExtraData is at Object level, i.e. I call GET "/api/Object/123/extra-data" and receive ExtraData for all SubObjects, but the response is a vector of [Name ExtraData] pairs. I.e. instead of using Id to identify ExtraData, the server use Name. Using Name as ident might probably work, but it feels quite ugly for a number of reasons (`Name` are not unique among all SubObjects so I’d have to unique-fy them, it would complicate other things and it just feels wrong 😎 )

2017-06-17T16:18:43.612230Z

@tony.kay I may end-up doing that, it’s just that by looking at the legacy api example, I thought that’s the idea behind current-app in UntangledNetwork/start. If not, what’s the point of that?

tony.kay 2017-06-17T16:21:53.623791Z

To be honest, I do not remember why the complete app is passed to networking. It could be we were thinking someone writing their own networking might need to access the app, but the default networking does not. I think that might be the case…might have been added to support websockets. Om defines the interaction with send

tony.kay 2017-06-17T16:22:28.626080Z

So, you say “name”…what about the object type? How are you going to write queries in the UI for these things if you don’t know what keys they have in advance?

tony.kay 2017-06-17T16:22:41.626792Z

or are you treating them as blobs of data?

tony.kay 2017-06-17T16:28:24.646939Z

Oh…duh. I just realized that you were pointing out a bug earlier: that current-app is there, but it doens’t work. Added issue: https://github.com/awkay/untangled/issues/1

2017-06-17T16:28:37.647595Z

I’m not sure I follow here. I know that Object has SubObjects, each SubObject had Id (number), Name (string) and ExtraData (string or nil when not loaded) . (actually, ExtraData is a couple of other things, but that’s not the point here)

tony.kay 2017-06-17T16:28:50.648347Z

you are writing your own networking 😊

tony.kay 2017-06-17T16:29:09.649467Z

ExtraData being other things is my point 😉

tony.kay 2017-06-17T16:29:25.650578Z

you cannot merge it successfully if the query doesn’t say what could be there

2017-06-17T16:29:43.651678Z

Trying to write 😎

✅ 1
2017-06-17T16:31:19.658075Z

I mean, in my case it is not single ExtraData but Value and Mode, both strings. The point is, I know what’s there, even the key is there, it is just set to nil until the follow-up load.

tony.kay 2017-06-17T16:33:43.666475Z

Can you paste an example REST response?

2017-06-17T16:50:30.726190Z

Example of follow-up request for one Object, these are some attributes belonging to it: {"ProtectionEnabled" ["true" "rw"], "Status" ["ok" "ro"]} So, it’s a map keyed by the name (that I have in local db already, but not as an ident), each value is a vector of new values. So apart from some massaging, I need to translate names (keys of this map) to ids …

tony.kay 2017-06-17T16:53:28.736938Z

So, a couple of possible approaches. If the data isn’t paricularly “deep”, then you could skip normalizing it and just treat it as a “bag of data” under a single prop in the database. E.g. the query could join an ident on a prop [ { ident [:object] } ] and merge the tree { ident {:object anything} } where anything just won’t be further normalized.

tony.kay 2017-06-17T16:54:51.741839Z

the other option I was thinking of had to do with a union query…which is what they are for: when a response can have any number of different types at a location.

tony.kay 2017-06-17T16:55:27.744048Z

then normalization can put the different kinds of things in different tables

2017-06-17T17:19:21.833826Z

I am not sure I understand here. Or maybe I’m just bad at explaining what the problem is 8-) I will think about it for some time and if I do not figure it out, I will create a complete working faked example of what the problem is. But thanks anyway for your time!

tony.kay 2017-06-17T17:33:20.884964Z

sure

2017-06-17T20:28:32.485710Z

@tony.kay Ok, so here’s the example of my problem, as minimal as I could make it:

2017-06-17T20:29:46.489410Z

(hmm… Slack asked me to import it. That would probably make big wall of text here, right? Is it a good etiquette to do that?)

2017-06-17T20:31:28.495030Z

The core is in the FakeRestRemote record. Note that as it is, it works flawlessly because the faked responses from the rest api are “good”. The equivalent of the response I am receiving in the real world is commented out.

pedroteixeira 2017-06-17T21:03:40.597082Z

@tony.kay just something I noticed: when testing with :networking (untangled.client.network/mock-network), it seems that only the first remote send gets executed (i.e. just the first log msg appears). For custom remotes, I had to define (serialize-requests? [this] false) (in untangled/master) as work around