Fork me on GitHub
#fulcro
<
2024-05-13
>
Eric Dvorsak14:05:40

Is it intentional that set-map-ops return a vector?

(defn set-map-ops
  "Returns an operation that will set all of the k-v pairs from `m` into the
   data model."
  [m]
  [{:op   :assign
    :data m}])
assign and delete in the same ns return a map

tony.kay14:05:10

Ah, don’t remember…it does seem a mistake

tony.kay14:05:59

in fact, it just looks wrong altogether?

tony.kay14:05:33

unless the multimethod implementation looks for it this way?

Eric Dvorsak14:05:34

possibly, I was looking for a way to clear the state of the chart

tony.kay14:05:10

No, I think that op is half-baked…it should be building a vector of assign ops, one per k-v pair 😕

Eric Dvorsak14:05:16

the :assign op

(defmethod run-flat-op :assign [all-data {:keys [data]}]
  (reduce-kv
    (fn [acc path value]
      (cond
        (= :ROOT path) value
        (keyword? path) (assoc acc path value)
        (and (vector? path) (= :ROOT (first path))) (assoc-in acc (rest path) value)
        (vector? path) (assoc-in acc path value)
        :else acc))
    all-data
    data))

tony.kay14:05:43

you’re using the flat data model?

tony.kay14:05:47

instead of the fulcro one?

tony.kay14:05:56

(defmethod run-fulcro-data-op! :assign [app processing-env {:keys [data]}]
  (let [session-id (senv/session-id processing-env)
        local-data (get-in @(state-atom app) (local-data-path session-id))
        aliases    (get local-data :fulcro/aliases)]
    (swap! (state-atom app)
      (fn [all-data]
        (reduce-kv
          (fn assign* [acc path value]
            (let [path (resolve-actors-in-path local-data path)]
              (cond
                (= :ROOT path) (assoc-in acc (local-data-path session-id) value)
                (and (sequential? path) (#{:fulcro/state :fulcro/state-map} (first path))) (assoc-in acc (rest path) value)
                (and (keyword? path) (contains? aliases path)) (assign* acc (get aliases path) value)
                (keyword? path) (assoc-in acc (local-data-path session-id path) value)
                (and (vector? path) (= :ROOT (first path))) (assoc-in acc (into (local-data-path session-id) (rest path)) value)
                (vector? path) (assoc-in acc (into (local-data-path session-id) path) value)
                :else acc)))
          all-data
          data)))))

tony.kay14:05:27

oh wait…it is doing a reduce-kv over the data

Eric Dvorsak14:05:28

I think I'm using the fulcro one then

Eric Dvorsak14:05:58

so if I use :ROOT as path and give it my initial data as value I will have a clear state

tony.kay14:05:40

Ah, the difference is that assign has an API like assoc, and set-map-ops has an API more like merge….but you are right that there is no need for the vector there

tony.kay14:05:48

On your :ROOT question, yes, that sounds right

Eric Dvorsak15:05:10

how do you deal with statechart events that require a route change in the UI? for instance I have:

(on :review :state/closed
                            (script-fn [_ {:keys [new-topic-id]}]
                                       (when new-topic-id
                                         (comp/transact! app [(mutations/route-to-topic {:subject-id new-topic-id})]))))
so my current solution is to call the mutation to route with transact!

tony.kay15:05:57

I personally make my own state that forces the route called rstate…didn’t I talk about this already?

Eric Dvorsak15:05:20

rstate stands for routing-state?

Eric Dvorsak15:05:04

right so you call change-route! in the script-fn (which is actually what my mutation does so I could just get rid of it)

tony.kay15:05:25

Here’s my thinking: Routing is a globally stateful thing. When you’re on a route that is a singular fact in the entire system. My statechart code relies on the UI being in a particular condition when I’m in a state, then it should be in control of that

tony.kay15:05:54

Right, but it becomes part of the state not the transition, which is critical IMO

tony.kay15:05:06

e.g. on-entry of the state

tony.kay15:05:45

The only caveat is if you use allow route change on targets in DR…then you can break things because the statechart will move to the state, but the route won’t

tony.kay15:05:25

which is why I’d suggest moving away from DR features like that (side effects on will-enter and denying routing via allow-route-change?). Move all of that logic into the chart, where it belongs and isn’t peppered all over the place 😄

tony.kay15:05:36

When I wrote DR I was trying to meet immediate needs of users who wanted what it does. But I never much cared for the way it pushes you to program. I’m very rapidly moving towards having statecharts be the primary logic artifacts in my UI. They compose, you can invoke them, they can have parallel regions, etc.

tony.kay15:05:12

I just haven’t refined my approach enough in real code artifacts to publish anything about it, other than the low-level lilbraries