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 đumâŚtry develop
I thought I fixed that
the mutation name changed namespaces
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
it is fixed in both now
thanks for looking đ
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
thanks for all the work. specially upgrading the cljs dependencies now
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.
but the combo of Om Nextâs concepts with some good concrete decisions is pretty nice
Any cheerleading you can do on #om is nice đ I try not to do too much of that.
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
Yeah, that was my problem with the parser concept as well. In theory it is great. In practice, not as much.
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
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.
why datascript? Needing to do complex queries on the client?
yes, because my backend is python, going to end up doing most of logic in the webworker, backend is mainly persistence
so youâre kinda kicking all the data to the client, and eliminating most remoting?
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
cool
the actual http remote is very simple, just some persistence of facts/tuples (and hability to get deltas)
so your untangled networking really just talks to your local datascript db?
yes, I was really happy to see your example with rest network đ it came really handy for me as an example
cool! I was just about to suggest that đ
itâs actually even easier than that. See the MockNetwork I use in some parts of the devguide
src/cards/untangled/client/load_cards.cljs
is a decent example , I think
then again, thatâs probably all youâre doing
hm, ok - didn't see it before.
https://github.com/awkay/untangled/blob/develop/src/cards/untangled/client/load_cards.cljs#L13
Itâs just what I say in REST, but without any networking
I do that when I want to demo full-stack without writing a server
also nice for playing with a component or app that normally talks to a remote in a devcard, without needing the real server.
This one hooks up to a multimethod: https://github.com/awkay/untangled/blob/develop/src/devguide/untangled_devguide/A_Quick_Tour.cljs#L129
with a full-blown parser
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
Not in the devguide yet
anywayâŚfeel free to ask questions. Iâm hacking like mad on various things trying to get to a nice 1.0 release
(just noticed that the stats are iâve added 6k lines in the past weekâŚmostly bootstrap and docs)
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.
Am I missing something here? Or is there a bug in initialize
and it should collect stuff returned from start
(s)? @tony.kay, please?
@bbktsk What do you get in send
?
@claudiu (prn complete-app)
at the beginning of send
prints just nil
.
yep, but if there is a reconciler in the params you can get the state from it
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.
ooh
@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.
@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?
âto parse the result I need other dataâ
why?
and have you read the section âData Mergeâ in devguide section H_Server_Interactions
Sub-items in the response do not have correct keys, or, have âkeysâ that need to be fixed using data already in the database.
keys? Those should just be renamed with set/rename-keys
. They are stable things, not data.
perhaps a short example?
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.
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 SubObject
s, 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 SubObject
s so Iâd have to unique-fy them, it would complicate other things and it just feels wrong đ )
@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?
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
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?
or are you treating them as blobs of data?
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
Iâm not sure I follow here. I know that Object
has SubObject
s, 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)
you are writing your own networking đ
ExtraData being other things is my point đ
you cannot merge it successfully if the query doesnât say what could be there
Trying to write đ
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.
Can you paste an example REST response?
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 âŚ
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.
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.
then normalization can put the different kinds of things in different tables
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!
sure
@tony.kay Ok, so hereâs the example of my problem, as minimal as I could make it:
https://gist.github.com/bbktsk/ba527eca247c5dd5cc24321e71912af0
(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?)
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.
@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