untangled

NEW CHANNEL: #fulcro
tony.kay 2017-02-22T00:57:37.003725Z

For anyone interested ( @darrellesh @baris @torkan ) in the forms support: I just pushed an update to develop and clojars. There are now several devcards in the guide that explain form support. The Whole Form Logic page in the guide in particular has a fun example: building a form that uses remoting to check if a username is in use

πŸ‘ 2
tony.kay 2017-02-22T00:58:15.003726Z

it simulates the server in the browser, but the code is exactly as you'd write it with a real server. Just run the server stuff in a clj server instead πŸ˜‰

tony.kay 2017-02-22T00:59:04.003731Z

At this point (barring bugs and expansion of field types/validation) the forms support should be pretty usable

tony.kay 2017-02-22T00:59:34.003733Z

I think I'm done renaming things, at least

macrobartfast 2017-02-22T01:22:27.003735Z

is there anything I should know before embarking on https://awkay.github.io/om-tutorial ?

adambros 2017-02-22T01:53:55.003736Z

@tony.kay it seems like post-mutations are only used for their :action, but i need it to (maybe) trigger another remote

tony.kay 2017-02-22T03:06:01.003737Z

@adambros Hm.

tony.kay 2017-02-22T03:06:23.003738Z

@macrobartfast that the Untangled dev guide is basically that, but expanded. I have not maintained the om tutorial much. If you're going to use Untangled, then ignore it

macrobartfast 2017-02-22T03:07:31.003740Z

ah ok cool, then I'll just do the Untangled dev guide

tony.kay 2017-02-22T03:08:31.003741Z

@adambros what is the scenario sequence?

tony.kay 2017-02-22T06:41:44.003742Z

proof of concept for the image crop tool is now up in UI. needs some polish, but generally works.

kauko 2017-02-22T08:09:32.003744Z

Hmm, this could be a stupid question πŸ™‚ I understand one of the advantages of Untangled + Untangled-server + Datomic (or you know, just Om + Datomic..) is that you can use the same queries and mutations on the client and on the server. From the examples it looks like the client just sends the queries it wants to the server, and apparently the server just.. executes them? What about security? I skimmed through the tutorial and the dev guide, but couldn't find anything to answer this question.

kauko 2017-02-22T08:13:49.003745Z

I was actually thinking whether an Untangled client would work well with Vase microservices. There's a bunch of stuff that the untangled-server does, but I didn't see a reason why Vase couldn't be extended to do these things also. One problem I do see that Vase seems to be meant for creating REST APIs, whereas Untangled-server doesn't look too RESTy to me πŸ™‚

qqq 2017-02-22T08:56:00.003747Z

https://github.com/untangled-web/untangled-todomvc <-- is there a typo in the first line?

Copy resources/config/defaults.edn to /usr/local/etc/todomvc.edn.
^^ wtf why am I copying something to a blocal path?

cjmurphy 2017-02-22T09:00:57.003750Z

@qqq: That's a safety/deployment thing, so that tutorial type code never overrides production code. You will find that apart from that there isn't any low level copying around of files.

qqq 2017-02-22T09:02:05.003751Z

@cjmurphy : wait, so that's not a typo and I'm really supposed to copy the file to /usr/local/etc/todomvc.edn ?

qqq 2017-02-22T09:02:19.003752Z

how does this provide safety? it just seems very very weird

qqq 2017-02-22T09:02:34.003753Z

why is this to .a local place relative to project.clj ?

cjmurphy 2017-02-22T09:03:38.003754Z

Yes - its like a standard so nothing bad ever happens - as Untangled is a framework - it does alot, but you don't want it to do alot in the wrong place.

qqq 2017-02-22T09:03:38.003755Z

eh, copied it over, this still confuses me to no ned

qqq 2017-02-22T09:04:16.003756Z

I will reserve my criticism until I work through the tutorial; after which I"m going ot ask about this again πŸ™‚

cjmurphy 2017-02-22T09:04:32.003757Z

It is going to a standard Unix place for config of applications.

cjmurphy 2017-02-22T09:05:09.003758Z

Sure - most of the actual Untangled people are asleep at the moment.

qqq 2017-02-22T09:07:00.003759Z

oh man, this is nice

qqq 2017-02-22T09:07:08.003760Z

