Fork me on GitHub
#fulcro
<
2020-12-30
>
stuartrexking02:12:41

I’ve added a signup uism to the RAD demo. Once the registering is successful I want to trigger the login flow, without the user having to re-enter their email and password. The LoginForm from RAD transacts the login mutation which remotely checks the credentials and locally in the ok-action checks the status and calls in the RAD auth system for either a success (auth/logged-in) or a failure (auth/failed). I’m not sure what the best approach is here. One idea I had was to have auth/Session as an actor in my uism and replicate the login mutation with a trigger-remote-mutation. Any other ideas for a better approach?

tony.kay03:12:21

The auth thing in RAD is half-baked. Just write something new. Copy the state machine out of what is there and add some more states and events to it.

stuartrexking03:12:29

Ok. Thanks. I have a half-baked solution on the half-baked RAD implementation. I feel half-baked myself after working through this.

😅 6
stuartrexking07:12:47

Is there an elegant approach to triggering a change of route from a uism? The examples I’ve seen require app and call dr/change-route directly from a handler.

tony.kay17:12:38

write a function like this:

(defn change-route-relative [{::uism/keys [app] :as env} router-actor new-route]
  #?(:cljs (dr/change-route-relative app
             (uism/actor-class env router-actor) new-route))
  env)
and make your router an actor

Jakub Holý (HolyJak)08:12:45

https://blog.jakubholy.net/2020/fulcro-divergent-ui-data/ is now live. Many thanks to everyone who contributed! ❤️

🎉 9
JAtkins17:12:27

Are diff added / diff removed broken on the new versions of inspect? I'm seeing nil everywhere, but it could just be my stuff being stupid.

Jakub Holý (HolyJak)17:12:06

Tony would accept a PR fixing it but I personally do not have time to look into it 😞

👍 3
JAtkins17:12:09

Ok. I may try to get the project spun up and work on fixing that if someone else isn't doing that already

🙏 3
JAtkins18:12:19

There seems to be a 2nd regression as well - looks like the db tab is treating state as (seq {state stuff}) and goofing up when you click an index to add to watches

JAtkins20:12:01

Scratch that last note --- not sure what happened, but that particular issue was just a fluke

tony.kay17:12:12

I have a request of this community. I’m a bit irritated by a recent GitHub issue and I’m trying to be as nice about it as possible; however, it has touched a nerve and I’d like your participation in addressing it. First, I’d like a little bit of understanding: I built Fulcro for my projects and my startups. I work 12-16 hour days. Many of those hours, as you can imagine, are spent refining Fulcro, documenting things, and answering questions. The first two I do out of partial self-interest: it makes it easier to onboard help in my own projects to have good docs, and I use Fulcro for practically everything I write. The last one, though, I do because I enjoy helping people. I am not Facebook. I don’t get paid billions of dollars selling your kitten memes to advertisers. I benefit from open-source, and so this is one way I “give back”. It is highly optional, very non-lucrative (I do make some money from free OSS, but it amounts to waaaaay less than minimum wage, and way less than I charge for my time professionally). A thank you goes a long way, and help is appreciated. But some days I have a very clear and personal understanding of why open-source projects get abandoned. There is no economic model for doing this. Businesses, on the whole, don’t pay even 0.001% of the benefit they get from OSS. So, this means that most OSS is pretty much a volunteer effort. That means that every issue you open or request you make takes a little bit of my time. So, here’s my request: Could each of you read this issue (it’s very short, and I think well-intentioned), think about how that might land on your average open-source maintainer, and gently and nicely add a comment to that issue that improves our shared understanding before I close it (or retitle it)? https://github.com/fulcrologic/fulcro-inspect/issues/97

👀 9
Jakub Holý (HolyJak)17:12:15

I feel your pain. But the average user doesn't see it, maybe they believe Fulcro is a community effort and not the heroic deed of mostly a single person. Perhaps it would help to define an issue template or some pre-issue checklist that would summarize ☝️ and explain when (not) to open an issue?

tony.kay18:12:24

Sorry, that’s all the time I’ve got for this. Not asking for a solution to people opening issues in the future. It’ll happen again no matter what I do. That’s OK. It’s normal. I’m doing something very unusual: Asking for people to do a bit of self-reflection in the “now”.

👍 9
tony.kay18:12:11

probably partly because this was the first thing that I saw when I woke up this morning, and perhaps I was a bit cranky 😜

tony.kay17:12:19

well, look at that, the entire issues fits here…so, reading it is even easier

tony.kay17:12:33

My apologies to the the person that opened the issue. I realize this might be a little embarrassing. I have no personal hard feelings toward you at all. I just have a need for people to be a bit more enlightened. Forgive me for using your issue as a “teaching moment”

Björn Ebbinghaus20:12:49

FYI: There is even a hooks helper namespace: com.fulcrologic.fulcro.react.hooks https://book.fulcrologic.com/#_react_hooks_support

nivekuil20:12:52

yup, although for useCallback we actually have access to that "sufficiently advanced compiler" the react docs mention and properly express its intent

tony.kay22:12:18

it’s also worth noting that if you use timbre, you already have encore, and encore has a memoize that will GC and can have a TTL. It’s a much easier thing to use that gets you 95% there with no need to even “name” your dependencies.

JAtkins22:12:32

dang. and I went to the trouble of making my own...

tony.kay22:12:56

yeah, I think everyone should look through encore…there’s a lot of useful stuff in there

genekim23:12:57

After watching all the remaining Fulcro 3 videos, and studying the code examples, a bunch of the concepts became much clearer — and I have finally created my first F3 components, as opposed to using the Fulcro RAD forms and reports. But I’m still struggling to understand how to access all the F3 entities from inside RAD reports and forms. Taking a stab at articulating clearly my questions: 1. When inside of a RAD report, how do you access data outside the report, such as the “global” components that are often stored in [:component/id] in so many of the F3 examples. (e.g., [:component/id :person-list :person-list/people or like here: https://github.com/fulcrologic/video-series/blob/forms-final/src/app/client.cljs#L118. (I tried adding them via ro/query-inclusions, but could never get it to show up in props 2. How can one use a RAD form from an F3 component? For example in the “forms-final” example, how would we leverage a RAD form for Undo/Save functionality to edit ItemDetails, instead of writing all of it ourselves? 3. (Maybe the easiest question, which would illuminate #2 above): how does one edit a specific entity in a RAD Form, say, a specific invoice, in the RAD example. Currently, the only way to reach them seems to be via ro/form-links — how does one edit a specific invoice, say by its UUID? Thank you, all!

genekim23:12:01

For instance, I’d like to use a RAD form to edit PersonDetails, like here: https://github.com/fulcrologic/video-series/blob/full-stack-over-time/src/app/client.cljs#L19 I can imagine implementing this by accessing the [:component/id :person-list :person-list/people], but how does one access this from inside a RAD form? (Question #1) I can also imagine using rroute/route-to or something to edit a specific entity, but how? (Question #3) Or maybe there’s a way to use RAD form functionality from within an existing F3 component (like PersonDetail), but how? (Question #2)

JAtkins23:12:57

You mean this?

(form/edit! this TaxForm (uuid))

JAtkins23:12:45

I can't speak to #1 yet, I've not tried anything like that to date. For #2, perhaps you are looking for formstate? https://book.fulcrologic.com#FormState For #3, you would want to look at the com.fulcrologic.rad.form ns, specifically create! and edit!

genekim23:12:12

🤯🤯🤯. That's awesome — will check it out later today! Thank you, @U5P29DSUS !

👍 3
genekim00:12:10

form/edit! is awesome! That worked — thank you! But is there a way to use RAD forms for just one component (of potentially many) on the screen? Like in this marked up screenshot? (i.e., I’d love to leverage all the RAD form functionality like Save, Undo…)

JAtkins00:12:37

now, this is something I'm curious about actually. I've been starting to toy with this exact bit of functionality. I haven't gotten far yet, but I think the potentially big issue is the fact that routers can only have one path target (correct me if I'm wrong please 🙂). To avoid that issue you would need to drop down a level in rad and do all the routing yourself, which may disturb some of the load code.

JAtkins00:12:14

Maybe this just requires a bit of tooling in rad to make it easy?

JAtkins00:12:32

In your e.g. you may still want manual placement control instead of a router though.

JAtkins00:12:15

dang. I'll need to read the code to get my head around this fully. I'll let you know my findings if someone doesn't post the solution in the interim

genekim00:12:36

This is so helpful — please keep me posted on your progress… I am currently trying to see if I can render it like a regular “defsc” component…. I’ll let you know how it goes.

genekim00:12:17

(…I realize I may be doing something that exposes my total ignorance on how “defsc-forms” actually work.)

JAtkins00:12:58

That is perfectly possible. I'm just not up to speed on what is(n't) required to make the life cycle work. AFAIK most of the form lifecycle is triggered by the router.

genekim00:12:28

OMG. It totally worked!!! What sort of black magic has @U0CKQ19AQ created!!! Will post more later!!!

3
tony.kay01:12:51

