Skip to content

Instantly share code, notes, and snippets.

@holyjak
Created March 4, 2023 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save holyjak/00556135462c7b1604ae8d6f25e12dcc to your computer and use it in GitHub Desktop.
Save holyjak/00556135462c7b1604ae8d6f25e12dcc to your computer and use it in GitHub Desktop.
Fulcro live coding 3 - Simplify with UISM - files
;; The finished UISM code
(let [cleanup-uism+list (fn cleanup [env]
(-> env
(uism/apply-action (fn [state-map]
(-> state-map
(dissoc :dependencies/id)
(dissoc :ui/show-deps-for))))
(uism/exit)))
event-reset {::uism/handler (fn [env]
(-> env
(uism/assoc-aliased :invalid? false)
(uism/assoc-aliased :actions {})
(uism/activate :state/editing))
)}
event-apply {::uism/handler (fn [env]
(let [actions (uism/alias-value env :actions)
;; Return actions in the *same* order as the dependants (which might be signifiant)
deps-idents-rev (mapv :ident (uism/alias-value env :dependants))
actions-list (mapv (fn [dep-ident] [dep-ident (get actions dep-ident)]) deps-idents-rev)
env' (validate-actions! env)
valid? (not (uism/alias-value env' :invalid?))
{target-ident :ident} (uism/alias-value env :target)]
(if valid?
(-> env'
(uism/trigger-remote-mutation :actor/deps-list `safe-delete-entity
{:ident target-ident
:actions actions-list
::uism/ok-event :event/apply-ok
::uism/error-event :event/apply-error})
(uism/activate :state/executing-apply))
(uism/activate env' :state/fixing))))}
event-cancel {::uism/handler cleanup-uism+list}]
(uism/defstatemachine deps-form
{::uism/actor-names #{:actor/deps-list}
::uism/aliases {:dependants [:actor/deps-list :dependencies/dependants]
:target [:actor/deps-list :dependencies/target]
:actions [:actor/deps-list :ui/actions]
:invalid? [:actor/deps-list :ui/invalid?]}
::uism/states {:initial {::uism/events {::uism/started {::uism/target-state :state/editing}}}
:state/editing {::uism/events {:event/select-action {::uism/handler (fn [{{:keys [action ident]} ::uism/event-data :as env}]
(uism/update-aliased env :actions assoc ident action))}
:event/apply event-apply
:event/cancel event-cancel
:event/reset event-reset ; FIXME rm - tmp event
}}
:state/fixing {::uism/events {:event/select-action {::uism/handler (fn [{{:keys [action ident]} ::uism/event-data :as env}]
(-> env
(uism/update-aliased :actions assoc ident action)
(validate-actions!)))}
:event/apply event-apply
:event/cancel event-cancel
:event/reset event-reset ; FIXME rm - tmp event
}}
:state/executing-apply {::uism/events {:event/reset event-reset ; FIXME rm - tmp event
:event/apply-ok {::uism/handler (fn [{{{body :body} ::uism/mutation-result} ::uism/event-data
::uism/keys [source-actor-ident] ; ] [:dependnecies/id [..]]
:as env}]
(if-let [problem (not-empty (get body `safe-delete-entity))]
(do (toast/toast! (str "Něco se nepovedlo: " problem))
env)
(cleanup-uism+list env)))}
:event/apply-error {::uism/handler cleanup-uism+list}}}
}}))
;; the component using the UISM
(defsc DependenciesList [this
{:dependencies/keys [dependants]
{target-ident :ident target-label :label} :dependencies/target
:ui/keys [actions invalid?] :as props}]
{:ident :dependencies/id
:query [:dependencies/id
{:dependencies/target [:ident :label]}
{:dependencies/dependants [:ident :label]}
:ui/actions :ui/invalid?]}
;; each item: ignore x delete (x none selected)
;; data: map of ident -> action :delete || :ignore
(dom/div
(dom/h1 (str "Nelze smazat "
(entity-label (first target-ident))
" '"
target-label
"' protože jiná data se na to odkazují"))
(dom/h2 "Závislé entity:")
(ui-form {:className "depsForm"}
(dom/div {} (dom/strong "Action:"))
(mapv (fn [{[id-prop id :as ident] :ident
:keys [label]}]
(dom/div {:key (str id) :style {:marginTop 5}}
(ui-form-field {:error (and invalid? (not (get actions ident)))
:style {:display "flex" :alignItems "center"}}
(ui-button-group {:icon true :compact true :size "tiny"}
(ui-button {:onClick #(uism/trigger! this :deps-form :event/select-action {:ident ident :action :delete})
:icon icons/trash-icon
;:negative true
:active (= :delete (get actions ident))
:toggle true :basic true
:title "Delete"})
(ui-button-or {:text "či"})
(ui-button {:onClick #(uism/trigger! this :deps-form :event/select-action {:ident ident :action :ignore})
:icon icons/broken-chain-icon
:active (= :ignore (get actions ident))
:toggle true :basic true
:title "Ignore"}))
(dom/div {:style {:flex 1 :marginLeft "0.3em"}}
(dom/em (entity-label id-prop)) ": "
label " "))))
dependants))
(dom/div {:style {:marginTop "1em"}}
(when invalid?
(ui-message {:error true} "Je třeba zvolit akci pro každou závislot. Zkontrolujte výše uvedený seznam."))
(ui-button {:onClick #(uism/trigger! this :deps-form :event/apply)
:primary true
:disabled (empty? actions)}
"Apply all")
(ui-button {:onClick #(uism/trigger! this :deps-form :event/cancel)}
"Cancel")
; FIXME rm the reset button
(ui-button {:onClick #(uism/trigger! this :deps-form :event/reset)} "Reset"))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment