devtools: use add-watch instead of error-prone run macro

--- contrib/devtools/src/carry_devtools/core.cljs
+++ contrib/devtools/src/carry_devtools/core.cljs
@@ -12,7 +12,7 @@
             cljsjs.filesaverjs
             cljs.pprint)
   (:import goog.ui.KeyboardShortcutHandler)
-  (:require-macros [reagent.ratom :refer [reaction run!]]))
+  (:require-macros [reagent.ratom :refer [reaction]]))

 (chrome-devtools/install! [:custom-formatters :sanity-hints])

@@ -183,13 +183,15 @@

                      (dispatch-action ::replay)))

-                 ; start persisting replayable events
-                 (run!
-                   (let [saved-model (-> @model
-                                         (assoc-in [::debugger :highlighted-signal-id] nil)
-                                         (update-in [::debugger :action-events] #(filter :for-replay? %))
-                                         -remove-orphaned-signals)]
-                     (assoc! storage storage-key saved-model)))
+                 ; start persisting for replay
+                 (add-watch model ::debugger-watcher
+                            (fn [_key _atom old-state new-state]
+                              (when (not= (::debugger old-state) (::debugger new-state))
+                                (let [saved-model (-> new-state
+                                                      (assoc-in [::debugger :highlighted-signal-id] nil)
+                                                      (update-in [::debugger :action-events] #(filter :for-replay? %))
+                                                      -remove-orphaned-signals)]
+                                  (assoc! storage storage-key saved-model)))))

                  ; now start app as usual
                  (record-and-dispatch-to-app :on-start nil))
@@ -342,7 +344,7 @@
         highlighted-signal-ids (reaction (into #{@highlighted-signal-id}
                                                (-signal-parent-ids @signal-id->parent-id @highlighted-signal-id)))]
     (-> (carry/track-keys debugger
-                         [:initial-model :replay-mode? :visible? :toggle-visibility-shortcut :action-events])
+                          [:initial-model :replay-mode? :visible? :toggle-visibility-shortcut :action-events])
         (assoc :signal-events (reaction
                                 ; mapv instead of map is essential, without it referenced reactions will be recalculated several times
                                 (mapv #(assoc % :highlighted? (contains? @highlighted-signal-ids (:id %))


update chat formatter

update chat formatter

--- src/cljs/wombats_web_client/components/chat_box.cljs
+++ src/cljs/wombats_web_client/components/chat_box.cljs
@@ -30,8 +30,8 @@

 (defn format-time
   [timestamp]
-  (f/unparse-local (f/formatter-local "h:mm A")
-                   (f/parse-local timestamp)))
+  (f/unparse (f/formatter "h:mm A")
+             (t/to-default-time-zone timestamp)))

 (defn get-username-color [stats username]
   (let [stat-filter-fn (fn [stat] (= (:username stat) username))
@@ -40,7 +40,7 @@
         color-hex (:color-hex (first (filter colors-8-filter-fn colors-8)))]
     color-hex))

-(defn default-message []
+(defn default-message []
   [:li {:class-name "chat-msg"}
    [:span {:class-name "msg-body default"} "Say something already!"]])

@@ -49,14 +49,14 @@
   (fn []
     (let [stats @stats
           messages @messages
-          element (first (array-seq (.getElementsByClassName js/document
+          element (first (array-seq (.getElementsByClassName js/document
                                                              "chat-box-message-container")))]
-
+
       ;; Check if you should auto scroll to the bottom
       (when (and element (= (+ element.scrollTop element.clientHeight) element.scrollHeight))
         ;; On the next tick, scroll the rendered element down
-        (js/setTimeout #(set! (.-scrollTop element)
-                              element.scrollHeight)
+        (js/setTimeout #(set! (.-scrollTop element)
+                              element.scrollHeight)
                        0))

        [:ul {:class-name "chat-box-message-container"}


defining compaction options when creating the table

--- src/clojure/src/leela/blackbox/storage/cassandra.clj
+++ src/clojure/src/leela/blackbox/storage/cassandra.clj
@@ -31,10 +31,17 @@
   (use-keyspace cluster keyspace)
   (when-not (describe-table cluster keyspace :graph)
     (warn "creating table graph")
-    (create-table cluster :graph (column-definitions {:a :blob :b :blob :primary-key [:a :b]})))
+    (create-table
+     cluster :graph
+     (column-definitions {:a :blob :b :blob :primary-key [:a :b]})
+     (with {:compaction {:class "LeveledCompactionStrategy" :sstable_size_in_mb "256"}})))
   (when-not (describe-table cluster keyspace :search)
     (warn "creating table search")
-    (create-table cluster :search (column-definitions {:key :blob :code :int :name :varchar :primary-key [[:key :code] :name]}))))
+    (create-table
+     cluster
+     :search
+     (column-definitions {:key :blob :code :int :name :varchar :primary-key [[:key :code] :name]})
+     (with {:compaction {:class "LeveledCompactionStrategy" :sstable_size_in_mb "256"}}))))

 (defmacro with-connection [[conn endpoint options] & body]
   `(let [~conn (client/connect (client/build-cluster {:contact-points ~endpoint


Check if date input is supported.

Check if date input is supported.

--- src-cljs/pepa/components/document.cljs
+++ src-cljs/pepa/components/document.cljs
@@ -62,23 +62,33 @@
       (callback :document-date date))
     (om/set-state! owner :editing? false)))

+(defn ^:private date-input-supported? []
+  (-> (doto (js/document.createElement "input")
+        (.setAttribute "type" "date"))
+      .-type
+      (= "date")))
+
 (ui/defcomponentmethod meta-value :document-date [[_ date] owner _]
   (init-state [_]
     {:editing? false
      :date (om/value date)})
   (render-state [_ {:keys [editing? date change-callback]}]
-    (if-not editing?
-      (let [value (when date (format-date date))]
+    (let [supported? (date-input-supported?)
+          value (when date (format-date date))]
+      (if-not editing?
         [:span.value {:key "value", :title (str value)
-                      :on-click (fn [e] (om/set-state! owner :editing? true))}
-         (or value "Click to set")])
-      (let [on-submit! (partial store-document-date! owner date)]
-        [:form {:on-submit on-submit! :on-blur on-submit!}
-         [:input {:type "date"
-                  :key "date-input"
-                  :on-change (partial document-date-changed owner)
-                  :value (when date
-                           (date->date-picker-value date))}]]))))
+                      :on-click (fn [e]
+                                  (when supported?
+                                    (om/set-state! owner :editing? true)))}
+         (or value
+             (when supported? "Click to set"))]
+        (let [on-submit! (partial store-document-date! owner date)]
+          [:form {:on-submit on-submit! :on-blur on-submit!}
+           [:input {:type "date"
+                    :key "date-input"
+                    :on-change (partial document-date-changed owner)
+                    :value (when date
+                             (date->date-picker-value date))}]])))))

 (ui/defcomponent meta-item [[prop value] owner _]
   (render-state [_ state]


make header class dynamic for language landing pages

--- frontend/components/header.cljs
+++ frontend/components/header.cljs
@@ -132,7 +132,7 @@
           [:div
            (when flash
              [:div#flash flash])]
-          [:div#navbar
+          [:div#navbar {:class (when (= :language-landing (:navigation-point app)) (get-in app [:navigation-data :language]))}
            [:div.container
             [:div.row
              [:div.span8


(MAINT) Reformatting

(MAINT) Reformatting

--- src/puppetlabs/trapperkeeper/authorization/rules.clj
+++ src/puppetlabs/trapperkeeper/authorization/rules.clj
@@ -12,16 +12,14 @@

 (def Rule
   "An ACL rule, with no less than a matching path, possibly a method list and an acl"
-  {
-   :type Type
+  {:type Type
    :path Pattern
    :method Method
    (schema/optional-key :allow-unauthenticated) schema/Bool
    :acl acl/ACL
    (schema/optional-key :query-params) {schema/Str #{schema/Str}}
    (schema/optional-key :file) schema/Str
-   (schema/optional-key :line) schema/Int
-   })
+   (schema/optional-key :line) schema/Int})

 (def Rules
   "A list of rules"


CMR-3156: Removed temporary logging.

CMR-3156: Removed temporary logging.

--- oracle-lib/src/cmr/oracle/connection.clj
+++ oracle-lib/src/cmr/oracle/connection.clj
@@ -52,15 +52,12 @@
       (info "Database conn info" (db-conn-info-safe-for-logging oracle-store))
       {:ok? false :problem (.getMessage e)})
     (catch java.lang.NoClassDefFoundError e
-      (error "temporary logging:" e)
-      (if (re-matches #".*Could not initialize class oracle.security.*" (.getMessage e))
+      (if (and (shutdown-on-oracle-class-error)
+               (re-matches #".*Could not initialize class oracle.security.*" (.getMessage e)))
         ;; shut down the app so that it could be restarted by puppet
-        (do (error "Caught java.lang.NoClassDefFoundError" e)
-          (when (shutdown-on-oracle-class-error)
-            (System/exit 0)))
-        (throw e)))
-    (catch Throwable e
-      (error "temporary logging, caught throwable:" e))))
+        (do (error "Caught java.lang.NoClassDefFoundError" e ", shutting down...")
+          (System/exit 0))
+        (throw e)))))

 (defn health
   "Returns the oracle health with timeout handling."


CMR-3797: Fixed a tricky bug Jason found.

--- umm-spec-lib/src/cmr/umm_spec/date_util.clj
+++ umm-spec-lib/src/cmr/umm_spec/date_util.clj
@@ -7,9 +7,6 @@
    [cmr.common.time-keeper :as tk]
    [cmr.common.xml.parse :refer :all]
    [cmr.umm-spec.models.umm-common-models :as cmn]))
-
-(def current-date-time
-  (tk/now))

 (def default-date-value "1970-01-01T00:00:00")

@@ -28,7 +25,7 @@
 (defn with-current
   "Returns x if not nil, or else the current-date-time placeholder value."
   ([x]
-   (or x current-date-time)))
+   (or x (tk/now))))

 (defn without-default
   "Returns x if it is not the default date value string."


fix form deletion (#211)

fix form deletion (#211)

--- server/src/spacon/components/form/core.clj
+++ server/src/spacon/components/form/core.clj
@@ -52,7 +52,7 @@
   (let [form-key (URLDecoder/decode (get-in request [:path-params :form-key])
                                     "UTF-8")
         forms (formmodel/find-by-form-key form-key)]
-    (if (< (count (map delete-form-by-id forms)) (count forms))
+    (if (== (count (map delete-form-by-id forms)) (count forms))
       (do
         (mqttapi/publish-scmessage mqtt
                                    "/config/update"


Fix mistake in sum-type doc

Fix mistake in sum-type doc

--- src/active/clojure/sum_type.cljc
+++ src/active/clojure/sum_type.cljc
@@ -398,7 +398,7 @@
      `arg` is the argument to be matched upon.
      `clauses` are pairs of conditions and bodies, e.g.:

-     `(match rgb-color? a
+     `(match rgb-color a
          red? \"red\"
          (make-green a) (str \"Green with \" a)
          blue? \"blue\")


Preserve metadata on in-REPL defn

Preserve metadata on in-REPL defn


Unimportant - commented-out troubleshooting code/notes


remove unused import attribute

remove unused import attribute


Display author information in the card

Display author information in the card


Lower announcement timeout

Lower announcement timeout

--- src/clj/collect_earth_online/views.clj
+++ src/clj/collect_earth_online/views.clj
@@ -63,7 +63,7 @@
                           :width            "100vw"
                           :z-index          "10000"}}
      [:script {:type "text/javascript"}
-      "setTimeout (function () {document.getElementById ('banner') .style.display='none'}, 10000);"]
+      "setTimeout (function () {document.getElementById ('banner') .style.display='none'}, 5000);"]
      [:p {:style {:font-size   "18px"
                   :font-weight "bold"
                   :margin      "0 30px 0 0"}}


display time at discussion list

display time at discussion list

--- src/clj/hsm/controllers/discussion.clj
+++ src/clj/hsm/controllers/discussion.clj
@@ -32,7 +32,7 @@
                 (cutoff (get-in x [:post :text]) 200)]]]
               [:div.col-lg-3 "Users"]
               [:div.col-lg-1 "Count"]
-              [:div.col-lg-2 "Activity"]
+              [:div.col-lg-2 (:published_at x)]
               ]]))))))

 (defn get-discussion


Dont use tc/jsonb-clj for geojson

Dont use tc/jsonb-clj for geojson

--- src/clj/org/openforis/ceo/db/plots.clj
+++ src/clj/org/openforis/ceo/db/plots.clj
@@ -22,9 +22,9 @@
 (defn- prepare-samples-array [plot-id project-id]
   (mapv (fn [{:keys [sample_id sample_geom sampleId geom value]}]
           (merge {:id         sample_id
-                  :sampleGeom (tc/jsonb->clj sample_geom)
+                  :sampleGeom sample_geom
                   :sampleId   sampleId ;TODO I don't think we distinguish between sample_id and sampleId so this could go away
-                  :geom       (tc/jsonb->clj geom)}
+                  :geom       geom}
                  (when (< 2 (count (str value)))
                    {:value (tc/jsonb->clj value)})))
         (call-sql "select_plot_samples" plot-id project-id)))
@@ -37,7 +37,7 @@
      :flagged       (< 0 (or flagged -1))
      :analyses      assigned
      :plotId        plotId
-     :geom          (tc/jsonb->clj geom)
+     :geom          geom
      :extraPlotInfo (dissoc (tc/jsonb->clj extra_plot_info) :gid :lat :lon :plotid)
      :samples       (prepare-samples-array plot_id project-id)}))


test commit

test commit

--- src/clj/rumahsewa141/routes/member.clj
+++ src/clj/rumahsewa141/routes/member.clj
@@ -55,9 +55,11 @@
     (layout/render "member.html" (merge {:username username
                                          :section section
                                          :subsection subsection}
-                                        (if (nil? get-content-fn)
-                                          nil
-                                          (get-content-fn))))))
+                                        nil
+                                        ;; (if (nil? get-content-fn)
+                                        ;;   nil
+                                        ;;   (get-content-fn))
+                                        ))))

 (defn settings-page [subsection req & [get-content-fn]]
   (member-page "settings" get-content-fn req subsection))


test commit

test commit

--- src/clj/rumahsewa141/routes/member.clj
+++ src/clj/rumahsewa141/routes/member.clj
@@ -55,7 +55,6 @@
     (layout/render "member.html" (merge {:username username
                                          :section section
                                          :subsection subsection}
-                                        nil
                                         ;; (if (nil? get-content-fn)
                                         ;;   nil
                                         ;;   (get-content-fn))


Support j.i.File as WebAddress

Support j.i.File as WebAddress

--- src/clj_chrome_devtools/automation.clj
+++ src/clj_chrome_devtools/automation.clj
@@ -127,7 +127,10 @@
   URI
   (as-string [this] (str this))
   URL
-  (as-string [this] (str this)))
+  (as-string [this] (str this))
+  java.io.File
+  (as-string [this]
+    (str (.toURI this))))

 (s/def ::web-address
   (s/or :url (partial instance? URL)


add tran. item memo to tran. form

add tran. item memo to tran. form

--- src/cljs/clj_money/views/accounts.cljs
+++ src/cljs/clj_money/views/accounts.cljs
@@ -538,6 +538,8 @@
                :in-fn (model-in-fn accounts :path)
                :out-fn (fn [v] (if (iterable? v) (first v) v))
                :result-fn (fn [[path id]] path)}]]
+   [:td [:input.form-control {:field :text
+                              :id [:items index :memo]}]]
    [:td [:input.form-control {:field :numeric
                               :id [:items index :credit-quantity]}]]
    [:td [:input.form-control {:field :numeric
@@ -564,6 +566,7 @@
     [:thead
      [:tr
       [:td "Account"]
+      [:td "Memo"]
       [:td "Credit Amount"]
       [:td "Debit Amount"]]]
     [:tbody


Fixed ul in p

Fixed ul in p

--- src/cljs/ikea_clojure_cup/pack_it.cljs
+++ src/cljs/ikea_clojure_cup/pack_it.cljs
@@ -30,9 +30,7 @@
                 [:img {:src "img/itDoesNotFit.png"}]]
            :partial [:div
                      [:img {:src "img/itFitsMayBe.png"}]
-                     [:p "You'll have to remove or get creative with the following products:"
-                      [:ul.list-inside
-                       (map #(vector :li.list-inside (-> % :name str)) (:missing result-state))]]])
+                     [:p "You'll have to remove or get creative with the following products:"]])
          [select-items/trolley-list-contents (reagent/cursor all-state [:trolley])]

          [bootstrap/button-toolbar


use new profile view

use new profile view

--- src/cljs/salava/location/ui/block.cljs
+++ src/cljs/salava/location/ui/block.cljs
@@ -75,7 +75,7 @@
                              (doseq [b (:badges data)]
                                (-> (js/L.latLng. (:lat b) (:lng b))
                                    (js/L.marker. (clj->js {:icon lu/user-icon}))
-                                   (.on "click" #(mo/open-modal [:user :profile] {:user-id (:user_id b)}))
+                                   (.on "click" #(mo/open-modal [:profile :view] {:user-id (:user_id b)}))
                                    (.addTo my-map))))
                            (reset! visible false)))}))
          300))}))


do :after-save callbacks on :after-loaded record

--- src/er_cassandra/model/alia/upsert.clj
+++ src/er_cassandra/model/alia/upsert.clj
@@ -329,20 +329,20 @@
                                (t/extract-uber-key-value entity record))
                               (return nil))

+            ;; gotta make the re-selected record presentable!
+            final-record (t/run-callbacks
+                          session
+                          entity
+                          :after-load
+                          reselected-record)
+
             ;; do any :after-save actions
             _ (t/run-callbacks
                session
                entity
                :after-save
-               reselected-record
-               opts)
-
-            ;; gotta make the re-selected record presentable!
-            final-record (t/run-callbacks
-                          session
-                          entity
-                          :after-load
-                          reselected-record)]
+               final-record
+               opts)]

        (return
         (pair final-record


removing spaces

removing spaces

--- data/celestial/fixtures/data.clj
+++ data/celestial/fixtures/data.clj
@@ -54,7 +54,6 @@
 (def redis-ec2-centos
   (assoc-in (read-fixture "redis-ec2-centos") [:aws :key-name] host))

-
 (def redis-vc-spec (read-fixture "redis-vc-system"))

 (def redis-docker-spec (read-fixture "redis-docker-system"))
@@ -63,8 +62,6 @@

 (def clustered-prox (read-fixture "celestial-cluster"))

-
-
 (def local-conf
   (let [path (me.raynes.fs/expand-home "~/.celestial.edn")]
     (when (me.raynes.fs/exists? path) (slurp-edn path))))


Update to reflect API change

Update to reflect API change

--- minimal-3d-physics/desktop/src-common/minimal_3d_physics/core.clj
+++ minimal-3d-physics/desktop/src-common/minimal_3d_physics/core.clj
@@ -70,7 +70,7 @@
   (fn [screen entities]
     (let [screen (update! screen
                           :renderer (model-batch)
-                          :world (bullet-3d :discrete-dynamics
+                          :world (bullet-3d :rigid
                                             :set-gravity (vector-3 0 -10 0))
                           :attributes (get-environment)
                           :camera (get-camera))]


fix waitForDevice omission

fix waitForDevice omission

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@7437 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -209,6 +209,7 @@

 (defn acq-sleep [interval-ms]
   (set-stage-position (core getFocusDevice) (@state :reference-z-position))
+  (wait-for-device (core getFocusDevice))
   (when (and (@state :init-continuous-focus)
     (not (core isContinuousFocusEnabled)))
       (core enableContinuousFocus true))


Snapshot version

Snapshot version

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.31.0"
+(defproject cook "1.31.1-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


CMR-2595: Making one more performance optimization I noticed for polygon intersection.

--- spatial-lib/src/cmr/spatial/ring_relations.clj
+++ spatial-lib/src/cmr/spatial/ring_relations.clj
@@ -99,11 +99,11 @@
                 ls2 (segments r2)]
             [ls1 ls2]))

-    ;; Are any of the points in ring 2 inside ring 1?
-    (some #(covers-point? r1 %) (:points r2))
-
-    ;; Are any of the points in ring 1 inside ring 2?
-    (some #(covers-point? r2 %) (:points r1))))
+    ;; Is ring 2 inside ring 1? Only one point check is required
+    (covers-point? r1 (first (:points r2)))
+
+    ;; Is ring 1 inside ring 2? Only one point check is required
+    (covers-point? r2 (first (:points r1)))))

 (defn covers-ring?
   "Returns true if the ring covers the other ring."


Fix 'Reload Organizations' button too

Fix 'Reload Organizations' button too

--- src-cljs/frontend/components/add_projects.cljs
+++ src-cljs/frontend/components/add_projects.cljs
@@ -76,7 +76,8 @@
     om/IRender
     (render [_]
       (button/button {:on-click #(raise! owner [:refreshed-user-orgs {}])
-                      :kind :primary}
+                      :kind :primary
+                      :size :medium}
                      "Reload Organizations"))))

 (defn- repo-title [repo link?]


Removing dead code from linux plan pricing.

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -338,9 +338,6 @@
                                          (pm/trial-containers plan)))
             min-slider-val (max 1 (+ (pm/freemium-containers plan) (pm/paid-plan-min-containers plan)))
             max-slider-val (max 80 (* 2 (pm/usable-containers plan)))
-            old-max-slider-val (if (< selected-containers 50)
-                                 80
-                                 (let [n (* 2 selected-containers)] (+ n (- 10 (mod n 10)))))
             selected-paid-containers (max 0 (- selected-containers (pm/freemium-containers plan)))
             osx-total (or (some-> plan :osx :template :price) 0)
             old-total (- (pm/stripe-cost plan) osx-total)
@@ -353,14 +350,13 @@
         (if-not plan
           (cond ;; TODO: fix; add plan
             (nil? plan)
-            [:div.loading-spinner common/spinner]
+              [:div.loading-spinner common/spinner]
             (not (seq plan))
-            [:h3 (str "No plan exists for" org-name "yet. Follow a project to trigger plan creation.")]
-            :else [:h3 "Something is wrong! Please submit a bug report."])
+              [:h3 (str "No plan exists for" org-name "yet. Follow a project to trigger plan creation.")]
+            :else
+              [:h3 "Something is wrong! Please submit a bug report."])

           [:div#edit-plan {:class "pricing.page"}
-           (when (pm/piggieback? plan org-name)
-             (plans-piggieback-plan-notification plan org-name))
            (when-not (config/enterprise?)
              [:fieldset
               [:legend (str "Our pricing is flexible and scales with you. Add as many containers as you want for $"
@@ -381,11 +377,7 @@
                                                         :value (int (.. % -target -value)))}]
                  [:span.new-plan-total (str (pluralize-no-val selected-containers "container") (when-not (config/enterprise?) (str " for " (if (= 0 new-total) "Free!" (str "$" new-total "/month")))))]
                  (when (not (= new-total old-total))
-                   [:span.strikeout {:style {:margin "auto"}} (str "$" old-total "/month")])
-                 (when false                                ;; (pm/grandfathered? plan) ;; I don't
-                   ;; think this is useful anymore.
-                   [:i.fa.fa-question-circle#grandfathered-tooltip-hack
-                    {:title "We've changed plan prices since you signed up, so you're grandfathered in at the old price!"}])]]
+                   [:span.strikeout {:style {:margin "auto"}} (str "$" old-total "/month")])]]
                [:fieldset
                 (if (and (pm/can-edit-plan? plan org-name) (or (config/enterprise?) (pm/paid? plan)))
                   (forms/managed-button


Kill the old sidebar.

Kill the old sidebar.

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -29,34 +29,6 @@
             [inflections.core :as infl :refer [pluralize]])
   (:require-macros [cljs.core.async.macros :as am :refer [go go-loop alt!]]
                    [frontend.utils :refer [html]]))
-
-(defn sidebar [{:keys [subpage plan org-name]} owner]
-  (reify
-    om/IRender
-    (render [_]
-      (letfn [(nav-links [templates]
-                (map (fn [{:keys [page text]} msg]
-                       [:li {:class (when (= page subpage) :active)}
-                        [:a {:href (str "#" (name page))} text]])
-                     (filter #(not (nil? %)) templates)))]
-        (html [:div.span3
-               [:ul.nav.nav-list.well
-                [:li.nav-header "Organization settings"]
-                [:li.divider]
-                [:li.nav-header "Overview"]
-                (nav-links [{:page :projects :text "Projects"}
-                            {:page :users :text "Users"}])
-                [:li.nav-header "Plan"]
-                (when plan
-                  (if (pm/can-edit-plan? plan org-name)
-                    (let [links [{:page :containers :text "Adjust containers"}
-                                 {:page :organizations :text "Organizations"}]
-                          links (if (pm/paid? plan)
-                                  (into links [{:page :billing :text "Billing info"}
-                                               {:page :cancel :text "Cancel"}])
-                                  links)]
-                      (nav-links links))
-                    (nav-links [{:page :plan :text "Choose plan"}])))]])))))

 (defn non-admin-plan [{:keys [org-name login]} owner]
   (reify
@@ -967,39 +939,16 @@
    :billing billing
    :cancel cancel})

-(defn determine-subpage
-  "Determines which subpage we should show the user. If they have
-   a plan, then we don't want to show them the plan page; if they
-   don't have a plan, then we don't want to show them the invoices page."
-  [subpage plan org-name]
-  (cond (#{:users :projects} subpage)
-        subpage
-
-        (and plan
-             (pm/can-edit-plan? plan org-name)
-             (= subpage :plan))
-        :containers
-
-        (and plan
-             (not (pm/can-edit-plan? plan org-name))
-             (#{:containers :organizations :billing :cancel} subpage))
-        :plan
-
-        :else subpage))
-
 (defn org-settings [app owner]
   (reify
     om/IRender
     (render [_]
-      (let [requested-subpage (get app :org-settings-subpage :projects)
-            org-data (get-in app state/org-data-path)
-            plan (get-in app state/org-plan-path)
-            subpage (determine-subpage requested-subpage plan (:name org-data))]
+      (let [org-data (get-in app state/org-data-path)
+            subpage (or (get app :org-settings-subpage) :projects)]
         (html [:div.container-fluid.org-page
                (if-not (:loaded org-data)
                  [:div.loading-spinner common/spinner]
                  [:div.row-fluid
-                  (om/build sidebar {:subpage subpage :plan plan :org-name (:name org-data)})
                   [:div.span9
                    (om/build common/flashes (get-in app state/error-message-path))
                    [:div#subpage


Register incise middlewares separately.

Register incise middlewares separately.

--- src/incise/middlewares/impl/incise.clj
+++ src/incise/middlewares/impl/incise.clj
@@ -96,14 +96,6 @@
     (load-parsers-and-layouts)
     (handler request)))

-(defn wrap-incise
-  "A middleware which does everything necessary for incise. It loads parsers and
-  layouts, and eagerly parses files. It even reparses files when Clojure source
-  is changed (e.g. a layout is modified)."
-  [handler]
-  (-> handler
-      (wrap-incise-parse)
-      (wrap-reset-modified-files-with-source-change)
-      (wrap-parsers-reload)))
-
-(register 000 wrap-incise)
+(register   0 wrap-incise-parse)
+(register  50 wrap-reset-modified-files-with-source-change)
+(register 100 wrap-parsers-reload)


Prettied up the query syntax.

Prettied up the query syntax.

--- src/appengine_magic/services/datastore.clj
+++ src/appengine_magic/services/datastore.clj
@@ -14,6 +14,8 @@
 ;;; ----------------------------------------------------------------------------

 (defonce *datastore-service* (atom nil))
+
+
 (defonce *current-transaction* nil)

@@ -25,24 +27,6 @@
 (defonce *datastore-implicit-transaction-policy-map*
   {:auto ImplicitTransactionManagementPolicy/AUTO
    :none ImplicitTransactionManagementPolicy/NONE})
-
-
-(defonce *filter-operator-map*
-  {:eq Query$FilterOperator/EQUAL
-   :gt Query$FilterOperator/GREATER_THAN
-   :ge Query$FilterOperator/GREATER_THAN_OR_EQUAL
-   :in Query$FilterOperator/IN
-   :lt Query$FilterOperator/LESS_THAN
-   :le Query$FilterOperator/LESS_THAN_OR_EQUAL
-   :ne Query$FilterOperator/NOT_EQUAL})
-
-
-(defonce *sort-direction-map*
-  {:ascending Query$SortDirection/ASCENDING
-   :asc Query$SortDirection/ASCENDING
-   :descending Query$SortDirection/DESCENDING
-   :dsc Query$SortDirection/DESCENDING
-   :desc Query$SortDirection/DESCENDING})

@@ -183,7 +167,18 @@
     (.put (get-datastore-service) entities)))

-(defn- make-query-object [kind ancestor filter sort keys-only?]
+
+;;; ----------------------------------------------------------------------------
+;;; query helper objects and functions
+;;; ----------------------------------------------------------------------------
+
+(defrecord QueryFilter [operator property value])
+
+
+(defrecord QuerySort [property direction])
+
+
+(defn- make-query-object [kind ancestor filters sorts keys-only?]
   (let [kind (cond (nil? kind) kind
                    (string? kind) kind
                    (extends? EntityProtocol kind) (unqualified-name kind)
@@ -194,42 +189,43 @@
         query-object (cond (and (nil? kind) (nil? ancestor-key-object)) (Query.)
                            (nil? kind) (Query. ancestor-key-object)
                            (nil? ancestor-key-object) (Query. kind)
-                           :else (Query. kind ancestor-key-object))
-        ;; normalize filter criteria into a vector (even if there's just one)
-        filter (if (every? sequential? filter) filter (vector filter))
-        ;; normalize sort criteria into a vector (even if there's just one)]
-        sort (if (every? sequential? sort) sort (vector sort))]
+                           :else (Query. kind ancestor-key-object))]
     (when keys-only?
       (.setKeysOnly query-object))
-    (doseq [[filter-operator filter-property-kw filter-value] filter]
-      (cond
-       ;; valid filter provided
-       (and (not (nil? filter-operator))
-            (not (nil? filter-property-kw))
-            (not (nil? filter-value))
-            (keyword? filter-property-kw))
-       (let [op-object (get *filter-operator-map* filter-operator)
-             filter-property (.substring (str filter-property-kw) 1)]
-         (.addFilter query-object filter-property op-object filter-value))
-       ;; no filter definition
-       (and (nil? filter-operator) (nil? filter-property-kw) (nil? filter-value))
-       nil
-       ;; invalid filter
-       :else (throw (RuntimeException. "invalid filter specified in query"))))
-    (doseq [[sort-property-kw sort-direction] sort]
-      (cond
-       ;; valid sort provided
-       (and (not (nil? sort-property-kw))
-            (not (nil? sort-direction))
-            (keyword? sort-property-kw))
-       (let [sort-property (.substring (str sort-property-kw) 1)
-             sort-direction-object (get *sort-direction-map* sort-direction)]
-         (.addSort query-object sort-property sort-direction-object))
-       ;; no sort definition
-       (and (nil? sort-property-kw) (nil? sort-direction))
-       nil
-       ;; invalid sort
-       :else (throw (RuntimeException. "invalid sort specified in query"))))
+    ;; prepare filters
+    (doseq [current-filter filters]
+      (let [filter-operator (:operator current-filter)
+            filter-property-kw (:property current-filter)
+            filter-value (:value current-filter)]
+        (cond
+         ;; valid filter provided
+         (and (not (nil? filter-operator))
+              (not (nil? filter-property-kw))
+              (not (nil? filter-value))
+              (keyword? filter-property-kw))
+         (let [filter-property (.substring (str filter-property-kw) 1)]
+           (.addFilter query-object filter-property filter-operator filter-value))
+         ;; no filter definition
+         (and (nil? filter-operator) (nil? filter-property-kw) (nil? filter-value))
+         nil
+         ;; invalid filter
+         :else (throw (RuntimeException. "invalid filter specified in query")))))
+    ;; prepare sorts
+    (doseq [current-sort sorts]
+      (let [sort-property-kw (:property current-sort)
+            sort-direction (:direction current-sort)]
+        (cond
+         ;; valid sort provided
+         (and (not (nil? sort-property-kw))
+              (not (nil? sort-direction))
+              (keyword? sort-property-kw))
+         (let [sort-property (.substring (str sort-property-kw) 1)]
+           (.addSort query-object sort-property sort-direction))
+         ;; no sort definition
+         (and (nil? sort-property-kw) (nil? sort-direction))
+         nil
+         ;; invalid sort
+         :else (throw (RuntimeException. "invalid sort specified in query")))))
     query-object))

@@ -344,14 +340,12 @@
              (throw err#))))))

-(defn query [& {:keys [kind ancestor filter sort keys-only?
-                       count-only? in-transaction?
-                       limit offset
-                       start-cursor end-cursor ; TODO: Implement this.
-                       prefetch-size chunk-size]
-                :or {keys-only? false, filter [[]], sort [[]],
-                     count-only? false, in-transaction? false}}]
-  (let [query-object (make-query-object kind ancestor filter sort keys-only?)
+(defn query* [kind ancestor filters sorts keys-only?
+              count-only? in-transaction?
+              limit offset
+              start-cursor end-cursor
+              prefetch-size chunk-size]
+  (let [query-object (make-query-object kind ancestor filters sorts keys-only?)
         fetch-options-object (make-fetch-options-object limit offset prefetch-size chunk-size)
         prepared-query (if (and in-transaction? *current-transaction*)
                            (.prepare (get-datastore-service) *current-transaction*
@@ -360,3 +354,47 @@
     (if count-only?
         (.countEntities prepared-query)
         (seq (.asIterable prepared-query fetch-options-object)))))
+
+
+(defmacro query [& {:keys [kind ancestor filter sort keys-only?
+                           count-only? in-transaction?
+                           limit offset
+                           start-cursor end-cursor ; TODO: Implement this.
+                           prefetch-size chunk-size]
+                    :or {keys-only? false, filter [], sort [],
+                         count-only? false, in-transaction? false}}]
+  ;; Normalize :filter and :sort keywords (into lists, even if only one is gen),
+  ;; then turn them into QueryFilter and QuerySort objects.
+  (let [filter (if (every? sequential? filter) filter (vector filter))
+        filter `(list ~@(map (fn [[op k v]] `(list (keyword '~op) ~k ~v)) filter))
+        sort (if (sequential? sort) sort (vector sort))]
+    `(let [filter# (map (fn [[sym# prop-kw# prop-val#]]
+                          (QueryFilter. (condp = sym#
+                                            := Query$FilterOperator/EQUAL
+                                            :> Query$FilterOperator/GREATER_THAN
+                                            :>= Query$FilterOperator/GREATER_THAN_OR_EQUAL
+                                            :in Query$FilterOperator/IN
+                                            :< Query$FilterOperator/LESS_THAN
+                                            :<= Query$FilterOperator/LESS_THAN_OR_EQUAL
+                                            :! Query$FilterOperator/NOT_EQUAL
+                                            :!= Query$FilterOperator/NOT_EQUAL
+                                            :<> Query$FilterOperator/NOT_EQUAL)
+                                        prop-kw# prop-val#))
+                        ~filter)
+           sort# (map (fn [sort-spec#]
+                        (if (sequential? sort-spec#)
+                            (let [[sort-property# sort-dir-spec#] sort-spec#
+                                  sort-dir# (condp = sort-dir-spec#
+                                                :asc Query$SortDirection/ASCENDING
+                                                :ascending Query$SortDirection/ASCENDING
+                                                :dsc Query$SortDirection/DESCENDING
+                                                :desc Query$SortDirection/DESCENDING
+                                                :descending Query$SortDirection/DESCENDING)]
+                              (QuerySort. sort-property# sort-dir#))
+                            (QuerySort. sort-spec# Query$SortDirection/ASCENDING)))
+                      ~sort)]
+       (query* ~kind ~ancestor filter# sort# ~keys-only?
+               ~count-only? ~in-transaction?
+               ~limit ~offset
+               ~start-cursor ~end-cursor
+               ~prefetch-size ~chunk-size))))


Fixes migrations timestamps

Fixes migrations timestamps

- Timestamps are in "yyyyMMddHHmmssSSS" format

--- src/larva/frameworks/luminus/stuff.clj
+++ src/larva/frameworks/luminus/stuff.clj
@@ -44,8 +44,7 @@
    ["test/{{sanitized}}/test/handler.clj" "core/test/handler.clj"]])

 (defn- get-migration-timestamp []
-  ;; TODO: This should always return timestamp string of fixed length
-  (.format (java.text.SimpleDateFormat. "yyyyMMddHHmmssSS")
+  (.format (java.text.SimpleDateFormat. "yyyyMMddHHmmssSSS")
            (java.util.Date.)))

 (defn- relational-db-queries [additional-or-not key]


Fix typo in comments (#23)

Fix typo in comments (#23)

--- src/leiningen/new/devcards/project.clj
+++ src/leiningen/new/devcards/project.clj
@@ -33,7 +33,7 @@
                         :figwheel { :devcards true  ;; <- note this
                                    ;; :open-urls will pop open your application
                                    ;; in the default browser once Figwheel has
-                                   ;; started and complied your application.
+                                   ;; started and compiled your application.
                                    ;; Comment this out once it no longer serves you.
                                    :open-urls ["http://localhost:3449/cards.html"]}
                         :compiler { :main       "{{name}}.core"


bumping version

bumping version

--- src/leiningen/new/figwheel/project.clj
+++ src/leiningen/new/figwheel/project.clj
@@ -11,7 +11,7 @@
                  [om "0.6.2"]]

   :plugins [[lein-cljsbuild "1.0.3"]
-            [lein-figwheel "0.1.2-SNAPSHOT"]]
+            [lein-figwheel "0.1.3-SNAPSHOT"]]

   :cljsbuild {
               :builds [{ :source-paths ["src"]


Update Project.clj with latest `re-frame-trace`

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -55,7 +55,7 @@
   :profiles
   {:dev
    {:dependencies [[binaryage/devtools "0.9.4"]{{#trace?}}
-                   [day8.re-frame/trace "0.1.18"]{{/trace?}}{{#cider?}}
+                   [day8.re-frame/trace "0.1.19"]{{/trace?}}{{#cider?}}
                    [figwheel-sidecar "0.5.13"]
                    [com.cemerick/piggieback "0.2.2"]{{/cider?}}{{#re-frisk?}}
                    [re-frisk "0.5.3"]{{/re-frisk?}}]


Added cider-nrepl lein plugin.

Added cider-nrepl lein plugin.

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -18,8 +18,9 @@
                  [re-pressed "0.3.1"]{{/re-pressed?}}{{#breaking-point?}}
                  [breaking-point "0.1.2"]{{/breaking-point?}}]

-  :plugins [[lein-shadow "0.3.1"]
-            {{#garden?}}[lein-garden "0.3.0"]{{/garden?}}{{#less?}}
+  :plugins [{{#cider?}}[cider/cider-nrepl "0.25.6"]{{/cider?}}
+            [lein-shadow "0.3.1"]{{#garden?}}
+            [lein-garden "0.3.0"]{{/garden?}}{{#less?}}
             [lein-less "1.7.5"]{{/less?}}
             [lein-shell "0.5.0"]]

@@ -48,7 +49,7 @@
 {{/less?}}

   :shadow-cljs {:nrepl {:port 8777}
-
+
                 :builds {:app {:target :browser
                                :output-dir "resources/public/js/compiled"
                                :asset-path "/js/compiled"
@@ -79,14 +80,14 @@
                          {:target :karma
                           :ns-regexp "-test$"
                           :output-to "target/karma-test.js"}{{/test?}}}}
-
+
   :shell {:commands {"karma" {:windows         ["cmd" "/c" "karma"]
                               :default-command "karma"}
                      "open"  {:windows         ["cmd" "/c" "start"]
                               :macosx          "open"
                               :linux           "xdg-open"}}}

-  :aliases {"dev"          ["do"
+  :aliases {"dev"          ["do"
                             ["shell" "echo" "\"DEPRECATED: Please use lein watch instead.\""]
                             ["watch"]]
             "watch"        ["with-profile" "dev" "do"
@@ -118,7 +119,7 @@
     :source-paths ["dev"]}

    :prod {}
-
+
    {{#handler?}}
    :uberjar {:source-paths ["env/prod/clj"]
              :omit-source  true


replace function with fn composition.

replace function with fn composition.


moved url-keyword

moved url-keyword

--- src/cljs/infinitelives/pixi/resources.cljs
+++ src/cljs/infinitelives/pixi/resources.cljs
@@ -77,22 +77,12 @@
 (defn get-texture [key scale]
   (scale (key @!textures)))

-
-(defn url-keyword [url]
-  (-> url
-      (.split "/")
-      last
-      (.split ".")
-      first
-      keyword))
-
-
 ;; setup a pixi texture keyed by the tail of its filename
 (defn- register-texture
   [url img]
   (when (string/ends-with? url ".png")
     (swap! !textures
-           assoc (url-keyword url)
+           assoc (string/url-keyword url)
            {
             :linear
             (PIXI/Texture.fromImage


simplify event-relay

simplify event-relay

--- src/cljx/jamesmacaulay/zelkova/signal.cljx
+++ src/cljx/jamesmacaulay/zelkova/signal.cljx
@@ -16,14 +16,13 @@
   (:require-macros [cljs.core.async.macros :refer [go go-loop]]))

 (defn- event-relay
-  "takes a sequence of topics, and returns an input signal which relays matching events as messages to its children"
-  [topics]
-  (let [topics (if (set? topics) topics (set topics))]
-    {:sources [:events]
-     :relayed-event-topics topics
-     :msg-fn (fn [prev [event]]
-               (when (contains? topics (impl/topic event))
-                 (impl/->Fresh (impl/value event))))}))
+  "takes a topic, and returns an input signal which relays matching events as messages to its children"
+  [topic]
+  {:sources [:events]
+   :relayed-event-topic topic
+   :msg-fn (fn [prev [event]]
+             (when (= topic (impl/topic event))
+               (impl/->Fresh (impl/value event))))})

 (defmulti ^:private value-source->events-fn
   "Takes some asynchronous `source` of values, plus an event `topic`, and returns
@@ -66,12 +65,12 @@
   ([init] (input init (keyword (gensym))))
   ([init topic]
    (impl/map->Signal {:init init
-                      :message-emitter (event-relay #{topic})}))
+                      :message-emitter (event-relay topic)}))
   ([init topic value-source]
    (let [event-channel-fn (value-source->events-fn value-source
                                                    topic)]
      (impl/map->Signal {:init init
-                        :message-emitter (event-relay #{topic})
+                        :message-emitter (event-relay topic)
                         :event-sources {topic event-channel-fn}}))))

 (defn constant
@@ -198,7 +197,7 @@
     (impl/map->Signal {:init (:init source)
                        :deps [source]
                        :event-sources {topic events-channel-fn}
-                       :message-emitter (event-relay #{topic})})))
+                       :message-emitter (event-relay topic)})))

 (defn mergeseq
   "Takes a sequence of signals `sigs`, and returns a new signal which relays fresh


Improved handling of queries which filter by other entities.

--- src/appengine_magic/services/datastore.clj
+++ src/appengine_magic/services/datastore.clj
@@ -205,7 +205,10 @@
               (not (nil? filter-property-kw))
               (not (nil? filter-value))
               (keyword? filter-property-kw))
-         (let [filter-property (.substring (str filter-property-kw) 1)]
+         (let [filter-property (.substring (str filter-property-kw) 1)
+               filter-value (if (extends? EntityProtocol (class filter-value))
+                                (get-key-object filter-value)
+                                filter-value)]
            (.addFilter query-object filter-property filter-operator filter-value))
          ;; no filter definition
          (and (nil? filter-operator) (nil? filter-property-kw) (nil? filter-value))


fix broken font tint

fix broken font tint

--- src/cljs/infinitelives/pixi/pixelfont.cljs
+++ src/cljs/infinitelives/pixi/pixelfont.cljs
@@ -95,7 +95,7 @@
                                        xhandle 0.5
                                        yhandle 0.5}}]
   (s/make-container
-   :children (make-char-sprite-set font-key text tint)
+   :children (make-char-sprite-set font-key text :tint tint)
    :particle (not tint)
    :scale scale
    :rotation rotation


use new func

use new func

--- src/cljs/infinitelives/pixi/pixelfont.cljs
+++ src/cljs/infinitelives/pixi/pixelfont.cljs
@@ -74,26 +74,7 @@
                                        yhandle 0.5}}]
   (let [font (get-font font-key)]
     (s/make-container
-     (loop [[c & l] (seq text)
-            xp 0 yp 0
-            last-c nil ;; remember last character for kerning
-            sprite-set []]
-       (let [char ((:font font) c)
-             {:keys [texture pos size]} char
-             [x y] pos
-             [w h] size
-             pair (str last-c c)
-             koff ((:kerning font) pair)
-             ]
-         (if (nil? char)
-           ;; if character is not present in font map, put a space
-           (when (seq l)
-             (recur l (+ xp (:space font)) yp c sprite-set))
-
-           (let [sprite (s/make-sprite texture :x (+ xp koff) :y yp :xhandle 0 :yhandle 0 :tint tint :scale 1)]
-             (if (seq l)
-               (recur l (+ xp w 1.0 koff) yp c (conj sprite-set sprite))
-               (conj sprite-set sprite))))))
+     (make-char-sprite-set font-key text)
      :particle (not tint)
      :scale scale
      :rotation rotation


format files 5

format files 5

--- src/com/wsscode/pathom/fulcro/network.cljs
+++ src/com/wsscode/pathom/fulcro/network.cljs
@@ -23,12 +23,12 @@

   fulcro.network/FulcroRemoteI
   (transmit [this {::fulcro.network/keys [edn ok-handler error-handler progress-handler]}]
-            (go
-              (try
-                (ok-handler {:transaction edn :body (<?maybe (parser {} edn))})
-                (catch :default e
-                  (js/console.error "PathomRemote error:" e)
-                  (error-handler {:body e}))))))
+    (go
+      (try
+        (ok-handler {:transaction edn :body (<?maybe (parser {} edn))})
+        (catch :default e
+          (js/console.error "PathomRemote error:" e)
+          (error-handler {:body e}))))))

 (defn pathom-remote
   "Create a Fulcro remote that will use a Pathom async parser to process the query."
@@ -59,68 +59,68 @@
 (defrecord TransformNetwork [network options]
   fulcro.network/NetworkBehavior
   (serialize-requests? [_]
-                       (try
-                         (fulcro.network/serialize-requests? network)
-                         (catch :default _ true)))
+    (try
+      (fulcro.network/serialize-requests? network)
+      (catch :default _ true)))

   fulcro.network/FulcroNetwork
   (send [_ edn ok error]
-        (let [{::keys [transform-query transform-response transform-error transform-transmission app*]
-               :or    {transform-query    (fn [_ x] x)
-                       transform-response (fn [_ x] x)
-                       transform-error    (fn [_ x] x)}} options
-              req-id (random-uuid)
-              env    {::request-id req-id
-                      ::app        @app*}]
-          (if-let [edn' (transform-query env edn)]
-            (if transform-transmission
-              (transform-transmission edn'
-                                      (fn [edn']
-                                        (fulcro.network/send network edn'
-                                                             #(->> % (transform-response env) ok)
-                                                             #(->> % (transform-error env) error))))
-              (fulcro.network/send network edn'
-                                   #(->> % (transform-response env) ok)
-                                   #(->> % (transform-error env) error)))
-            (ok nil))))
+    (let [{::keys [transform-query transform-response transform-error transform-transmission app*]
+           :or    {transform-query    (fn [_ x] x)
+                   transform-response (fn [_ x] x)
+                   transform-error    (fn [_ x] x)}} options
+          req-id (random-uuid)
+          env    {::request-id req-id
+                  ::app        @app*}]
+      (if-let [edn' (transform-query env edn)]
+        (if transform-transmission
+          (transform-transmission edn'
+                                  (fn [edn']
+                                    (fulcro.network/send network edn'
+                                      #(->> % (transform-response env) ok)
+                                      #(->> % (transform-error env) error))))
+          (fulcro.network/send network edn'
+            #(->> % (transform-response env) ok)
+            #(->> % (transform-error env) error)))
+        (ok nil))))

   (start [this]
-         (fulcro.network/start network)
-         this))
+    (fulcro.network/start network)
+    this))

 (defrecord TransformRemoteI [network options]
   fulcro.network/NetworkBehavior
   (serialize-requests? [_]
-                       (try
-                         (fulcro.network/serialize-requests? network)
-                         (catch :default _ true)))
+    (try
+      (fulcro.network/serialize-requests? network)
+      (catch :default _ true)))

   fulcro.network/FulcroRemoteI
   (transmit [this {::fulcro.network/keys [edn ok-handler error-handler progress-handler]}]
-            (let [{::keys [transform-query transform-response transform-error
-                           transform-progress transform-transmission app*]
-                   :or    {transform-query    (fn [_ x] x)
-                           transform-response (fn [_ x] x)
-                           transform-error    (fn [_ x] x)
-                           transform-progress (fn [_ x] x)}} options
-                  req-id (random-uuid)
-                  env    {::request-id req-id
-                          ::app        @app*}]
-              (if-let [edn' (transform-query env edn)]
-                (if transform-transmission
-                  (transform-transmission env edn'
-                                          (fn [edn']
-                                            (fulcro.network/transmit network
-                                                                     {::fulcro.network/edn              edn'
-                                                                      ::fulcro.network/ok-handler       (fn [response] (ok-handler (update response :body #(transform-response env %))))
-                                                                      ::fulcro.network/error-handler    (fn [error] (error-handler (update error :body #(transform-error env %))))
-                                                                      ::fulcro.network/progress-handler (fn [progress] (progress-handler (transform-progress env progress)))})))
-                  (fulcro.network/transmit network
-                                           {::fulcro.network/edn              edn'
-                                            ::fulcro.network/ok-handler       (fn [response] (ok-handler (update response :body #(transform-response env %))))
-                                            ::fulcro.network/error-handler    (fn [error] (error-handler (update error :body #(transform-error env %))))
-                                            ::fulcro.network/progress-handler (fn [progress] (progress-handler (transform-progress env progress)))}))
-                (ok-handler nil))))
+    (let [{::keys [transform-query transform-response transform-error
+                   transform-progress transform-transmission app*]
+           :or    {transform-query    (fn [_ x] x)
+                   transform-response (fn [_ x] x)
+                   transform-error    (fn [_ x] x)
+                   transform-progress (fn [_ x] x)}} options
+          req-id (random-uuid)
+          env    {::request-id req-id
+                  ::app        @app*}]
+      (if-let [edn' (transform-query env edn)]
+        (if transform-transmission
+          (transform-transmission env edn'
+                                  (fn [edn']
+                                    (fulcro.network/transmit network
+                                      {::fulcro.network/edn              edn'
+                                       ::fulcro.network/ok-handler       (fn [response] (ok-handler (update response :body #(transform-response env %))))
+                                       ::fulcro.network/error-handler    (fn [error] (error-handler (update error :body #(transform-error env %))))
+                                       ::fulcro.network/progress-handler (fn [progress] (progress-handler (transform-progress env progress)))})))
+          (fulcro.network/transmit network
+            {::fulcro.network/edn              edn'
+             ::fulcro.network/ok-handler       (fn [response] (ok-handler (update response :body #(transform-response env %))))
+             ::fulcro.network/error-handler    (fn [error] (error-handler (update error :body #(transform-error env %))))
+             ::fulcro.network/progress-handler (fn [progress] (progress-handler (transform-progress env progress)))}))
+        (ok-handler nil))))

   (abort [this abort-id]
          (fulcro.network/abort network abort-id)))


local tombstone prevention for primary-table upsert

--- src/er_cassandra/model/alia/unique_key.clj
+++ src/er_cassandra/model/alia/unique_key.clj
@@ -17,7 +17,8 @@
     [lookup :as l]]
    [prpr.promise :as pr :refer [ddo]]
    [schema.core :as s]
-   [taoensso.timbre :refer [info warn]])
+   [taoensso.timbre :refer [info warn]]
+   [er-cassandra.model.alia.minimal-change :as min.ch])
   (:import
    [er_cassandra.model.types Entity]
    [er_cassandra.model.model_session ModelSession]))
@@ -396,11 +397,24 @@
          nok-old-record (select-keys
                          (without-unique-keys entity old-record)
                          (keys nok-record))
-         ;; if the no-key part of the old-record
-         ;; is identical to the record we don't need
-         ;; to do anything
-         noop? (= nok-record nok-old-record)]
-     (if noop?
+
+         ;; we will actually upsert the minimum change, with
+         ;; any unchanged cols removed
+         min-change (min.ch/minimal-change-for-table
+                     (:primary-table entity)
+                     nok-old-record
+                     nok-record)
+
+         ;; (warn "upsert-primary-record-without-unique-keys"
+         ;;       {:primary-table (:primary-table entity)
+         ;;        :old-record old-record
+         ;;        :record record
+         ;;        :nok-old-record nok-old-record
+         ;;        :nok-record nok-record
+         ;;        :min-change min-change})
+
+         ]
+     (if (nil? min-change)
        (return deferred-context nok-record)
        (ddo [:let [primary-table-name (get-in entity [:primary-table :name])
                    primary-table-key (get-in entity [:primary-table :key])
@@ -415,13 +429,13 @@
                                if-not-exists
                                (r/insert session
                                          primary-table-name
-                                         nok-record
+                                         min-change
                                          (fns/opts-remove-timestamp opts))

                                (and (not if-exists) (not only-if))
                                (r/insert session
                                          primary-table-name
-                                         nok-record
+                                         min-change
                                          opts)

                                :else ;; only-if
@@ -443,7 +457,7 @@
                                 session
                                 primary-table-name
                                 primary-table-key
-                                nok-record
+                                min-change
                                 (fns/opts-remove-timestamp opts))

                                insert?