A form is a plain defsc component. It just adds routing integration and a state machine. If you want to use it anywhere, you just have to trigger the stuff that the routing would trigger. Trying my best not to tie you down with anything. Everything (I’ve thought of at least) has an escape.

tony.kay01:12:05

The routing integration is a convenience, not a requirement.

genekim08:12:39

This really is incredible, @U0CKQ19AQ!!!! The ability to have multiple RAD forms on the screen is so freaking cool, and makes it so easy to use the form machinery you've created! Is there a way to have a RAD Form access things like {:component/id :person-list} ? I'm trying to replicate some of the "video-series" examples you created with RAD, but can't figure out how to reach those "global state" things... Thx!!

Jakub Holý (HolyJak)08:12:07

@U6VPZS1EK please consider sending a PR to the RAD book to make it easier to discover form/edit! etc. Somebody (you?) could perhaps also write a section on "Using Forms outside of a router" 🙂 For reports it is perfectly OK to use them outside of a router but you need to start their UISM manually. I guess you just need to look at what the form/report :will-enter does.

Jakub Holý (HolyJak)08:12:35

> s there a way to have a RAD Form access things like `{:component/id :person-list}` ? ro/query-inclusions should work, provided you write it right, I believe. What does your look like? After adding it, look at the outgoing Network request - does the query look the way you expect? What about the response?

genekim08:12:22

Will do in the next week, @U0522TWDA ! (And thanks for solving the mystery of why the form didn't look quite right... Looking at the screenshot, I noticed that it hadn't fully populated yet! Nice!)

genekim08:12:51

@U0522TWDA Okay, I love that like ro/query-inclusions is likely the right mechanism! I had tried adding something like ro/query-inclusions [ [{:component/id {:person-list {:person-list/people [id, name]}] -- but it seemed like everything I put in resulted in nil everywhere. It should be an EQL query, which can be tested in Fulcro Inspector, yes? It occurs to me that I should have studied what the results of (comp/get-query) and (comp/get-ident) were. Will pick it up again tomorrow! Thx!!

Jakub Holý (HolyJak)09:12:13

that is wrong. You are trying to add a join on the :component/id property of current entity and there is no such thing, I think. Look at https://book.fulcrologic.com/#_link_queries

Jakub Holý (HolyJak)09:12:08

Also, Pathom knows nothing about :component/id so you don't want that at all in your query.

Jakub Holý (HolyJak)09:12:43

Hm, I have problems getting ro/query-inclusions working on latest rad-demo, it does not add it to the query sent to the backend... 1. I added ro/query-inclusions [:category/all-categories] to the RAD demo InvoiceList report 2. (comp/get-query com.example.ui.invoice-forms/InvoiceList) has the added part: [:com.fulcrologic.rad.report/id ... :ui/current-page [#:ui{:current-rows [:account/id ...]} ...] :category/all-categories] 3. (df/load! com.example.client/app :invoice/all-invoices com.example.ui.invoice-forms/InvoiceList) sends the query including the added part, like this:

[{:invoice/all-invoices
  [:com.fulcrologic.rad.report/id :category/all-categories]}
 :com.wsscode.pathom.core/errors]
but the query sent by the report when I reload the page is different:
[({:invoice/all-invoices
   [:account/id
    :invoice/id
    :invoice/date
    :account/name 
    :invoice/total]}) 
 :com.wsscode.pathom.core/errors]
so it has more stuff in the query but lacks the added stuff. I guess the report UISM load event does something weird to the query... That is because it loads the data differently:
[({:invoice/all-invoices
   [:account/id
    :invoice/id
    :invoice/date
    :account/name 
    :invoice/total]}) 
 :com.wsscode.pathom.core/errors]
see https://github.com/fulcrologic/fulcro-rad/blob/d81892cabdcb3b48d4f95c763414f5ff1c9c7bdf/src/main/com/fulcrologic/rad/report.cljc#L161 So this uism/load is good b/c it includes the BodyItem query needed for the report but it is bad b/c it ignores the query-inclusion. Is this a bug? Should ro/query-inclusions be added here as well?!

Jakub Holý (HolyJak)09:12:47

Now I realize that also the query produced by df/load! is not what I expected (and I was wrong to expect it). Of course it puts the attributes into the join:

[{:invoice/all-invoices
  [:com.fulcrologic.rad.report/id :category/all-categories]}
 :com.wsscode.pathom.core/errors]
b/c that is what load! does when provided with "server-property". So I would need to make sure that the resolver for :invoice/all-invoices returns whatever extra properties I want to request. (And I still do not understand how ro/query-inclusions is supposed to be used given that report/reload / report/load-report does send a different query, one without it.) I guess it could work if the properties I ask for were returned by the all-invoices resolver and I issued a manual df/load! - then it would be loaded and stored in the client DB. The report UISM would subsequently issue its own load to load the actual report data itself so that both would be in the DB. Then I guess props would contain both... But I need to look at what exectly report's :will-enter does

Jakub Holý (HolyJak)11:12:38

@U6VPZS1EK I thought more about it and perhaps I have the answer to #3. You use ro/query-inclusions . If the data is already in the client DB then you are good. If not, you need to df/load! them manually, e.g. as shown above. To access :component/id :person-list :person-list/people in this way you must remember that the query is relative to the report's position in the data tree (which is a subset of the ui tree). Only the Root can ask directly for {[:component/id ..] [..]} in its query. Any nested component must use https://book.fulcrologic.com/#_link_queries to reach it. So something like

ro/query-inclusions [{[:component/id :person-list] [:person-list/people]}]
;; or st. like:     [{[:component/id :person-list] (comp/get-query PersonList)}]
should do the job (here I leverage a join on an ident https://blog.wsscode.com/pathom/v2/pathom/2.2.0/connect/resolvers.html#SingleInputs to get at the particular component) (Use get-query on the Root or the report component to have a look at the query and check that it looks OK. Remember you can turn the query into the resulting data tree manually.)

genekim18:01:04

This is great, @U0522TWDA — I had intended to study your ro/query-inclusions example this weekend, but ended up spending 4 hours trying to figure out how to get the UISM machinery started for forms not started via router: https://clojurians.slack.com/archives/C68M60S4F/p1609404307479000?thread_ts=1609369557.443000&amp;cid=C68M60S4F > For reports it is perfectly OK to use them outside of a router but you need to start their UISM manually. I guess you just need to look at what the form/report :will-enter does. I tried using (form/start-form!) , and it took me a day to figure out where / when to call it. (I put it in the same place where the df-load! went.) My problem now: when I edit the form, the “Save” or “Undo” briefly flicker on, but then get disabled… Edits to the data show up outside the form, too… Movie of this happening here: https://www.dropbox.com/s/ogqoey8r9m58kbv/Screen%20Recording%202021-01-03%20at%2010.31.00%20AM.mov?dl=0 My current theory: something in the Form UISM was set wrong? Here’s the state from the demo app: Area of difference shown with a “<====”

- com.fulcrologic.fulcro.ui-state-machines/begin
 {:com.fulcrologic.fulcro.ui-state-machines/asm-id
  [:session/uuid #uuid "63827c18-5960-408f-8421-66d121a175b2"],
  :com.fulcrologic.fulcro.ui-state-machines/state-machine-id
  com.fulcrologic.rad.form/form-machine,
  :com.fulcrologic.fulcro.ui-state-machines/event-data
  {:action "edit",              ;;; <==== NOTE THIS:
   :id "63827c18-5960-408f-8421-66d121a175b2",
   :com.fulcrologic.rad.form/create? false},
  :com.fulcrologic.fulcro.ui-state-machines/actor->component-name
  {:actor/form :com.example.ui.session-forms/SessionForm},
  :com.fulcrologic.fulcro.ui-state-machines/actor->ident
  {:actor/form
   [:session/uuid #uuid "63827c18-5960-408f-8421-66d121a175b2"]}})
And here’s the form that I set up manually thru form-begin!
- (com.fulcrologic.fulcro.ui-state-machines/begin
 {:com.fulcrologic.fulcro.ui-state-machines/asm-id
  [:session/uuid #uuid "8a481331-eb1d-4e5b-9d19-759da23cb674"],
  :com.fulcrologic.fulcro.ui-state-machines/state-machine-id
  com.fulcrologic.rad.form/form-machine,
  :com.fulcrologic.fulcro.ui-state-machines/event-data
  {:com.fulcrologic.rad.form/create? false},   ; <===== NOTE THIS
  :com.fulcrologic.fulcro.ui-state-machines/actor->component-name
  {:actor/form :com.example.ui.session-forms/SessionForm},
  :com.fulcrologic.fulcro.ui-state-machines/actor->ident
  {:actor/form
   [:session/uuid #uuid "8a481331-eb1d-4e5b-9d19-759da23cb674"]}})
Going through the source code now to see where and how event-data is set…

genekim18:01:03

(…By the way, those state machine states come from the Fulcro Inspector Transactions…)

genekim19:01:31

…upon some study, I’m not sure the differences in UISM state actually matter — `(:action "edit"}` shouldn’t affect functionality? All the right buttons are appearing… I’m now studying why the Undo and Save buttons flicker on, and then off, as shown in the movie…

lgessler23:12:12

does anyone have a strong opinion about whether keywords used for data (so, ones appearing in the fulcro db or in pathom resolvers/mutations) ought to have "full" namespaces? in general clojurians tend to prefer "full" namespaces like :com.mycompany.widget/id , but it's common at least historically for fulcro projects to use :widget/id. Personally while I'm sympathetic to the best practice of using full NSes in general, a major reason for this practice is to avoid name clashes, and if your app is never going to be a dependency for another system, and data flowing into your app won't clash with abbreviated namespaces, then I wonder whether abbreviated namespaces might be harmless and perhaps even preferable for certain kinds of readability

currentoor00:12:25

i agree with your assessment

currentoor00:12:58

non-library applications should use :widget/id, readability is very important

👍 6
tony.kay01:12:18

I concur; with one caveat: If you expect your data store to be published for use in federated data system (i.e. you might pair up with other companies and use pathom to combine data sets in a federated graph) then it is quite useful and important to use the longer names. Most people are just building some in-house thing that doesn’t need to integrate that way, so the shorter name does create less mental overhead/work/aliasing

👍 3
lgessler01:12:01

right, that's uncommon in my corner of the world but i'd expect it to be perfectly normal elsewhere... one way of having your short namespace and eating it too could be to map between short and full namespaces at the system boundaries (`:com.mycompany.widget/...` <--> :widget/...) but now you've got a mapping to maintain and the responsibility to make sure it's applied just where it's needed

tony.kay01:12:32

yep…aliasing a lot of stuff creates way more headaches than having to type a little more during dev

Jakub Holý (HolyJak)11:12:25
replied to a thread:After watching all the remaining Fulcro 3 videos, and studying the code examples, a bunch of the concepts became much clearer — and I have finally created my first F3 components, as opposed to using the Fulcro RAD forms and reports. But I’m still struggling to understand how to access all the F3 entities from inside RAD reports and forms. Taking a stab at articulating clearly my questions: 1. When inside of a RAD report, how do you access data outside the report, such as the “global” components that are often stored in `[:component/id]` in so many of the F3 examples. (e.g., `[:component/id :person-list :person-list/people` or like here: https://github.com/fulcrologic/video-series/blob/forms-final/src/app/client.cljs#L118. (I tried adding them via `ro/query-inclusions`, but could never get it to show up in `props` 2. How can one use a RAD form from an F3 component? For example in the “forms-final” example, how would we leverage a RAD form for Undo/Save functionality to edit ItemDetails, instead of writing all of it ourselves? 3. (Maybe the easiest question, which would illuminate #2 above): how does one edit a specific entity in a RAD Form, say, a specific invoice, in the RAD example. Currently, the only way to reach them seems to be via `ro/form-links` — how does one edit a specific invoice, say by its UUID? Thank you, all!

See the ro/query-inclusions working here https://github.com/holyjak/fulcro-rad-demo/commit/946f4a8ee84296f12786b8e438ab6c2dccd03582

genekim19:01:31
replied to a thread:After watching all the remaining Fulcro 3 videos, and studying the code examples, a bunch of the concepts became much clearer — and I have finally created my first F3 components, as opposed to using the Fulcro RAD forms and reports. But I’m still struggling to understand how to access all the F3 entities from inside RAD reports and forms. Taking a stab at articulating clearly my questions: 1. When inside of a RAD report, how do you access data outside the report, such as the “global” components that are often stored in `[:component/id]` in so many of the F3 examples. (e.g., `[:component/id :person-list :person-list/people` or like here: https://github.com/fulcrologic/video-series/blob/forms-final/src/app/client.cljs#L118. (I tried adding them via `ro/query-inclusions`, but could never get it to show up in `props` 2. How can one use a RAD form from an F3 component? For example in the “forms-final” example, how would we leverage a RAD form for Undo/Save functionality to edit ItemDetails, instead of writing all of it ourselves? 3. (Maybe the easiest question, which would illuminate #2 above): how does one edit a specific entity in a RAD Form, say, a specific invoice, in the RAD example. Currently, the only way to reach them seems to be via `ro/form-links` — how does one edit a specific invoice, say by its UUID? Thank you, all!

…upon some study, I’m not sure the differences in UISM state actually matter — `(:action "edit"}` shouldn’t affect functionality? All the right buttons are appearing… I’m now studying why the Undo and Save buttons flicker on, and then off, as shown in the movie…