I think I'm already sold

qqq 2017-02-22T09:07:23.003761Z

is there any nice way to have the backend use gae or aws instead of datomic?

πŸ™‚ 1
cjmurphy 2017-02-22T09:09:15.003762Z

It is simple data structures that are passed back and forth, so you can go against s/thing other than Datomic yes. I've only written against an existing server.

kauko 2017-02-22T09:57:27.003763Z

@cjmurphy any chance you could answer my question above?

cjmurphy 2017-02-22T10:05:31.003764Z

Auth (both types) has always been a hazy subject for me with Untangled. I compare it to Sente where (IIRC) the example you follow (use as a template) has a login screen and, and uses some Auth library to help. I'm just about to go through the Cookbook recipies - there is one called server-query-security. I understand that some users have not specifically used Untangled for Auth. Its something I too am looking for leadership on...

cjmurphy 2017-02-22T10:07:43.003767Z

As far as using something that is RESTy - yes just use Untangled Client, and talk across like any web client - that's what I did - the application is really a Untangled/Sente one, which is quite close to being an Om/Sente one.

kauko 2017-02-22T10:09:53.003768Z

Yeah about the Vase thing.. I brought that up because like I said, I was looking into the possibility of using Vase and an Untangled client together. But to me it seems like an Untangled client works really well with a server that can just accept incoming queries and mutations, and Vase seems to be meant for exposing Datomic queries through a REST API

cjmurphy 2017-02-22T10:10:03.003769Z

Another way is to communicate across using Untangled/Om, then still call REST services on the server.

kauko 2017-02-22T10:10:08.003770Z

Obviously they CAN work together, but you lose some synergy.

2017-02-22T14:44:22.003775Z

@kauko you can run vase with an untangled server support. The new server module-system makes it possible to run your own web-server, middleware etc. So it’s possible to use vase with pedestral for exposing your data as a web-service to other consumers. Furthermore you can run an untangled client aside. Checkout the docs in the source code

2017-02-22T14:44:52.003778Z

The untangled client communicates at the "/api/" endpoint by default and do a lot of network plumbing stuff. You need to implement the server reads and writes.

kauko 2017-02-22T14:49:08.003779Z

So yeah, if I understand you correctly, my thinking was correct. Vase solves a different kind of problem, it doesn't really apply to Untangled. Like you said, it's good for exposing data for other consumers, but I'd probably want to have a different endpoint for my untangled client

2017-02-22T14:54:51.003780Z

For the moment - yes. Maybe in the near feature you can plug your server reads and mutations to vase.

2017-02-22T14:55:15.003781Z

Vase is also on my todo list....didn’t had the time to check it out

tony.kay 2017-02-22T16:29:57.003784Z

@kauko Security. Yes, that cookbook recipe are my musings on the subject.

tony.kay 2017-02-22T16:31:09.003785Z

Your query will always be "rooted". e.g. you're going to combine session info with the query to figure out where to start. From there you are following a graph. So, a query is allowed if: 1. The user is allowed to read the root entity of the query 2. AND there appear no keywords in the query that follow references that the user is not allowed to traverse

tony.kay 2017-02-22T16:31:41.003786Z

That is not foolproof, but the exceptions are relatively simple...there might be cases where you have to do more than just check the keywords are in a whitelist

tony.kay 2017-02-22T16:32:18.003787Z

So, you could run a post-query analysis on the graph edges that actually resolved with a permissions check function before returning it

tony.kay 2017-02-22T16:33:44.003788Z

same problem with any kind of client-based query language. Using SQL with Untangled isn't bad (we're doing it, now too). The security issue is the same: if you allow the UI to generate the query, you get great power, but you have to solve the security issue.

tony.kay 2017-02-22T16:34:05.003789Z

In practice, the algorithm I just described in 1/2 above is pretty good

kauko 2017-02-22T16:34:48.003791Z

Yeah it makes sense to me.

kauko 2017-02-22T16:35:19.003792Z

Keeping a white- or blacklist of allowed keys can be a challenge

tony.kay 2017-02-22T16:35:39.003793Z

@qqq as cjmurphy said: this is meant to be a production framework. You would not want to accidentally start a development mode config on a production server...might seed data, etc. Bad news. You CAN run without the copy, with a command line option that tells it to use an internal config...but you have to be explicit.

