Fork me on GitHub
#fulcro
<
2024-03-19
>
genekim03:03:56

I have a RAD report that shows a list of podcasts — upon selecting a row, I want it to bring up a list of Podcast Episodes, restricted to only the :podcast/id.

ro/on-select-row (fn [this row-props]
                      (let [{:podcast/keys [id]} row-props]
                        (log/warn :on-select-row :id id :row-props row-props)
                        (rroute/route-to! this Episodes {:podcast/id id})
In the episodes resolver, I have something like this:
(pc/defresolver all-episodes [{:keys [query-params] :as env} input]
       {; no ::pc/input
        ::pc/output [{:podcast-episode/all-episodes
                      [:podcast-episode/id
                       :podcast-episode/title
                       :podcast-episode/pub_date_ms]}]}
But whenever that resolver is called, the query-params is an empty map, as is input. And for that matter, (-> env :ast :params). I thought the route-params in rroute/route-to are given to the resolver as query-params? Any help appreciated! Thank you!

1
Eric Dvorsak09:03:14

Would help if you shared the Episode component. But for sure I would expect your defresolver all-episodes to have :podcast/id as input

genekim15:03:57

Good call — I published the full Episode component and the resolver here: https://gist.github.com/realgenekim/b19f31ddedbaeb3de742ef6257e56ba5 The resolver is a global resolver, and takes no input — which I think matches the category resolver in the demo application? https://github.com/fulcrologic/fulcro-rad-demo/blob/main/src/shared/com/example/model/category.cljc#L24

genekim17:03:24

Good morning, @tony.kay! I’m so sure I’m missing something simple…. Can’t wait to get educated! 🙂

Eric Dvorsak17:03:34

I don't see the Episode component in the link you provided

Eric Dvorsak17:03:15

but also the category resolver from the demo application doesn't seem to do what you want at all

Eric Dvorsak17:03:55

it is meant to get the list of all possible categories so that you can pick one when creating a new item

Eric Dvorsak17:03:18

while you need a resolver that will return all episodes for one particular podcast

Eric Dvorsak17:03:48

I think you may not understand how pathom works yet? You should make sure you grasp that part before you dive too much into fulcro, let alone fulcro rad

genekim19:03:54

Ah, yes. I was in a hurry this morning. I updated the gist, and the comment now reads: > The resolver closely matches what is the account model here: https://github.com/fulcrologic/fulcro-rad-demo/blob/main/src/shared/com/example/model/account.cljc#L142 > This resolver is called by the AccountInvoices report, and through a menu item: (rroute/route-to! this AccountInvoices {:account/id (new-uuid 101)})

genekim19:03:21

I’m now endeavoring to try to figure this out now… i.e., I feel like I’ve mirrored the structure of the AccountInvoice form and the resolver…. Pretty sure I understand pathom enough to make this work, but could be totally wrong. 😂

Eric Dvorsak19:03:27

Does your resolver get called at all?

genekim19:03:25

Oh… Looking at the AccountInvoices form… > (report/defsc-report AccountInvoices [this props] > {ro/title “Customer Invoices” > ro/source-attribute :account/invoices > ro/row-pk invoice/id > ro/columns [invoice/id invoice/date invoice/total] > ro/column-headings {:invoice/id “Invoice Number”} > > ro/form-links {:invoice/id InvoiceForm} > ro/controls {:account/id {:type :uuid > :local? true > :label “Account”}} > ;; No control layout...we don’t actually let the user control it > > ro/run-on-mount? true > ro/route “account-invoices”}) It has a ro/row-pk invoice/id. (!!)

Eric Dvorsak19:03:26

Is the intent of the episode-report to only show episodes of a specific podcast?

genekim19:03:29

Hey, thanks for helping me think this through — yes, resolver is being called, but the query-params map is empty. I’m studying how the AccountInvoices resolver is called right now…

Eric Dvorsak19:03:00

Do you want your UI to fetch all episodes of all podcasts or just the ones for the podcast that you click on?

Eric Dvorsak19:03:36

You need ro/controls if you want to have parameters sent to the resolver

genekim19:03:59

Oh!!! ro/controls!!!!

Eric Dvorsak19:03:24

Like {:podcast/id {:type :none}}

genekim19:03:59

Holy cow, I’m not sure if I would have made that connection if you hadn’t explicitly mentioned that. TY!!!! 🙏 To confirm: ro/controls somehow sets up the machinery to send the parameters to the resolvers? (I’m reading the doc string right now — is that where the best documentation is for what controls do?).

genekim19:03:44

From docstring: >

Input control values are stored in the report's parameters, and can be used in the filtering/sorting of the
> rows
In previous reports, I had ro/controls, but didn’t realize that was actually required to get query-parameters sent to resolver.

genekim20:03:27

To answer your question: I want the resolver to return all podcast episodes if no query parameters are given (which is the current behavior). However, if a podcast/id is specified, return/filter only those that have that as a parent. (So right now, I’m in the resolver, trying to figure out whether query-parameters are being passed to it by the Episodes report. And if not, why not…)

Eric Dvorsak20:03:42

Yeah then what I suggested should work?

Eric Dvorsak20:03:15

Do you have fulcro chrome extension? There is a tab where you can see the queries that your app is doing

genekim20:03:59

Yes, indeed — thank you! I’m now using the report controls to filter on a UUID on the client side. Almost have it working. That was a super great call. But if I wanted to do the “filtering” on the server by passing query parameters to the resolver, how would I do that? (Right now, filtering on 2000+ episodes on client by making the visible/not-visible is definitely slow.) After I get this working, I want to implement it on server, to make the report load faster. (I will look at Fulcro Inspect to confirm that the Account Invoices passes this via query parameters — I’m still a bit mystified why all my query parameters are empty.) Thanks again!

genekim20:03:01

Filtering on client works. 🎉

genekim20:03:44

(Now looking at how to do this better, by [somehow] sending query-params to resolver…)

genekim20:03:23

For posterity: the working Podcast report is here, that does all filtering on client side. https://gist.github.com/realgenekim/b19f31ddedbaeb3de742ef6257e56ba5#file-forms2-cljc

genekim21:03:58

Okay, @U03K8V573EC — thanks again for holding my hand through this. I’m a bit dumbfounded, but now the resolver is indeed getting the query-parameters. I’m well on my way to getting this working. This is terrific! (I am going to go back a couple of commits to figure out what I was passing in rroute/route-to! before that didn’t make it to the resolve.)

W 2024-03-19T21:02:16.723Z com.example.model.podcast-episode:-101 - :RESOLVER :all-episodes :input {} :query-params {:filter/parent-id #uuid "f8e555de-37a2-4148-a56b-7332e27d9c18"}

genekim21:03:39

IT WORKED!!! 🎉 Thanks again, @U03K8V573EC!!!

🎉 1
Eric Dvorsak07:03:48

thanks @tony.kay for the tip of using gettext with lisp language. My bb task for i18n translation is now much faster than back when it had to release the js, grep for translations (because the output was sometimes tripping gettext and not going through the whole js). Here is the task I use now:

(let [clj-files (str/join " "
                                  (concat (fs/glob "./src" "**.clj*")
                                          (fs/glob "../fulcro-rad-semantic-ui/src" "**.clj*")
                                          (fs/glob "../fulcro-rad/src" "**.clj*")))]
          ;; extracting from the lisp files
          (shell (str "xgettext --language=Lisp --no-location --sort-output --from-code=UTF-8 -k -ktr:1 -ktrc:1c,2 -ktrf:1 -o resources/po-files/messages.pot " clj-files))
          ;; Warning! Ensure locale list matches locales defined in ns translations ;; TODO: import locales from config or sources
          (let [supported-locales 
        ["de" "fr"]
                update-po (fn [pot po]
                            (if (fs/exists? po)
                              (shell (format "msgmerge --force-po --no-wrap -U %s %s" po pot))
                              (do (fs/copy pot po)
                                  (shell (format "sed -i s/charset=CHARSET/charset=UTF-8/g %s" po)))))]
            (println "Supported locales:" supported-locales)
            (doseq [l supported-locales]
              (update-po "resources/po-files/messages.pot" (format "resources/po-files/%s.po" l))
              (println "Chat GPT input:\n\n")
              (println (format "Translate/fix the %s in the following msgstr in this po file. For context blah blah blah. When a translation is fuzzy make sure to double check it and remove the fuzzy. Please make it easy for me to copy paste your answer into a PO file all at once:\n\n"
                               (case l
                                 "de" "german"
                                 "fr" "french")))
              (shell (format "awk 'BEGIN{ RS=\"\"; FS=\"\\n\" }
    /msgid \"[^\"]+\"/ {
                     if (/msgstr \"\"/ || /#, fuzzy/) {
                                                     print $0 \"\\n\"
                                                     }
                     }' resources/po-files/%s.po" l))))
          (fs/delete "resources/po-files/messages.pot"))

🔥 1
Eric Dvorsak07:03:14

Note that I also grab rad and rad-semantic-ui sources because they have translations as well 😄

tony.kay16:03:37

Yeah, that is the one caveat to using that approach. You have to include all the libraries that have translations. Fortunately, that's not very many, at least at this point. I guess the fulcro libraries should probably just export a file that you can import?

❤️ 1
Eric Dvorsak16:03:22

Yeah that could be a good way to avoid cloning the other repositories in a CI context for instance