Fork me on GitHub
#fulcro
<
2023-01-09
>
Eva O15:01:33

In the RAD Semantic UI Plugin the action-layout of the report is checked for visibility but the input-layout is not. Also in the container neither are checked for visibility. Is that intentional?

Eva O15:01:22

It's also not checked in the form

tony.kay15:01:56

no. Inconsistencies like that are typically oversights whose nature is “I didn’t need it, have never needed it, and forgot others might need it”

👍 2
tony.kay15:01:09

Sometimes you might find I’ve duplicated effort as a result, which is unfortunate. For example, the embedded? flag has sort of an amorphous meaning at the moment…sort of “you’re not participating in routing and you might sorta hide some stuff” 😄

tony.kay15:01:35

I’m slightly embarrassed at these. When I had more free time I was better at keeping it all straight.

Eva O15:01:28

ManyFiles uses rand-int to set the key of the input. The comment says that it's so that a failed upload can be retried. Why not use inc?

tony.kay15:01:53

does it matter?

Eva O15:01:06

Not really

tony.kay15:01:13

basically you change the key, react remounts it. Remounting it clears the selected files from the browser.

tony.kay15:01:23

hacky but effective

Eva O15:01:36

There's probably some 0.000000001% edge case that makes one better than the other

tony.kay15:01:55

rand could return the same number twice

tony.kay15:01:04

so inc is technically better

Eva O15:01:21

Yeah that's what I was thinking. Very unlikely but still possible

Eva O15:01:41

Are rotated tables supposed to have selection, alignment, and column-classes?

tony.kay15:01:42

don’t remember

Eva O16:01:49

Off the top of my head I can't think of anything that would go wrong if they were added

tony.kay16:01:52

RAD really is an unfinished work. I use it heavily, but it was always intended as a system of patterns. The actual implementation of the plugins gets fleshed out as I need features, but the community is welcome to use what I have so far and is encouraged to contribute. I don’t ever expect this kind of work to ever be finished. Too many things people will want. So, it was always designed to be that way. So, when you find something like that, the answer is “think about it”. I don’t have a grand master plan of every element. In this case, I’d agree with you. There’s nothing wrong with having them. I just didn’t need them for that use-case (yet).

Eva O16:01:05

Sorry are these too many questions?

tony.kay16:01:30

I’m one of those people who’d rather understand how/why something works, because then I can usually derive the answers to new questions. So, that’s why I’m trying to make sure you understand that I actually don’t have answers to many of these questions because RAD itself is just a system of evolving patterns that are meant to be extensible, and many parts of it are “what I needed at the time”. I did a big sprint initially where I had it all in my head and did a pretty good job of getting the “bones” right-ish. That was 3+ years ago? So, in many cases I just don’t remember and have to read the code and figure out “what was I thinking here?” It’s why I try to write books around the stuff ASAP, which I didn’t do as well for RAD due to time constraints. So, I’d love to help you understand my thought process so you can be more confident about re-deriving the same things I would 😄

❤️ 2
tony.kay16:01:13

My general thought pattern is: • Provide a context-specific place to put things • Layer those when possible if there is a specialization where it makes sense to be “more specific: So, something like the (recently added) ao/label on at attribute: People want to be able to label things in the data model. But in a form there is a lot of space, so the label might get to be larger or have an info bubble. In a report column heading it might need to be abbreviated for space. And that might depend on the number of columns.

tony.kay16:01:15

That kind of thing

Eva O16:01:15

I appreciate the answers

tony.kay16:01:26

No no. You’re not annoying me in the least ::)

🙂 2
tony.kay16:01:13

So, fo/field-label, ro/column-heading…but then I realize I’m defining both of those to be the same thing all the time…so it should have also had ao/label

tony.kay16:01:22

Then of course there’s the problem of what args to pass them when then are functions (the ?! case). What will be available? For fo/field-label its a form. For ro/column-heading it is a report…for ao/label it is a bit dodgy…what if I’m generating a printed report PDF in the server?

tony.kay16:01:36

So, you run into that kind of complication 😄

Eva O16:01:19

There are other options that have an attribute version, a form version, and a report version. I think it's helpful to have the 3 types to cover both those usecases: the attribute version when your labels really are the same everywhere, and the more specialized versions when the labels are different

tony.kay16:01:12

because forms/reports and whatever else you invent are aggregators that have the context…that’s why validators are defined on forms, and not so much on attributes.

tony.kay16:01:24

(though you get ao/valid? it isn’t sufficient)

tony.kay16:01:07

I can define a form with one field that makes entities that require three. As long as the save middleware can fill in the other two server-side, then that’s a perfectly valid use-case.

tony.kay16:01:30

So I would not want the form saying I can’t save because I’m missing data I didn’t even put on the form 😄

tony.kay16:01:46

I have a REST-endpoint generator that looks a bit like a form declaration. Purely server-side, using RAD schema model. It generates the Swagger docs, parses REST inputs and turns them into a proper RAD tree of data, validates it, and can return REST errors to the user.

tony.kay16:01:30

Uses defentity to describe what model bits are communicated (each is like a form with subforms (subentities)), and then defendpoint spells out things like which entity the body will be, docstrings, etc.

tony.kay16:01:22

same kinds of patterns emerge where you might define something like a swagger docstring on an attribute, but want to indicate something special about that attribute in a given REST endpoint context.

tony.kay16:01:01

Also doing similar things for other common patterns, like CSV import, excel export….

Eva O16:01:27

That might be an interesting alternative to yada

tony.kay16:01:21

I already have my complete data model well defined and related. Why have to re-state it again?

tony.kay16:01:11

The new “facts” are “I want to take a JSON tree and transform it to my EDN tree”. That’s a very tractable problem with attributes and form-like entity declarations.

tony.kay16:01:11

(defentity InvoiceItem
  {eno/attributes [invoice-item/product invoice-item/amount]})

(defentity Invoice
  {eno/attributes [invoice/number invoice/amount invoice/items]
   eno/subentities {:invoice/items InvoiceItem}
   ...})

(defendpoint SubmitInvoice [env invoice]
  {eo/method :post
   eo/uri "/invoice" 
   eo/body Invoice
   ...}
  invoice ; is a RAD-model tree of data)

tony.kay16:01:00

Data coercion can be defined for all the attribute data types, with overrides available at each layer, etc.

Eva O16:01:19

Very interesting. I like this idea

Eva O16:01:55

Why does the normalize-options mutation in the autocomplete field have a separate blank clojure impl from the default clojurescript one?

tony.kay17:01:17

in autocompletee?

tony.kay17:01:45

because you’re in a SUI plugin ns. I want clj to compile, but it won’t do anything useful if run in CLJ.

tony.kay17:01:21

the semantic UI js code won’t run in CLJ…so it’s CLJC to prevent compile errors when your spiderweb of requires accidentally gets that file

tony.kay17:01:06

and it needed to use the #js reader, which I was being lazy about 😄

tony.kay17:01:38

Now that I think about it, I think i have data readers on Fulcro for #js as identity…so it probably can just be unconditional

2
tony.kay17:01:01

The js namespace fails, so I was probably just typing too fast (e.g. (js/console.log…) won’t compile, but I think the reader for js will).

Eva O17:01:27

Oh ok that makes sense

Eva O17:01:40

I saw there's a new wrap-exceptions-as-form-errors in the RAD demo. Why doesn't it wrap all the save middleware?

tony.kay14:01:20

Excellent question. I'm being ultra conservative about things that could be breaking changes. I assume that since I had not already provided such a thing, that others might have already done some additional error plumbing, and I didn't want to make a change that wasn't optional. For example, someone might have written a pathom layer to deal with exceptions, and if I suddenly stopped those exceptions from propagating it would break their program

tony.kay14:01:23

Also, doing it this way makes error handling more pluggable. Some exceptions might not be form errors, and might indicate some other condition to your front end code that you handle differently. For example, actual validation errors might go to the form, but you might like server-related errors to use a toast.

Eva O19:01:51

I meant wrap as in moved down in the code like this:

(def middleware
  (-> (xtdb/wrap-xtdb-save)
      (r.s.middleware/wrap-rewrite-values)
      (wrap-exceptions/wrap-exceptions-as-form-errors)))

Eva O19:01:12

Although that answers my second question of why it's not in RAD itself

Eva O19:01:38

Whoops imagine if my code example was using datomic not xtdb

tony.kay19:01:41

I didn’t add it to that one, but really it just depends on what layers you want it to protect. I’d agree with you that in general it’s probably best to just put it around the entire stack

Jakub Holý (HolyJak)20:01:33

@UGBKV7HHP I love your explorations and all the questions you are asking. I learn a ton and it might contribute to making RAD better 🙂