tony.kay 2017-02-22T16:37:41.003794Z

@kauko On synergy: You can plug in your own network object in untangled client and talk to whatever. You'd just transform the EDN to whatever request you want to make, then transform the response into the right shape. That, in fact, is what I do in a lot of the full-stack examples to simulate a server using the browser (I hook in networking that just calls js functions instead of doing networking)

tony.kay 2017-02-22T16:37:53.003795Z

So, REST is totally possible, just more work

kauko 2017-02-22T16:38:25.003796Z

Yeah, again, I didn't think that you wouldn't be able to use Untangled with any server πŸ™‚ Or talk to REST endpoints

tony.kay 2017-02-22T16:38:28.003797Z

We'll get documentation on the more modular server support in untangled-server soon.

kauko 2017-02-22T16:38:45.003798Z

That came out a bit rude, sorry

tony.kay 2017-02-22T16:38:48.003799Z

we're using it, just havent doc'd it yet

tony.kay 2017-02-22T16:38:58.003800Z

@kauko I didn't take it that way. no worries

kauko 2017-02-22T16:39:33.003801Z

πŸ‘ Thought it sounded snappy

tony.kay 2017-02-22T16:39:46.003802Z

Part of the advantage of Untangled is you get the plumbing for Om without having to write it. As soon as you go to REST you're losing half of the goodness

kauko 2017-02-22T16:39:52.003803Z

Yeah

tony.kay 2017-02-22T16:40:15.003804Z

and it's so trivial to write the server logic when you're working with EDN

tony.kay 2017-02-22T16:40:39.003805Z

so, we write REST when external clients need to hit against it with old tech, but don't hit it ourselves from our SPAs

tony.kay 2017-02-22T16:41:15.003806Z

the server-side functions are often so thin it is a waste of time to write converters to try to avoid code duplication

tony.kay 2017-02-22T16:41:36.003807Z

it's like..."let's write this REST interpreter to avoid duplicating a line of really simple code here and there"

tony.kay 2017-02-22T16:41:46.003808Z

seems like a bad tradeoff

tony.kay 2017-02-22T16:42:20.003809Z

and you can share the common query code among the endpoints...so you can still eliminate code duplication

tony.kay 2017-02-22T16:43:07.003810Z

but it is tempting to say "I already have the REST...so let's just leverage those"

tony.kay 2017-02-22T16:43:34.003811Z

That can work...you don't have to do complicated recursive queries from the UI

tony.kay 2017-02-22T16:43:54.003812Z

you can always join up the graph as a post step (post mutation) on the client

tony.kay 2017-02-22T16:44:33.003813Z

so, just query the entities (with something you can detect as the desired graph edge, like the FK value), get them in the db, them hook em together by rewriting the FK ID into idents

tony.kay 2017-02-22T16:44:37.003814Z

all sorts of options

tony.kay 2017-02-22T16:45:53.003815Z

for that matter, as long as the "graph" returned from REST can be trivially converted to EDN and normalized by Om...it really isn't that hard. Who says you have to parse the UI query? Just blindly respond with the "right thing" when you see a certain kind of query

tony.kay 2017-02-22T16:46:32.003816Z

ok...all day meeting I gotta go to. Hope I caught up to everybody πŸ™‚

1
urbank 2017-02-22T18:32:10.003819Z

I'm confused as to how to tread [:items/by-id 1] as a reference to an entity in a table

urbank 2017-02-22T18:32:22.003820Z

so if the state has a list of items

urbank 2017-02-22T18:32:56.003821Z

{:list [[:items/by-id 1] [:items/by-id 2]]}

urbank 2017-02-22T18:33:14.003822Z

if a parent component queries for this :list

urbank 2017-02-22T18:33:42.003823Z

how does the child resolve [:items/by-id 1] to {:item/id 1 :item/name "a name"}

urbank 2017-02-22T18:35:44.003824Z

Or am I misunderstanding. Does the child query merely provide a part of the query to the parent?

urbank 2017-02-22T18:36:39.003825Z

I'm asking, because I can't seem to make the queries actually provide what I want to the child component

urbank 2017-02-22T18:36:57.003826Z

the child is just geting [:items/by-id 1]

urbank 2017-02-22T19:16:21.003827Z

The queries of my components from the root down combine into a query which does return what I want when run through om/db->tree, yet doesn't work in the actual ui

urbank 2017-02-22T19:16:58.003828Z

Root: (query [this] `[:ui/react-key {:workers/table ~(om/get-query WorkersTable)}])

urbank 2017-02-22T19:17:17.003829Z

WorkersTable: (query [this] [{:workers (om/get-query WorkerRow)}])

urbank 2017-02-22T19:17:33.003830Z

WorkerRow: [:worker/id :worker/first-name :worker/last-name :worker/nick-name]

urbank 2017-02-22T19:17:41.003831Z

which would combine into

urbank 2017-02-22T19:17:53.003832Z

[{:workers/table [{:workers [:worker/id :worker/first-name :worker/last-name :worker/nick-name]}]}]

urbank 2017-02-22T19:18:13.003833Z

where :workers/table is a vector in the app db

urbank 2017-02-22T19:18:26.003834Z

a vector of

urbank 2017-02-22T19:18:53.003835Z

[[:workers/by-id 1] [:workers/by-id 2]]

macrobartfast 2017-02-22T20:33:01.003836Z

I'm really enjoying the devguide... so cool it's done in devcards.

adambros 2017-02-22T22:06:53.003837Z

@urbank is your WorkersTable correct? There's no syntax quote and you are putting it under just workers? Aside from that sprinkle prints in your UI graph to tell where the data is failing, and make sure you are using the real app-state and root query (ie call get query on root)

adambros 2017-02-22T22:10:17.003838Z

@baris @kauko @cjmurphy I'll be writing documentation for the new server api (untangled-system and APIHandler) as I wrote it so we could use the image library component in untangled-ui

πŸ‘ 2
2017-02-22T22:16:06.003840Z

are there any good tutorials for Om Next/Untangled that are up to date? we just had a new hire join and I am looking to get him familiar with both. He has React and some clj experience

2017-02-22T22:16:26.003841Z

I remember I used the Untangled tutorials when they first came out. Are those still good sources?

adambros 2017-02-22T22:17:03.003843Z

Pretty sure we've had a whole sprint to updating the documentation, so yes?

qqq 2017-02-22T22:17:27.003844Z

the devcards look nice

qqq 2017-02-22T22:17:40.003845Z

I started with untangeld yesterday, am working through the devcards now, and they seem very well written.

πŸ‘ 1
2017-02-22T22:17:42.003846Z

awesome, i totally forgot about that @adambros.

adambros 2017-02-22T22:18:09.003847Z

There's also awkay/om-tutorial

2017-02-22T22:18:32.003848Z

@adambros I remember using that as well when it first came out. @qqq did you have any om next experience before this?

2017-02-22T22:21:15.003851Z

i think ill start him on the untangled tutorial for now. If he wants more ill point him to tony’s tutorial. πŸ™‚

πŸ‘ 1
urbank 2017-02-22T22:36:41.003853Z

@adambros Well :workers is the field under :workers/table that holds the worker idents. I added the syntax quote (though I'm not exactly sure why it needs to be there). Also, (om/get-query Component) returns nil in the repl.

urbank 2017-02-22T22:37:02.003854Z

You mean (get-query WorkersTable) in root?

urbank 2017-02-22T22:38:40.003855Z

The correct Idents get to WorkerRow, but they're just idents ([workers/by-id 1] instead of {:worker/first-name "name" ...})

urbank 2017-02-22T22:39:07.003856Z

I might be fundamentally misunderstand what's going on

adambros 2017-02-22T22:44:49.003857Z

Can you provide code? and your app state as well?

urbank 2017-02-22T22:57:25.003858Z

@adambros Thanks for the help! here's the code http://pastebin.com/abVhgAdF

adambros 2017-02-22T23:00:39.003860Z

urbank: for reference you can upload a snippet in slack itself

adambros 2017-02-22T23:01:57.003862Z

what is the reason for :workers/table having :workers in it?

adambros 2017-02-22T23:02:13.003864Z

eg: why not just {:workers/table [idents…]}

urbank 2017-02-22T23:02:37.003866Z

Because I might want to add more fields there later

adambros 2017-02-22T23:02:53.003868Z

WorkersTable ident is just [:workers/table]

adambros 2017-02-22T23:02:59.003870Z

om idents must be 2 elements

adambros 2017-02-22T23:03:15.003872Z

are you coming into untangled with or without om experience?

urbank 2017-02-22T23:03:26.003874Z

Without

adambros 2017-02-22T23:03:43.003876Z

ah ok

adambros 2017-02-22T23:04:16.003878Z

you may want to follow https://awkay.github.io/om-tutorial/ for learning about om next

adambros 2017-02-22T23:04:39.003880Z

it’s not necessary, but i would suggest it while you wait and use it as a reference in the future

urbank 2017-02-22T23:05:23.003882Z

Oh nice. I'll definitely read through it.

adambros 2017-02-22T23:05:56.003886Z

towards the bottom theres a section on idents

urbank 2017-02-22T23:09:55.003888Z

Right... so a top level table and the id. I thought that since :workers/table was a top level key, it could be used as an Ident. A bit pointless, but I put it there for some reason. But I'm under the impression that it doesn't really change anything if that ident is there or not, in the WorkersTable component

urbank 2017-02-22T23:10:42.003891Z

Given the code as it currently is

adambros 2017-02-22T23:19:58.003893Z

so im running your app and when i look at the app state:

@(om/app-state (:reconciler @urbank.core/app))
=&gt; {:ui/react-key "58ae1c49-49a8-4ba7-a268-96549e03ada6", :workers/by-id {nil {:workers/by-id 5}}, :workers/table {:single
ton {:workers [[:workers/by-id nil] [:workers/by-id nil] [:workers/by-id nil] [:workers/by-id nil] [:workers/by-id nil]
]}}, :ui/locale β€œen-US”}

adambros 2017-02-22T23:20:20.003897Z

which seems wrong

adambros 2017-02-22T23:20:45.003899Z

ah i think its the WorkersTable ident

urbank 2017-02-22T23:27:16.003901Z

Hm... that's weird.

urbank 2017-02-22T23:30:20.003903Z

I'm not getting any nils. I'm just getting the map at the beginning of the file I posted

adambros 2017-02-22T23:30:41.003905Z

yeah i had to tweak it’s ident

adambros 2017-02-22T23:30:49.003907Z

but i cant get it quite right yet

adambros 2017-02-22T23:35:15.003909Z

aha

adambros 2017-02-22T23:35:20.003911Z

something showed up

adambros 2017-02-22T23:35:31.003913Z

not sure im doing it right

urbank 2017-02-22T23:41:33.003918Z

Hm. Interesting. I'll try it on my end. I suppose the InitialAppState is equivalent to just having that in the initial atom that gets passed to untangled?

urbank 2017-02-22T23:42:10.003919Z

Thanks a lot for taking the time to help me out with this, by the way!

adambros 2017-02-22T23:42:52.003921Z

yeah basically, it’s the recommended way forwards for initial state

adambros 2017-02-22T23:43:26.003923Z

i think that devguide has basically what you are trying to do

adambros 2017-02-22T23:43:32.003924Z

person -> worker

adambros 2017-02-22T23:44:10.003925Z

notice how PeopleWidget has no query or ident

adambros 2017-02-22T23:48:39.003927Z

so key insight, WorkersTable doesn’t need a query or ident, it will just render the :workers it gets passed in

adambros 2017-02-22T23:49:47.003928Z

make sure you read all of that devguide section E_UI_Queries_and_State

urbank 2017-02-22T23:53:32.003929Z

Right. In this case this is great. I wonder though if I'll run in to a similar problem later down the line, where this isn't a solution. Will definitely read the devguides

adambros 2017-02-22T23:54:05.003930Z

are you wondering about having other keys in your old :workers/table ?

adambros 2017-02-22T23:54:53.003931Z

ie: are you asking about how to view the same table in different ways?

urbank 2017-02-22T23:55:22.003932Z

Yes! That's actually the thing I most need. A bunch of ways to view and edit some data

adambros 2017-02-22T23:58:16.003933Z

well so the idea is that all your data is under :workers/by-id, if you need different views on the same data, you just need to query WorkersRow with a different join key and render them however you need to

adambros 2017-02-22T23:58:58.003934Z

om will take care of de-normalizing the data, it’s your job to filter/map/reduce that data until it looks like what you need it to