Fork me on GitHub
#fulcro
<
2023-11-04
>
Eric Dvorsak19:11:27

@tony.kay still going through i18n, there's a few holes in support for labels in RAD. I'm currently looking at how to have tr labels in reports, it doesn't work when you have ao/enumerated-labels and the values are tr labels

Eric Dvorsak19:11:08

one workaround is to have a column formatted like this for example:

ro/column-formatter (fn [report-instance value row-props attribute]
                         (case value
                           "active" (tr "active")
                           "invited" (tr "invited")))

tony.kay20:11:19

So, for string extraction to work right, you always want the former, right?

tony.kay20:11:49

using tr on database values doesn’t make any sense, since it isn’t an AI

tony.kay20:11:26

so you always need a fn to do the explicit value-to-value translation, which means column-formatter is the right place to internationalize. You could use tr-unsafe in the column formatter

Eric Dvorsak20:11:45

the problem is that colum-formatter is report specific

Eric Dvorsak20:11:54

and there is already an ao/enunerated-labels for enums

tony.kay20:11:57

which is its purpose: assert you know you need translations that come into vars

Eric Dvorsak20:11:13

I added the example in the PR:

(def student-statuses  {"active" #(tr "active")
                        "invited" #(tr "invited")})

Eric Dvorsak20:11:42

(defattr status :student/status :enum
  {ao/label #(tr "Status")
   ao/enumerated-values (set (keys student-statuses))
   ao/enumerated-labels student-statuses
   ...})})

tony.kay20:11:03

but enumerated labels supports a fn.

tony.kay20:11:30

sorry, I didn’t look at your code link

tony.kay20:11:42

you’re suggesting this isn’t sufficient:

(if-let [labels (::attr/enumerated-labels column-attribute)]
                            (?! (labels value))
                            (str value))

tony.kay20:11:06

the value from the database itself will never be a fn, so how would another ?! help here?

tony.kay20:11:12

I see…yes, you are right. I was looking at your PR

tony.kay20:11:21

and thinking you were saying that was my code and it needed fixed 😄

tony.kay20:11:31

but your fix is correct.

Eric Dvorsak20:11:45

well actually I don't know if the fix is needed I'm exploring possible solutions

tony.kay20:11:49

should we also pass in “this” though?

Eric Dvorsak20:11:01

it looks like enumerated-labels doc is missing the [value] param

Eric Dvorsak20:11:10

because I guess this would work:

ao/enumerated-values #{"active" "invited"}
   ao/enumerated-labels (fn [value]
                          (case value
                            "active" (tr "active")
                            "invited" (tr "invited")))

tony.kay20:11:26

The docstring says:

(def enumerated-labels
  "RECOMMENDED For data type :enum. A map from enumeration keyword to string (or a `(fn [] string?)` that defines
   the label that should be used for the given enumeration (for example in dropdowns). See `enumerated-values`.

   Labels default to a capitalized version of their keyword name."
  :com.fulcrologic.rad.attributes/enumerated-labels)

tony.kay20:11:42

and thus the code isn’t right as released

tony.kay20:11:46

but would be with your patch

Eric Dvorsak20:11:48

(fn [value] string?)

tony.kay20:11:10

um…yeah, that would probably be nice

tony.kay20:11:28

we could update the docstring. Won’t hurt to pass a param that no one is expecting

Eric Dvorsak20:11:29

it does seem to work without my patch,

tony.kay20:11:32

that’s a compatible change

tony.kay20:11:55

it’s possible I did something in another layer.

Eric Dvorsak20:11:13

my patch except the value to be a potential fn

Eric Dvorsak20:11:25

the current code expect the whole enumerated-label thing to be a fn

Eric Dvorsak20:11:53

so in the snippet I sent above it works because the whole enumerated labels thing is a fn and not just the values for each label

tony.kay20:11:15

well, but that would be a breaking change for this default formatter at least

tony.kay20:11:31

and the docstring does not say enumerated-labels itself is meant to be a fn

tony.kay20:11:35

not saying it was the perfect choice, just that I can’t change it now.

tony.kay20:11:12

well, I guess it could support being a fn, since that would be a non-breaking change

Eric Dvorsak20:11:13

Sorry I'm not sure I follow you, to recap if we ignore my PR completely this is the situation: the default formatter does this:

{:default (fn [_ value _ column-attribute]
                          (if-let [labels (::attr/enumerated-labels column-attribute)]
                            (labels value)
                            (str value)))}
the docstring says this
A map from enumeration keyword to string (or a `(fn [] string?)
` which is actually
A map from enumeration keyword to string (or a `(fn [value] string?)
`

tony.kay20:11:46

no, you’re misunderstanding the code

tony.kay20:11:00

enumerated labels is a map. Maps are ifn

tony.kay20:11:16

so (labels value) is just (get labels value)

tony.kay20:11:38

The docstring is saying that this should be wrapped how your patch does it

Eric Dvorsak20:11:50

(let [value "active"] (if-let [labels (fn [value] (case value
                                                                               "active" (tr "active")
                                                                               "invited" (tr "invited")))]
                                                   (labels value)
                                                   (str value)))
"active"

Eric Dvorsak20:11:59

(labels value) is (get labels value) or ((fn [value] string?) value)

Eric Dvorsak20:11:33

the code could be slightly more clear but it does work as expected if you consider that the docstring was meant to say (fn [value] string?)

Eric Dvorsak20:11:53

again my patch would have been a completely different semantic: currently enumerated-value can be a map (ifn) or a function (taking one arg) and returning a string. with my patch it would have still be the case but on top of that the result of (enumerated-values value) could have been a fn as well. It seems unecessary . however I might not have the whole context and vision on rad so if you think it's still a good idea to add that feel free to merge the PR, but locally I reverted my change and things work great now that I know that enumerated-value can be a fn that takes value as argument

tony.kay20:11:35

Ah…you’re right, I may have intended it that way. The docstring is ambiguous

tony.kay20:11:24

I patched the docstring

🙌 1
Eric Dvorsak21:11:46

I got a bit too hopeful it does work with reports but then it breaks forms

Eric Dvorsak21:11:19

probably because of enumerated-field:

(defn enumerated-options [{::form/keys [form-instance] :as env} {::attr/keys [qualified-key] :as attribute}]
  (let [{::attr/keys [enumerated-values]} attribute
        enumeration-labels (merge
                            (::attr/enumerated-labels attribute)
                            (comp/component-options form-instance ::form/enumerated-labels qualified-key))]
    ;; TODO: Sorting should be something users control
    (mapv (fn [k]
            {:text  (?! (get enumeration-labels k (name k)))
             :value k}) enumerated-values)))

Eric Dvorsak21:11:54

But it is fixed by changing it to:

(defn enumerated-options [{::form/keys [form-instance] :as env} {::attr/keys [qualified-key] :as attribute}]
  (let [{::attr/keys [enumerated-values]} attribute
        enumerated-labels (or
                           (::attr/enumerated-labels attribute)
                           (comp/component-options form-instance ::form/enumerated-labels qualified-key))
        options (sort-by :text
                         (mapv (fn [k]
                                 {:text  (or (enumerated-labels k) (name k))
                                  :value k})
                               enumerated-values))]
    options))
I can make a PR to rad-semantic-ui if that suits you I don't use a fork of semantic-ui and just have a rewritten UI plugin

tony.kay22:11:42

ok, so obviously I did mean (fn [] string) as the value in the enumerated labels map. {:k (fn [] (tr "k")) …}

tony.kay22:11:16

The ability to make the entire option a (fn [value] ) is also workable, esp since a map is exactly that.

tony.kay22:11:47

I think we can change it to the following and it will not break anything (this is the new docstring for enumerate-labels)…also requires improving the docstring for ::form/enumerated-labels

The labels for the various values an enumeration can take. Can be one of the following:

1. A map from value to label. E.g. {:k "k" ...}
2. A map from value to a `(fn [] string?)`. E.g. {:k #(tr "k") ...}
3. A `(fn [value] string)` E.g. (fn [k] (get my-labels k))

tony.kay22:11:27

and then of course code changes in all relevant places to make sure all three are supported

tony.kay22:11:00

so a global search of the SUI plugin and RAD itself for “enumerated-labels” to catch things like the ::form/enumerated-labels override.

tony.kay22:11:37

they actually don’t appear in very many places

Eric Dvorsak23:11:42

Yeah having the 3 options sounds nice