uri encoding fix

uri encoding fix

--- src/cljs/salava/core/ui/share.cljs
+++ src/cljs/salava/core/ui/share.cljs
@@ -12,7 +12,7 @@
 (def video-link-en "<iframe width=\"250\" height=\"250\" src=\"https://www.youtube.com/embed/YJJ8lZshqbY\" frameborder=\"0\"></iframe>")

 (defn clipboard-button [target status]
-
+
   (let [clipboard-atom (atom nil)]
     (create-class
      {:display-name "clipboard-button"
@@ -106,7 +106,7 @@
                                   (add-to-profile-image)]
                             [:a {:href "https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME" :target "_blank"} (str " " (t :core/Sharelinkedinclickhere) ".")]]]]
                          [:div.row
-
+
                           [:div.col-md-6.copy-boxes
                            [:form {:class "form-horizontal"}
                             [input-button (t :core/Certificationname)  "name" name]
@@ -191,7 +191,7 @@
              :href     "#"
              :on-click (fn []
                          (do
-
+
                            #_(-> (js* "$('#reagent-modal .modal-dialog')")
                                (.addClass "modal-lg" )
                                (.removeClass "modal-sm"))
@@ -204,7 +204,7 @@
          (t :core/Addtoprofile)]]
        [:div (str (t :core/Sharelinkedinupdate) ":") ]
        [:div
-        [:a {:class "btn btn-oauth btn-linkedin" :href (str "https://www.linkedin.com/shareArticle?mini=true&url=" url "&title=" title "&summary=" (js/encodeURIComponent (str site-name ": " title)) "&source=" hashtag) :rel "nofollow" :target "_blank"}
+        [:a {:class "btn btn-oauth btn-linkedin" :href (str "https://www.linkedin.com/shareArticle?mini=true&url=" url "&title=" (js/encodeURIComponent title) "&summary=" (js/encodeURIComponent (str site-name ": " title)) "&source=" hashtag) :rel "nofollow" :target "_blank"}
          [:i {:class "fa fa-linkedin"}]
          (t :badge/Share)]
         ]]]
@@ -266,7 +266,7 @@
                 :target "_blank"}
             [:i {:title "LinkedIn Add to Profile" :class "inprofile fa fa-linkedin-square"}]]
          [:div.share-button
-          [:a {:href (str "https://www.linkedin.com/shareArticle?mini=true&url=" url "&title=" title "&summary=" (js/encodeURIComponent (str site-name ": " title)) "&source=" hashtag) :target "_blank"}
+          [:a {:href (str "https://www.linkedin.com/shareArticle?mini=true&url=" url "&title=" (js/encodeURIComponent title) "&summary=" (js/encodeURIComponent (str site-name ": " title)) "&source=" hashtag) :target "_blank"}
            [:i {:title "LinkedIn Share" :class "fa fa-linkedin-square"}]]]
          )
        ]
@@ -274,10 +274,10 @@
        [google-plus url]]
       [:div.share-button
        [:a {:href (str "https://www.facebook.com/sharer/sharer.php?u=" url) :target "_blank"} [:i {:class "fa fa-facebook-square"}]]]
-
+
       [:div.share-button
        (if is-badge?
-         [:a {:href            (str "https://www.pinterest.com/pin/create/button/?url=" url "&media=" (base-url) "/" image-file "&description=" title)
+         [:a {:href            (str "https://www.pinterest.com/pin/create/button/?url=" url "&media=" (base-url) "/" image-file "&description=" title)
               :data-pin-do     "buttonPin"
               :data-pin-custom "true"
               :target "_blank"


Refactored timing code.

Refactored timing code.

--- src/cmr/dev/env/manager/timing.clj
+++ src/cmr/dev/env/manager/timing.clj
@@ -1,58 +1,62 @@
 (ns cmr.dev.env.manager.timing)

-(def times
+(def default-intervals
   {:min (* 60 1000)
-   :5mins (* 5 60 1000)
-   :15mins (* 15 60 1000)
+   :5min (* 5 60 1000)
+   :15min (* 15 60 1000)
    :hr (* 60 60 1000)
-   :6hrs (* 6 60 60 1000)
-   :12hrs (* 12 60 60 1000)
+   :6hr (* 6 60 60 1000)
+   :12hr (* 12 60 60 1000)
    :day (* 24 60 60 1000)
    :week (* 7 24 60 60 1000)})

 (defn new-tracker
-  []
-  (zipmap (keys times)
-          (replicate (count times) (System/currentTimeMillis))))
+  [intervals]
+  (zipmap (keys intervals)
+          (replicate (count intervals) (System/currentTimeMillis))))

 (defn get-interval
-  [times tracker time-key]
+  [intervals tracker time-key]
   (- (System/currentTimeMillis)
      (time-key tracker)
-     (time-key times)))
+     (time-key intervals)))

-(defn get-interval-key-pair
-  [times tracker time-key]
-  [time-key (get-interval times tracker time-key)])
+(defn make-interval-kv
+  ([intervals tracker time-key]
+    (make-interval-kv intervals tracker identity time-key))
+  ([intervals tracker interval-fn time-key]
+    [time-key (interval-fn (get-interval intervals tracker time-key))]))
+
+(defn do-intervals
+  [intervals tracker interval-fn]
+  (->> (keys intervals)
+       (map (partial make-interval-kv intervals tracker interval-fn))
+       (into {})))

 (defn intervals
-  [times tracker]
-  (into {} (map (partial get-interval-key-pair times tracker) (keys times))))
-
-(defn get-passed
-  [times tracker time-key]
-  [time-key (pos? (get-interval times tracker time-key))])
+  [intervals tracker]
+  (do-intervals intervals tracker identity))

 (defn passed?
-  [times tracker]
-  (into {} (map (partial get-passed times tracker) (keys times))))
+  [intervals tracker]
+  (do-intervals intervals tracker pos?))

 (defn update-interval
-  ([times tracker time-key]
-    (update-interval times tracker time-key (constantly true)))
-  ([times tracker time-key update-fn]
-    (if (pos? (get-interval times tracker time-key))
+  ([intervals tracker time-key]
+    (update-interval intervals tracker time-key (constantly true)))
+  ([intervals tracker time-key update-fn]
+    (if (pos? (get-interval intervals tracker time-key))
       (do
-        (update-fn times tracker time-key)
+        (update-fn intervals tracker time-key)
         (assoc tracker time-key (System/currentTimeMillis)))
       tracker)))

 (defn update-tracker
-  ([times tracker]
-    (update-tracker times tracker (constantly true)))
-  ([times tracker update-fn]
-    (loop [[time-key & time-keys] (keys times)
+  ([intervals tracker]
+    (update-tracker intervals tracker (constantly true)))
+  ([intervals tracker update-fn]
+    (loop [[time-key & time-keys] (keys intervals)
            t tracker]
       (if-not time-key
         t
-        (recur time-keys (update-interval times t time-key update-fn))))))
+        (recur time-keys (update-interval intervals t time-key update-fn))))))


Remove debug println :scream_cat:

Remove debug println :scream_cat:

--- test/metabase/test/data/bigquery.clj
+++ test/metabase/test/data/bigquery.clj
@@ -171,7 +171,6 @@
 (defn- destroy-test-databases!
   {:expectations-options :after-run}
   []
-  (println "TIME TO DESTROY:" @created-databases)
   (u/pdoseq [db-name @created-databases]
     (u/ignore-exceptions
       (destroy-dataset! db-name))))


don't generate empty tests for datasets we're not testing against

--- test/metabase/test/data/datasets.clj
+++ test/metabase/test/data/datasets.clj
@@ -204,10 +204,8 @@
 (defmacro expect-when-testing-dataset
   "Generate a unit test that only runs if we're currently testing against DATASET-NAME."
   [dataset-name expected actual]
-  `(expect
-       (when-testing-dataset ~dataset-name
-         ~expected)
-     (when-testing-dataset ~dataset-name
+  `(when-testing-dataset ~dataset-name
+     (expect ~expected
        ~actual)))

 (defmacro expect-with-dataset


Document comparison of records to map entries.


Warn on missing opts

Warn on missing opts

--- src/parbench/core.clj
+++ src/parbench/core.clj
@@ -29,6 +29,10 @@
             :concurrency concurrency
             :requests    requests
             :scale        scale}]
+      (cond (not url)
+        (do
+          (println "You must specify a URL! See -h for options")
+          (System/exit 1)))
       (println "Initializing displays")
       (run-state-displays reqs-state opts)
       (str "Starting run against " url


folder:resourceLocation

folder:resourceLocation

--- src/grafter/rdf/ontologies/pmd.clj
+++ src/grafter/rdf/ontologies/pmd.clj
@@ -18,3 +18,4 @@
 (def folder:hasTree      (folder "hasTree"))
 (def folder:defaultTree  (folder "defaultTree"))
 (def folder:parentFolder (folder "parentFolder"))
+(def folder:resourceLocation (folder "resourceLocation"))


Use the symbol name for the variadic blend.

--- src/klangmeister/instruments.cljs
+++ src/klangmeister/instruments.cljs
@@ -56,7 +56,7 @@
 (defn destination [at context]
   (.-destination context))

-(defn >< [ugen1 ugen2]
+(defn blend [ugen1 ugen2]
   (fn [at context]
     (let [one (ugen1 at context)
           two (ugen2 at context)
@@ -65,15 +65,15 @@
       (.connect two sink)
       sink)))

-(defn blend [& nodes]
-  (reduce >< nodes))
+(defn >< [& nodes]
+  (reduce blend nodes))

 (defn bell! [{:keys [time duration pitch]}]
   (let [harmonic (fn [n proportion]
                    (>>> (sin-osc (* n pitch) 1.5)
                         (percuss 0.01 proportion)
                         (volume 0.01)))]
-    (apply blend
+    (apply ><
            (map
              harmonic
              [1.0 2.0 3.0 4.1 5.2]
@@ -98,4 +98,4 @@
                      (volume 0.05)))
               freqs
               envelopes)
-         (apply blend))))
+         (apply ><))))


need to pass along :language-in and :language-out to module processing

--- src/main/clojure/cljs/closure.clj
+++ src/main/clojure/cljs/closure.clj
@@ -1283,10 +1283,10 @@

 (defn make-convert-js-module-options [opts]
   (-> opts
-      (select-keys [:closure-warnings
-                    :pretty-print
-                    :closure-extra-annotations])
-      (set-options (CompilerOptions.))))
+    (select-keys
+      [:closure-warnings :closure-extra-annotations :pretty-print
+       :language-in :language-out])
+    (set-options (CompilerOptions.))))

 (util/compile-if can-convert-commonjs?
   (defmethod convert-js-module :commonjs [ijs opts]


Add TODO

Add TODO

--- src/main/clojure/pigpen/local.clj
+++ src/main/clojure/pigpen/local.clj
@@ -40,6 +40,7 @@

 (set! *warn-on-reflection* true)

+;; TODO add option to skip this for faster execution
 (defn ^:private eval-code [{:keys [return expr args]} values]
   (let [{:keys [init func]} expr
         ^EvalFunc instance (eval `(new ~(symbol (str "pigpen.PigPenFn" return))))


Fail gracefully if levelset in route doesn't exist

--- src/sojoban/core.cljs
+++ src/sojoban/core.cljs
@@ -141,6 +141,10 @@
         level-set-atom (get level-sets set-name)
         level-set (and level-set-atom @level-set-atom)]
     (cond
+      (nil? level-set-atom)
+      ; We don't know about this level set, so redirect to the default level.
+      (.replaceToken history "/")
+
       (nil? level-set)
       ;; Not loaded and not in the process of loading. Start load.
       (do


replace linebreak with spaces on loading

--- src/todos/storage.clj
+++ src/todos/storage.clj
@@ -5,7 +5,12 @@
 (defn load-data
   "Load data from data-file-name."
   [default-data]
-  (try (read-string (slurp data-file-name))
+  (try (read-string
+         (clojure.strin/replace
+           (slurp data-file-name)
+           #"\s+"
+           " "
+           ))
        (catch Exception e
          (do (println (format "Error on load-data: %s" (.getMessage e)))
              default-data


Improve (and log) missing template error

--- src/pdok/featured_to_extracts/core.clj
+++ src/pdok/featured_to_extracts/core.clj
@@ -207,14 +207,24 @@
   (let [[version collection changes] (parse-changelog changelog-stream)]
     (if-not (= version "pdok-featured-changelog-v2")
       {:status "error" :msg (str "unknown changelog version" version)}
-      (if-not (every? *initialized-collection?* (map #(template/template-key dataset % collection) extract-types))
-        {:status "error" :msg "missing template(s)" :collection collection :extract-types extract-types}
-        (do
-          (when (seq? changes)
-            (let [tx (pg/begin-transaction config/db)]
-              (process-changes tx dataset collection extract-types changes unique-versions)
-              (pg/commit-transaction tx)))
-          {:status "ok" :collection collection})))))
+      (let [missing-templates (->> extract-types
+                                (map #(template/template-key dataset % collection))
+                                (filter #(not (*initialized-collection?* %))))]
+        (if (next missing-templates)
+          (let [error-msg {:status "error"
+                           :msg "missing template(s)"
+                           :collection collection
+                           :extract-types extract-types
+                           :missing-templates missing-templates}]
+            (log/error "Not all templates are found. Details: " + error-msg)
+            error-msg)
+          (do
+            (log/info "All templates found")
+            (when (seq? changes)
+              (let [tx (pg/begin-transaction config/db)]
+                (process-changes tx dataset collection extract-types changes unique-versions)
+                (pg/commit-transaction tx)))
+            {:status "ok" :collection collection}))))))

 (defn -main [template-location dataset extract-type & args]
   (let [templates-with-metadata (template/templates-with-metadata dataset template-location)]


cleaning up

cleaning up

--- src/celestial/persistency.clj
+++ src/celestial/persistency.clj
@@ -40,7 +40,6 @@
 (defn fuzzy-host [h]
   "Searches after a host in a fuzzy manner, first fqn then tried prefixes"
   (let [ks (reverse (reductions (fn [r v] (str r "." v)) (split h #"\.")))]
-    (println ks)
     (when-let [k (first (filter #(= 1 (wcar (car/exists (hk %)))) ks))]
       (host k))))


Fixed field names for fix for #151

Fixed field names for fix for #151

--- src/clj/forma/source/rain.clj
+++ src/clj/forma/source/rain.clj
@@ -182,8 +182,8 @@
         mod-coords ["?mod-h" "?mod-v" "?sample" "?line"]]
     (<- [?dataset ?m-res ?t-res !date ?mod-h ?mod-v ?sample ?line ?val]
         (rain-vals !date ?row ?col ?float-val)
-        (not= ?val nodata)
-        (double ?val :> ?val)
+        (not= ?float-val nodata)
+        (double ?float-val :> ?val)
         (pix-tap :>> mod-coords)
         (p/add-fields "precl" "32" m-res :> ?dataset ?t-res ?m-res)
         (r/wgs84-indexer :<< (into [m-res ascii-map] mod-coords) :> ?row ?col))))


Code Siphon discount for install. Apply effects in same order as stated on card, just in case it ever matters.

--- src/clj/game/cards-events.clj
+++ src/clj/game/cards-events.clj
@@ -36,11 +36,10 @@
    {:effect (effect (run :rd
                          {:replace-access
                           {:prompt "Choose a program to install"
-                           :msg (msg "Code Siphon to install " (:title target) " and take 1 tag")
-                           :choices (req (filter #(and (has? % :type "Program")
-                                                       (<= (:cost %) (:credit runner))) (:deck runner)))
-                           :effect (effect (gain :tag 1)
-                                           (runner-install target) (shuffle! :deck))}} card))}
+                           :msg (msg "install " (:title target) " and take 1 tag")
+                           :choices (req (filter #(has? % :type "Program") (:deck runner)))
+                           :effect (effect (install-cost-bonus (* -3 (count (get-in corp [:servers :rd :ices]))))
+                                           (runner-install target) (gain :tag 1) (shuffle! :deck))}} card))}

    "Day Job"
    {:additional-cost [:click 3] :effect (effect (gain :credit 10))}


require at least 1 program to be installed to play Scavenge

--- src/clj/game/cards-events.clj
+++ src/clj/game/cards-events.clj
@@ -495,7 +495,8 @@
     :effect (req (doseq [c targets] (expose state side c)))}

    "Scavenge"
-   {:choices {:req #(= (:type %) "Program")}
+   {:req (req (> (count (filter #(= (:type %) "Program") (all-installed state :runner))) 0))
+    :choices {:req #(= (:type %) "Program")}
     :effect (req (let [trashed target]
                    (trash state side trashed)
                    (resolve-ability


update Blackmail prerequisite

update Blackmail prerequisite

--- src/clj/game/cards-events.clj
+++ src/clj/game/cards-events.clj
@@ -42,7 +42,7 @@
                        (gain state :runner :memory (:memoryunits c))))))}

    "Blackmail"
-   {:req (req (> (:bad-publicity corp) 0)) :prompt "Choose a server" :choices (req runnable-servers)
+   {:req (req has-bad-pub) :prompt "Choose a server" :choices (req runnable-servers)
     :msg "prevent ICE from being rezzed during this run"
     :effect (effect (register-run-flag!
                       card


change Modded to use card targeting system

--- src/clj/game/cards-events.clj
+++ src/clj/game/cards-events.clj
@@ -385,8 +385,9 @@
      {:effect (effect (resolve-ability (mhelper 1) card nil))})

    "Modded"
-   {:prompt "Choose a card to install"
-    :choices (req (filter #(#{"Hardware" "Program"} (:type %)) (:hand runner)))
+   {:prompt "Choose a program or piece of hardware to install from your Grip"
+    :choices {:req #(and (or (= (:type %) "Hardware") (= (:type %) "Program"))
+                         (= (:zone %) [:hand]))}
     :effect (effect (install-cost-bonus [:credit -3]) (runner-install target))}

    "Net Celebrity"


add option merge helper

add option merge helper

--- src/clj/shadow/cljs/build.clj
+++ src/clj/shadow/cljs/build.clj
@@ -2415,6 +2415,20 @@
 (defn set-build-options [state opts]
   (merge state opts))

+(defn merge-build-options [state opts]
+  (reduce-kv
+    (fn [state key value]
+      (cond
+        (and (map? value)
+             (map? (get state key)))
+        (update state key merge value)
+
+        :default
+        (assoc state key value)
+        ))
+    state
+    opts))
+
 (defn get-closure-compiler [state]
   (::cc state))


Fix circular dependency.

Fix circular dependency.

--- src/cljs/openslack/state.cljs
+++ src/cljs/openslack/state.cljs
@@ -1,7 +1,6 @@
 (ns openslack.state
   (:require [om.core :as om :include-macros true]
-            [shodan.console :as console :include-macros true]
-            [openslack.browser :as browser]))
+            [shodan.console :as console :include-macros true]))

 ; TODO: schema of state?
 (defn make-initial-state []


Last touches to get everything working under cljs

--- src/cljx/quile/component.cljx
+++ src/cljx/quile/component.cljx
@@ -95,22 +95,24 @@
              (dependencies component)))

 (defn- try-action [component system key f args]
-  (if (nil? f)
-    (println "Uh oh, nil function"))
-  (if (nil? component)
-    (println "Oh no! nil component"))
-  ;;;(println (str "Trying to call " (.toString f) " on " (.toString component)))
   (try (apply f component args)
-       (catch #+clj Throwable #+cljs js/Object t
-         (throw (ex-info (str "Error in component " key
-                              " in system " #+clj (.getName (class system)) #+cljs component
+       (catch #+clj Throwable #+cljs js/Error t
+         #+clj (throw (ex-info (str "Error in component " key
+                              " in system " (.getName (class system))
                               " calling " f)
                          {:reason ::component-function-threw-exception
                           :function f
                           :system-key key
                           :component component
                           :system system}
-                         t)))))
+                         t))
+         #+cljs (throw (ex-info (str "Error in component " + key)
+                         {:reason ::component-function-threw-exception
+                          :function f
+                          :component component
+                          :system system}
+                         t))
+         )))

 (defn- get-component [system key]
   (or (get system key)
@@ -126,6 +128,7 @@
   [system component-keys f & args]
   (let [graph (dependency-graph system component-keys)]
     (reduce (fn [system key]
+              (println key)
               (assoc system key
                      (-> (get-component system key)
                          (assoc-dependencies system)
@@ -151,9 +154,9 @@
   collection of keys (order doesn't matter) in the system specifying
   the components to start, defaults to all keys in the system."
   ([system]
-     (start-system system (keys system)))
+    (start-system system (keys system)))
   ([system component-keys]
-     (update-system system component-keys #+clj #'start #+cljs (aget quile.component "start"))))
+    (update-system system component-keys #+clj #'start #+cljs (aget quile.component "start"))))

 (defn stop-system
   "Recursively stops components in the system, in reverse dependency


Filter disconnected nodes, too

Filter disconnected nodes, too

--- src/clojure/defgraph/core.clj
+++ src/clojure/defgraph/core.clj
@@ -55,10 +55,11 @@
            {}))))))

 (defn graph
-  [root re]
-  (let [filtered-edges (filter #(re-matches re (first %)) (edges root))
+  [root prefix]
+  (let [re (re-pattern (str prefix ".*"))
+        filtered-edges (filter #(re-matches re (first %)) (edges root))
         complete-edges (reduce conj {} (map #((rootpath root) %) (keys filtered-edges)))]
-    {:v (map #(.getName %) (yamldefs root))
+    {:v (filter #(re-matches re %) (map #(.getName %) (yamldefs root)))
      :e complete-edges}))

 (defn mx-layout
@@ -120,7 +121,7 @@
           prefix (second args)
           button (JButton. "layout")
           button-panel (JPanel.)
-          g (graph root (re-pattern (str prefix ".*")))
+          g (graph root prefix)
           panel (JPanel. (BorderLayout.))
           width 1200
           height 700


Allow sinking from any stage node.

Allow sinking from any stage node.

--- src/clojure/parkour/graph.clj
+++ src/clojure/parkour/graph.clj
@@ -252,7 +252,7 @@
   [node dsink]
   (-> node (config map-only) (assoc :stage reduce) (sink dsink)))

-(defmethod sink :reduce
+(defmethod sink :default
   [node dsink]
   (let [dsink (dsink/dsink dsink), dseq (dseq/dseq dsink),
         node (sink* node dsink)]
@@ -272,7 +272,7 @@
   (apply sink-multi (-> node (config map-only) (assoc :stage reduce))
          ,          named-dsinks))

-(defmethod sink-multi :reduce
+(defmethod sink-multi :default
   [node & named-dsinks]
   (let [dsink (apply dux/dsink named-dsinks)
         dseqs (map (comp dseq/dseq second) (cc/partition 2 named-dsinks))


Fixed problem where trace id might not be set in headers.

--- src/cmr/system_trace/http.clj
+++ src/cmr/system_trace/http.clj
@@ -17,7 +17,9 @@
   [system request]
   (let [{{^String trace-id TRACE_ID_HEADER
           ^String span-id SPAN_ID_HEADER} :headers} request]
-    (c/request-context system (c/trace-info (Long. trace-id) (Long. span-id)))))
+    (if (and trace-id span-id)
+      (c/request-context system (c/trace-info (Long. trace-id) (Long. span-id)))
+      (c/request-context system (c/trace-info)))))

 (defn build-request-context-handler
   "This is a ring handler that will extract trace info from the current request."


saner unfocusing after search

saner unfocusing after search

--- src/semtag_web/client/main.cljs
+++ src/semtag_web/client/main.cljs
@@ -84,12 +84,11 @@
   (add-sort-to parent))

 (defn mls-search
-  [search-box text-field button & [callback event]]
+  [search-box text-field & [callback event]]
   (let [query (jq/val text-field)]
     (-> (jq/find search-box :h2)
       (inner (str "Search results for '" query "'")))
-    ;; focus off input
-    (.focus button)
+    (.blur text-field)
     (backend-request (path-to "/mls?query=" query) (partial create-search-table search-box))
     (when callback (callback query))))

@@ -137,7 +136,7 @@
         $add-button ($ :#add_url_button)
         $add-text ($ :#add_url_text)
         create-url (partial add-url $add-text $add-button)
-        search-and-update-page (partial mls-search ($ :#search_box) $text-field $button)
+        search-and-update-page (partial mls-search ($ :#search_box) $text-field)
         search-and-update-page-and-url (partial search-and-update-page
                                                 #(.pushState window.history "" "" (path-to "/?query=" %)))
         query-param (re-find #"[\?&]?query=([^&]+)" (.-search window.location))]


Enable session handling for the emebedded Jetty instance

--- src/main/clojure/cascade/jetty.clj
+++ src/main/clojure/cascade/jetty.clj
@@ -25,13 +25,14 @@
 (defn run-jetty
   "Starts an instance of the Jetty Server running.
   webapp defines the folder containing ordinary static resources (the docroot).
-  Returns the new Jetty Server instance. No web.xml is necessary, a
+  Returns the new Jetty Server instance. The instance is started with session support, but
+  without security support. No web.xml is necessary, a
   cascade.filter will automatically be installed. Any provided namespace-symbols will be
-  loaded at filter startup (you will specify namespaces containing views and actions)."
+  loaded at filter startup (this is to specify namespaces containing views and actions)."
   [#^String webapp port & namespaces]

   (let [server (Server. port)
-        context (ServletContextHandler. server "/" false false)
+        context (ServletContextHandler. server "/" true false)
         namespace-list (str-join "," (map name namespaces))]
 	  (doto context
 	    (.setResourceBase webapp)


fix compiler warning

fix compiler warning

--- src/main/clojure/org/dada/core.clj
+++ src/main/clojure/org/dada/core.clj
@@ -64,7 +64,7 @@
     (.addAll array-list args)
     array-list))

-(def *class-factory* (new ClassFactory))
+(def #^ClassFactory *class-factory* (new ClassFactory))

 ;; e.g.
 ;;(make-class


added camber-function, gradient-function and started upper-surface-x-function

--- model.clj
+++ model.clj
@@ -1,5 +1,5 @@
 (defn thickness-function
-  "Take the thickness and returns the function of thickess around the camber line"
+  "Take a corrected thickness and returns the function of thickess around the camber line"
   [thickness x]
   (let [a-0 0.2969
         a-1 -0.126
@@ -8,3 +8,27 @@
         a-4 -0.1036]
         (* (/ thickness 0.2)
            (+ (* a-0 (^ x 0.5)) (* a-1 x) (* a-2 (^ x 2)) (* a-3 (^ x 3)) (* a-4 (^ x 4))))))
+
+(defn camber-function
+  "Takes in a corrected maxiumum camber, corrected camber position, and an x value.
+    Returns the y-coordinate of the camber at that x value"
+  [max-camber position-camber x]
+  (if (and (> x 0) (< x position-camber))
+    (* (/ (* 2 max-camber) (^ position-camber 2)) (- (* 2 position-camber x) (^ x 2))) ;;; (2M/P^2)(2Px - x^2)
+    (* (/ (* 2 max-camber) (^ (- 1 position-camber) 2))
+       (- (+ (- 1 (* 2 position-camber)) (* 2 position-camber x))) (^ x 2)))) ;;; (2M/(1-P)^2)(1 - 2P + 2Px -x^2)
+
+(defn gradient-function
+  "Takes a corrected maximum camber, corrected camber position, and an x value.
+   Returns the camber gradient at that x value"
+  [max-camber position-camber x]
+  (if (and (> x 0) (< x position-camber))
+    (* (/ (* 2 max-camber) (^ position-camber 2)) (- position-camber x)) ;;; (2M/P^2)(P-x)
+    (* (/ (* 2 max-camber) (^ (- 1 position-camber) 2)) (- position-camber x)))) ;;; (2M/(1-P)^2)(P-x)
+
+(defn upper-surface-x-function
+  "takes an x  and gives an x coordinate on the paremetric upper-surface-x-function"
+  [x thickess]
+  (- x (* (thickness-function thickess x)
+          (Math/sin (FILL IN STUFF)))))
+


Add frequency generator combinator

Add frequency generator combinator

--- src/simple_check/generators.clj
+++ src/simple_check/generators.clj
@@ -70,6 +70,19 @@
   [generators]
   (bind (choose 0 (dec (count generators)))
         #(nth generators %)))
+
+(defn- pick
+  [[h & tail] n]
+  (let [[chance gen] h]
+    (if (<= n chance)
+      gen
+      (recur tail (- n chance)))))
+
+(defn frequency
+  [pairs]
+  (let [total (apply + (clojure.core/map first pairs))]
+    (bind (choose 1 total)
+          (partial pick pairs))))

 (defn elements
   [coll]


define support node

define support node

--- src/synthesis_crawlers/core.clj
+++ src/synthesis_crawlers/core.clj
@@ -199,7 +199,16 @@
                                                      (s/coll-of #(instance? Element %))))))
 (defn find-support-nodes
   [url-attr-nodes]
-  nil)
+  (let [result (for [[url attr-nodes] url-attr-nodes
+                     [attr nodes] attr-nodes
+                     node (set (flatten (map reachable-elements nodes)))]
+                 [url [node nodes]])]
+    (reduce (fn [acc [url [node nodes]]]
+              (let [node-nodes (get acc url {})
+                    node-set (get node-nodes node #{})]
+                (assoc acc url (assoc node-nodes node (into node-set nodes)))))
+            {}
+            result)))

 #_(let [best-attr-set (keys (filter (fn [[attr nodes]] (not-empty nodes)) attr-nodes))]
     best-attr-set)


Correct collision type

Correct collision type

--- src/uk/co/tombooth/pollock.cljs
+++ src/uk/co/tombooth/pollock.cljs
@@ -335,8 +335,8 @@

 ;; When an impact splatters it will only take a fraction of the
-;; velocity, otherwise know as being elastic rather than inelastic
-;; **check these definitions**. We can define a constant that will be
+;; velocity, otherwise know as being na inelastic rather than elastic
+;; collision. We can define a constant that will be
 ;; used to reduce the total velocity of the bounced vector to reflect
 ;; this elasticity.


Update tools-deps variants to 1.11.1.1189


Update tools-deps to 1.11.1.1149

Update tools-deps to 1.11.1.1149


Extract common code for xhrio requests

Extract common code for xhrio requests

--- src/elfeed_cljsrn/events.cljs
+++ src/elfeed_cljsrn/events.cljs
@@ -28,6 +28,12 @@
     (js/encodeURIComponent
      (clojure.string/trim (str term " " (:feed-title search-params))))))

+(def default-http-xhrio-attrs
+  {:method :post
+   :timeout 5000
+   :format (ajax/json-request-format)
+   :response-format (ajax/json-response-format {:keywords? true})})
+
 ;; -- Interceptors -------------------------------------------------------------

 (defn check-and-throw
@@ -110,12 +116,10 @@
  :update-server
  [check-spec]
  (fn [{db :db} [_ url]]
-   {:http-xhrio {:method :post
-                 :uri (str url "/elfeed/update")
-                 :format :json
-                 :response-format (ajax/json-response-format {:keywords? true})
-                 :on-success [:success-update-server]
-                 :on-failure [:failure-update-server]}
+   {:http-xhrio (merge default-http-xhrio-attrs
+                       {:uri (str url "/elfeed/update")
+                        :on-success [:success-update-server]
+                        :on-failure [:failure-update-server]})
     :db (assoc db :server {:url url :checking? true})}))

 (reg-event-fx
@@ -135,12 +139,10 @@
  (fn [{db :db} [_ url ]]
    (let [events {:db (assoc db :server {:url url :checking? true})}]
      (if (valid-url? url)
-       (merge events {:http-xhrio {:method :post
-                                   :uri (str url "/elfeed/update")
-                                   :format :json
-                                   :response-format (ajax/json-response-format {:keywords? true})
-                                   :on-success [:success-save-server]
-                                   :on-failure [:failure-save-server]}})
+       (merge events {:http-xhrio (merge default-http-xhrio-attrs
+                                         {:uri (str url "/elfeed/update")
+                                          :on-success [:success-save-server]
+                                          :on-failure [:failure-save-server]})})
        (merge events {:dispatch [:failure-save-server {:status-text "Invalid URL (should start with http://)"}]})))))

 (reg-event-fx
@@ -174,20 +176,15 @@
      {:db db})))

 (defn fetch-entries [{db :db} [_event-id search-params]]
-  (let [query-term (js/encodeURIComponent
-                    (or (:term search-params) (:default-term search-params)))
-        uri (str (:url (:server db)) "/elfeed/search?q=" query-term)]
-    {:http-xhrio {:method :post
-                  :uri uri
-                  :format :text
-                  :response-format (ajax/json-response-format {:keywords? true})
-                  :keywords? true
-                  :on-success [:success-fetch-entries search-params]
-                  :on-failure [:failure-fetch-entries]}
-     :db (assoc db
-                :error-entries false
-                :fetching-feeds? true
-                :fetching-entries? true)}))
+  (let [query-term (compose-query-term (dissoc search-params :feed-title))
+        uri (str (:url (:server db)) "/elfeed/search")]
+    {:http-xhrio (merge default-http-xhrio-attrs
+                        {:uri uri
+                         :params {:q query-term}
+                         :format (ajax/url-request-format)
+                         :on-success [:success-fetch-entries search-params]
+                         :on-failure [:failure-fetch-entries]})
+     :db (assoc db :fetching-feeds? true :fetching-entries? true)}))

 (reg-event-fx
  :fetch-entries
@@ -227,14 +224,13 @@
  (fn [{db :db} [_ search-params response]]
    (if (:feed-title search-params)
      (let [query-term (compose-query-term search-params)
-           uri (str (:url (:server db)) "/elfeed/search?q=" query-term)]
-       {:http-xhrio {:method :post
-                     :uri uri
-                     :format :text
-                     :response-format (ajax/json-response-format {:keywords? true})
-                     :keywords? true
-                     :on-success [:process-entries]
-                     :on-failure [:failure-fetch-entries]}
+           uri (str (:url (:server db)) "/elfeed/search")]
+       {:http-xhrio (merge default-http-xhrio-attrs
+                           {:uri uri
+                            :params {:q query-term}
+                            :format (ajax/url-request-format)
+                            :on-success [:process-entries]
+                            :on-failure [:failure-fetch-entries]})
         :dispatch [:process-feeds response]})
      {:dispatch-n (list [:process-feeds response] [:process-entries response])})))

@@ -270,13 +266,12 @@
  :mark-entries-as-unread
  [check-spec]
  (fn [{db :db} [_ ids]]
-   {:http-xhrio {:method :put
-                 :uri (str (:url (:server db)) "/elfeed/tags")
-                 :params {:entries ids :add (list "unread")}
-                 :format (ajax/json-request-format)
-                 :response-format (ajax/json-response-format)
-                 :on-success [:success-mark-entries-as-unread ids]
-                 :on-failure [:failure-mark-entries-as-unread ids]}
+   {:http-xhrio (merge default-http-xhrio-attrs
+                       {:method :put
+                        :uri (str (:url (:server db)) "/elfeed/tags")
+                        :params {:entries ids :add (list "unread")}
+                        :on-success [:success-mark-entries-as-unread ids]
+                        :on-failure [:failure-mark-entries-as-unread ids]})
     :db db}))

 (reg-event-db
@@ -300,13 +295,12 @@
  :mark-entries-as-read
  [check-spec]
  (fn [{db :db} [_ ids]]
-   {:http-xhrio {:method :put
-                 :uri (str (:url (:server db)) "/elfeed/tags")
-                 :params {:entries ids :remove (list "unread")}
-                 :format (ajax/json-request-format)
-                 :response-format (ajax/json-response-format)
-                 :on-success [:success-mark-entries-as-read ids]
-                 :on-failure [:failure-mark-entries-as-read ids]}
+   {:http-xhrio (merge default-http-xhrio-attrs
+                       {:method :put
+                        :uri (str (:url (:server db)) "/elfeed/tags")
+                        :params {:entries ids :remove (list "unread")}
+                        :on-success [:success-mark-entries-as-read ids]
+                        :on-failure [:failure-mark-entries-as-read ids]})
     :db db}))

 (defn success-mark-entries-as-read [db [_event-id entry-ids response]]
@@ -329,12 +323,11 @@
    db))

 (defn fetch-entry-content [{db :db} [_event-id entry]]
-  {:http-xhrio {:method :post
-                :uri (str (:url (:server db)) "/elfeed/content/" (:content entry))
-                :format :json
-                :response-format (ajax/text-response-format)
-                :on-success [:success-fetch-entry-content (:webid entry)]
-                :on-failure [:failure-fetch-entry-content]}
+  {:http-xhrio (merge default-http-xhrio-attrs
+                      {:uri (str (:url (:server db)) "/elfeed/content/" (:content entry))
+                       :response-format (ajax/text-response-format)
+                       :on-success [:success-fetch-entry-content (:webid entry)]
+                       :on-failure [:failure-fetch-entry-content]})
    :db (-> db
            (assoc :error-entry false
                   :current-entry (:webid entry)
@@ -368,13 +361,11 @@
 (reg-event-fx
  :fetch-update-time
  (fn [{db :db} _]
-   {:http-xhrio {:method :post
-                 :uri (str (:url (:server db)) "/elfeed/update")
-                 :params {:time (:update-time db)}
-                 :format :json
-                 :response-format (ajax/json-response-format {:keywords? true})
-                 :on-success [:success-fetch-update-time]
-                 :on-failure [:failure-fetch-update-time]}
+   {:http-xhrio (merge default-http-xhrio-attrs
+                       {:uri (str (:url (:server db)) "/elfeed/update")
+                        :params {:time (:update-time db)}
+                        :on-success [:success-fetch-update-time]
+                        :on-failure [:failure-fetch-update-time]})
     :db (assoc db :fetching-update-time true)}))

 (reg-event-db


also keep a local cache of transactions

also keep a local cache of transactions

--- src/pc/http/sente.clj
+++ src/pc/http/sente.clj
@@ -664,13 +664,21 @@
       (log/infof "sending %s tx-ids for %s to %s" (count tx-ids) (:document/id ?data) client-id)
       (?reply-fn {:tx-ids tx-ids}))))

-(defn frontend-tx-data [db tx-id]
-  (-> (replay/reproduce-transaction db tx-id)
+(def ^:dynamic *db* nil)
+(defn memo-frontend-tx-data* [tx-id]
+  (-> (replay/reproduce-transaction *db* tx-id)
     (datomic-common/frontend-document-transaction)
     :read-only-data
     ;; remove entity-maps b/c easier to cache that way
     (update-in [:tx-data] vec)
     (dissoc :transaction/document)))
+
+(defonce memo-frontend-tx-data (memo/lru memo-frontend-tx-data
+                                         :lru/threshold 10000))
+
+(defn frontend-tx-data [db tx-id]
+  (binding [*db* db]
+    (memo-frontend-tx-data tx-id)))

 (defn get-frontend-tx-data [db tx-id]
   (cache/wrap-memcache


show link to ph post in blogroll

show link to ph post in blogroll

--- src/pc/views/blog.clj
+++ src/pc/views/blog.clj
@@ -27,10 +27,10 @@
 (def slugs
   "Sorted array of slugs, assumes the post content can be found in the
    function returned by post-fn"
-  [{:slug "interactive-layers"
+  [{:slug "product-hunt-wake-up-call"
     :display-in-overview true}
-   {:slug "product-hunt-wake-up-call"
-    :display-in-overview false}
+   {:slug "interactive-layers"
+    :display-in-overview true}
    ;; "instrumenting-om-components"
    ;; "lets-replace-pen-and-paper"
    ])


Only create input listeners when screen is first created

--- src/play_clj/core.clj
+++ src/play_clj/core.clj
@@ -70,7 +70,9 @@
                                    (wrapper screen)
                                    (reset-changed! entities old-entities)))))]
     ; add the input listeners to the screen atom
-    (swap! screen assoc :input-listeners (input-listeners options execute-fn!))
+    (when-not (:input-listeners @screen)
+      (->> (input-listeners options execute-fn!)
+           (swap! screen assoc :input-listeners)))
     ; update screen when either the screen or entities are changed
     (add-watch screen :changed (fn [_ _ _ new-screen]
                                  (update-screen! new-screen)))


Turn instrument on orien change even before init touch

--- src/playmary/one.cljs
+++ src/playmary/one.cljs
@@ -53,13 +53,14 @@
   [scale]
   {:piano-keys (into (sorted-map) (map (fn [freq] [freq {}])
                                        scale))
-   :notes [] :w 0 :h 0})
+   :notes [] :w 0 :h 0 :sound-ready false})

 (defn add-synths-to-instrument
   [instrument]
-  (reduce (fn [a x] (assoc-in a [:piano-keys x :synth] (create-note-synth x)))
-          instrument
-          (-> instrument :piano-keys keys)))
+  (assoc (reduce (fn [a x] (assoc-in a [:piano-keys x :synth] (create-note-synth x)))
+                 instrument
+                 (-> instrument :piano-keys keys))
+    :sound-ready true))

 (defn audio-time []
   (.-currentTime js/audioCtx))
@@ -109,6 +110,14 @@
     (or (and f-instrument (f-instrument instrument event))
         instrument)))

+(defn fire-touch-data-on-instrument
+  [instrument data]
+  (if (-> instrument :sound-ready)
+    (reduce fire-event-on-instrument
+            instrument
+            (touch-data->touches data))
+    (recur (add-synths-to-instrument instrument) data)))
+
 (defn update-size [instrument canvas-id]
   (let [{w :w h :h :as window-size} (util/get-window-size)]
     (do (util/set-canvas-size! canvas-id window-size)
@@ -123,7 +132,7 @@
 (let [canvas-id "canvas"
       c-instrument (chan)
       c-orientation-change (util/listen js/window :orientation-change)
-      c-input (create-input-channel canvas-id)]
+      c-touch (create-input-channel canvas-id)]

   (go
    (let [draw-ctx (util/get-ctx canvas-id)]
@@ -136,17 +145,10 @@
                (recur instrument)))))))

   (go
-   (let [display-instrument (update-size (create-instrument (scales/c-minor)) canvas-id)]
-     (>! c-instrument display-instrument)
-
-     (<! (create-input-channel canvas-id)) ;; wait for first touch before creating synths
-     (loop [instrument (add-synths-to-instrument display-instrument)]
-       (>! c-instrument instrument)
-       (let [[data c] (alts! [c-input c-orientation-change])]
-         (condp = c
-           c-orientation-change (recur (update-size instrument canvas-id))
-           c-input (recur (reduce fire-event-on-instrument
-                                  instrument
-                                  (touch-data->touches data))))))))
-
+   (loop [instrument (update-size (create-instrument (scales/c-minor)) canvas-id)]
+     (>! c-instrument instrument)
+     (let [[data c] (alts! [c-touch c-orientation-change])]
+       (condp = c
+         c-orientation-change (recur (update-size instrument canvas-id))
+         c-touch (recur (fire-touch-data-on-instrument instrument data))))))
   )


Add utility function to check when strict-mode is enabled.

--- src/puget/printer.clj
+++ src/puget/printer.clj
@@ -62,6 +62,14 @@
    :function-symbol [:bold :blue]
    :class-delimiter [:blue]
    :class-name      [:bold :blue]})
+
+
+(defn- illegal-when-strict
+  "Checks whether strict mode is enabled and throws an exception if so."
+  [value]
+  (when (:strict *options*)
+    (throw (IllegalArgumentException.
+             (str "No canonical representation for " (class value) ": " value)))))

 (defmacro with-color
@@ -202,14 +210,12 @@

 (defmethod canonize clojure.lang.IRecord
-  [r]
-  (if *strict-mode*
-    (throw (IllegalArgumentException.
-             (str "No canonical representation for " (class r) ": " r)))
-    [:span
-     (color-doc :delimiter "#")
-     (.getName (class r))
-     (canonize-map r)]))
+  [record]
+  (illegal-when-strict record)
+  [:span
+   (color-doc :delimiter "#")
+   (.getName (class record))
+   (canonize-map record)])

 (prefer-method canonize clojure.lang.IRecord clojure.lang.IPersistentMap)
@@ -227,14 +233,12 @@

 (defmethod canonize :default
   [value]
-  (if *strict-mode*
-    (throw (IllegalArgumentException.
-             (str "No canonical representation for " (class value) ": " value)))
-    [:span
-     (color-doc :class-delimiter "#<")
-     (color-doc :class-name (.getName (class value)))
-     " " (str value)
-     (color-doc :class-delimiter ">")]))
+  (illegal-when-strict value)
+  [:span
+   (color-doc :class-delimiter "#<")
+   (color-doc :class-name (.getName (class value)))
+   " " (str value)
+   (color-doc :class-delimiter ">")])


sorting

sorting

--- src/scrabble/core.clj
+++ src/scrabble/core.clj
@@ -38,9 +38,9 @@
   (let [perms (combo/permutations letters)
         perms-words (map str/join perms)
         valid-words (intersection (set perms-words) (set all-words))]
-    (into {}
+    (into []
           (for [vl valid-words]
-            {(word-value vl) vl}))))
+            {:value (word-value vl) :word vl}))))

 (def cli-options
@@ -54,6 +54,6 @@
   "I don't do a whole lot ... yet."
   [& args]
   (let [options (parse-opts args cli-options)
-        word (nth (:arguments options) 0)]
-
-    (prn (possibilities word))))
+        word (nth (:arguments options) 0)
+        variants (sort-by :value (possibilities word))]
+    (println variants)))


added ifequal tag

added ifequal tag

--- src/selmer/parser.clj
+++ src/selmer/parser.clj
@@ -47,25 +47,36 @@
           (.append buf (render content (assoc-in context-map id value))))
         (.toString buf)))))

+(defn render-if [context-map condition first-block second-block]
+  (render
+    (cond
+      (and condition first-block)
+      (:content first-block)
+
+      (and (not condition) first-block)
+      (:content second-block)
+
+      condition
+      (:content second-block)
+
+      :else [""])
+    context-map))
+
 (defn if-handler [[condition] rdr]
   (let [tags (tag-content rdr :else :endif)
         condition (keyword condition)]
     (fn [context-map]
-      (render
-        (cond
-          (and (condition context-map)
-               (:else tags))
-          (get-in tags [:else :content])
-
-          (and (not (condition context-map))
-               (:else tags))
-          (get-in tags [:endif :content])
-
-          (condition context-map)
-          (get-in tags [:endif :content])
-
-          :else [""])
-        context-map))))
+      (render-if context-map (condition context-map) (:else tags) (:endif tags)))))
+
+(defn ifequal-handler [args rdr]
+  (let [tags (tag-content rdr :else :endifequal)
+        args (for [arg args]
+               (if (= \" (first arg))
+                 (.substring arg 1 (dec (count arg)))
+                 (keyword arg)))]
+    (fn [context-map]
+      (let [condition (apply = (map #(if (keyword? %) (% context-map) %) args))]
+        (render-if context-map condition (:else tags) (:endifequal tags))))))

 (defn block-handler [args rdr]
   (let [content (tag-content rdr :endblock)]
@@ -73,6 +84,7 @@

 (def expr-tags
   {:if if-handler
+   :ifequal ifequal-handler
    :for for-handler
    :block block-handler})


stop writing y.ogg

stop writing y.ogg

--- src/sledge/server.clj
+++ src/sledge/server.clj
@@ -136,18 +136,16 @@
         chan (async/chan)
         thr (future
               (let [buf (byte-array 4096)]
-                (with-open [writer (java.io.FileOutputStream. "/tmp/y.ogg")]
-                  (loop []
-                    (let [w (.read transcode-stream buf)]
-                      (cond (> w 0)
-                            (do
-                              (.write writer buf 0 w)
-                              (async/>!!
-                               chan
-                               (java.util.Arrays/copyOf buf w))
-                              (recur))
-                            (< w 0)
-                            (async/close! chan)))))))]
+                (loop []
+                  (let [w (.read transcode-stream buf)]
+                    (cond (> w 0)
+                          (do
+                            (async/>!!
+                             chan
+                             (java.util.Arrays/copyOf buf w))
+                            (recur))
+                          (< w 0)
+                          (async/close! chan))))))]
     chan))

 (defn transcode-handler [request pathname]


fix for https://github.com/status-im/status-react/issues/643

--- src/status_im/navigation/handlers.cljs
+++ src/status_im/navigation/handlers.cljs
@@ -12,7 +12,7 @@
   (let [stack' (if (> 2 (count stack))
                  (list :chat-list)
                  (pop stack))]
-    (conj stack' view-id)))
+      (conj stack' view-id)))

 (defn replace-view [db view-id]
   (-> db
@@ -75,13 +75,22 @@
             (assoc db :view-id first-in-stack)))
         db))))

+(defn navigate-to-clean
+  [db [_ view-id]]
+  (-> db
+      (assoc :navigation-stack (list))
+      (push-view view-id)))
+
+(register-handler :navigate-to-clean navigate-to-clean)
+
 (register-handler :navigate-to-tab
-  (enrich preload-data!)
-  (fn [db [_ view-id]]
-    (-> db
-        (assoc :prev-tab-view-id (:view-id db))
-        (assoc :prev-view-id (:view-id db))
-        (replace-view view-id))))
+  (->
+    (fn [db [_ view-id]]
+      (-> db
+          (assoc :prev-tab-view-id (:view-id db))
+          (assoc :prev-view-id (:view-id db))))
+    ((enrich navigate-to-clean))
+    ((enrich preload-data!))))

 (register-handler :on-navigated-to-tab
   (enrich preload-data!)
@@ -95,10 +104,3 @@

 (register-handler :show-profile show-profile)

-(defn navigate-to-clean
-  [db [_ view-id]]
-  (-> db
-      (assoc :navigation-stack (list))
-      (push-view view-id)))
-
-(register-handler :navigate-to-clean navigate-to-clean)


Add total-pages field to projects (#2)

Add total-pages field to projects (#2)

--- src/uxbox/services/projects.clj
+++ src/uxbox/services/projects.clj
@@ -77,8 +77,9 @@

 (defn get-projects-for-user
   [conn user]
-  (let [sql (str "SELECT * FROM projects "
-                 " WHERE \"user\"=? ORDER BY created_at DESC")]
+  (let [sql (str "SELECT projects.*, Count(pages.id) as total_pages FROM projects "
+                 "JOIN pages ON pages.project=projects.id "
+                 "WHERE projects.user=? GROUP BY projects.id ORDER BY created_at DESC")]
     (->> (sc/fetch conn [sql user])
          (map usc/normalize-attrs))))


Implement -write-example for FS

Implement -write-example for FS

--- src/grimoire/api/fs/write.clj
+++ src/grimoire/api/fs/write.clj
@@ -31,7 +31,18 @@
     (.mkdirs (.getParentFile handle))
     (spit handle data)))

-;; FIXME: add write-example
+(defmethod api/-write-example ::fs/Config [config thing data]
+  {:pre [(fs/Config? config)
+         (t/thing? thing)
+         (string? data)]}
+  (let [thing  (t/ensure-thing thing)
+        _      (assert thing)
+        id     (java.util.UUID/randomUUID)
+        handle (impl/thing->example-handle config thing id)
+        _      (assert thing)]
+    (.mkdirs (.getParentFile handle))
+    (spit handle data)))
+

 (defmethod api/-write-related ::fs/Config [config thing related-things]
   {:pre [(fs/Config? config)


Progressive loading fixes.

Progressive loading fixes.

--- src/hatti/ona/csv_reader.cljs
+++ src/hatti/ona/csv_reader.cljs
@@ -1,6 +1,7 @@
 (ns hatti.ona.csv-reader
   (:require-macros [cljs.core.async.macros :refer [go]])
-  (:require [cljs.core.async :refer [<! put! chan timeout close!]]))
+  (:require [cljs.core.async :refer [<! put! chan timeout close!]]
+            [cljsjs.papaparse]))

 (defn process-aggregated-data!
   "Calls callback on aggregated data that come via messages in channel.
@@ -32,17 +33,23 @@
 (defn progressively-read-csv!
   "Given csv-string + callback for incremental data,
    progressively parses csv (with exponential chunk processing).
-   Channel-based asynchronization + waits allow browser to render in bckgrnd."
+   Channel-based asynchronization + waits allow browser to render in bckgrnd.
+   Returns a channel which is closed when processing is completed."
   [csv-string chunk-callback]
   (let [*n* (atom 0)
         *agg* (atom [])
         channel (chan)
+        return-channel (chan)
         step (fn [chnk parser]
                (read-next-chunk! chnk parser *n* *agg* channel))
-        complete #(put! channel {:data @*agg* :completed? true})
+        complete (fn [_]
+                   (put! channel {:data @*agg* :completed? true})
+                   (close! return-channel))
         config (clj->js {:header true
                          :skipEmptyLines true
                          :step step
                          :complete complete})]
     (process-aggregated-data! channel chunk-callback)
-    (.parse js/Papa csv-string config)))
+    (.parse js/Papa csv-string config)
+    return-channel))
+


Fix wrong arguments function call on icons menu initialization.

--- src/uxbox/main/ui/dashboard/icons.cljs
+++ src/uxbox/main/ui/dashboard/icons.cljs
@@ -360,7 +360,7 @@
      (header)
      [:section.dashboard-content
       (nav state colls)
-      (menu coll)
+      (menu state coll)
       (content state coll)]]))

 ;; --- New Icon Lightbox (TODO)


CMR-8464: Fixed AQL granule search with list of ECHOGranuleIDs.

--- search-app/src/cmr/search/services/aql/conversion.clj
+++ search-app/src/cmr/search/services/aql/conversion.clj
@@ -264,10 +264,11 @@
 (defmethod element->condition :granule-concept-id
   [concept-type element]
   (let [gran-condition (string-element->condition concept-type element)
-        provider-ids (->> element
-                          :content
-                          first
-                          :content
+        concept-id-elem (first (:content element))
+        concept-ids (if (= :value (:tag concept-id-elem))
+                      (:content concept-id-elem)
+                      (mapcat :content (:content concept-id-elem)))
+        provider-ids (->> concept-ids
                           (map (comp :provider-id cc/parse-concept-id))
                           distinct)
         coll-query-condition (qm/->CollectionQueryCondition


Fixed the bug that it was failed to create a new object json file when the target class directory has not been generated yet.

--- src/tames/systems.clj
+++ src/tames/systems.clj
@@ -254,12 +254,12 @@
         object-id   (if (is-key-field-uuid class-id)
                         (str (UUID/randomUUID))
                         (s-exp-data key-name))
+        class-dir   (get-absolute-path (str "data/" class-id))
         object-file (get-absolute-path (str "data/" class-id "/" object-id ".json"))
         object-data (assoc s-exp-data key-name object-id)]
     (println (format "  key-name  : %s" key-name))
     (println (format "  object-id : %s" object-id))
-    (if (= CLASS_ID class-id)
-        (ensure-directory (format "data/%s" object-id)))
+    (ensure-directory class-dir)
     (with-open [w (io/writer object-file)]
       (json/write object-data w))
     object-data))


Add relation causing a concurrency

Add relation causing a concurrency

--- src/tick/interval.clj
+++ src/tick/interval.clj
@@ -319,7 +319,7 @@
                 y (get intervals yi)
                 conc (concur x y)]
           :when conc]
-      {:x x :y y :concur concur})))
+      {:x x :y y :relation (relation x y) :concur conc})))

 ;; Comparison. We have now built up the capability of comparing
 ;; intervals using the normal <, >, <=, >= operators.


removing logs

removing logs

--- src/tictactoe/ai.cljs
+++ src/tictactoe/ai.cljs
@@ -54,11 +54,10 @@
   (some (partial winning-by? player) (all-lines board) ))

 (defn evaluate-board [board player]
-  (do (prn (str "Player: " (winning? board player)  "  Opponent:" (winning? board (opponent player))))
-      (cond (winning? board player) 1
-            (winning? board (opponent player)) -1
-            (draw? board) 0
-            :else nil)))
+  (cond (winning? board player) 1
+        (winning? board (opponent player)) -1
+        (draw? board) 0
+        :else nil))

 (defn evaluate-moves-deep [board player max-depth computer & last-move]
   (let [score (evaluate-board board computer)]
@@ -67,12 +66,9 @@
               evaluated-moves (map #(hash-map :score ((trampoline evaluate-moves-deep (% :board) (opponent player)
                                                                  (dec max-depth) computer (% :move)) :score )
                                               :move (% :move)) legal-moves  )]
-          (do (prn player "++" computer "-- " max-depth "~>" (sort-by :score > evaluated-moves))
-              (prn player "++" computer "-- " max-depth "~<" (sort-by :score < evaluated-moves))
-              (prn "~~~~~~~~~" legal-moves)
-            (first (if (= player computer)
-                     (sort-by :score > evaluated-moves)
-                     (sort-by :score < evaluated-moves))))))))
+          (first (if (= player computer)
+                   (sort-by :score > evaluated-moves)
+                   (sort-by :score < evaluated-moves)))))))

 (defn find-best-move [board]
   ((evaluate-moves-deep board "O" 3 "O") :move ))
@@ -82,14 +78,14 @@
                ["B" "X" "B"]
                ["O" "B" "X"]]
         score ((evaluate-moves-deep board "O" 1 "O") :score)]
-    (do (prn "~~" score ) (is (= score -1 )  ))))
+    (is (= score -1 )  )))

 (deftest eval-won-pos
   (let [board [["X" "B" "O"]
                ["B" "X" "B"]
                ["O" "B" "X"]]
         score ((evaluate-moves-deep board "X" 1 "X") :score)]
-    (do (prn "~~" score ) (is (= score 1 )  ))))
+    (is (= score 1 )  )))

 (deftest one-move-win
   (let [board [["X" "B" "B"]
@@ -97,7 +93,7 @@
                ["O" "B" "O"]]
         result (evaluate-moves-deep board "O" 1 "O")
         move (result :move)]
-    (do (prn "!!" result)  (is (= move [2 1] )  ))))
+    (is (= move [2 1] )  )))

 (deftest block-one-move-win
   (let [board [["X" "B" "B"]


Stop listening for nav events if RootView is unmounted

--- src/web/chatom/web/ui/core.cljs
+++ src/web/chatom/web/ui/core.cljs
@@ -32,6 +32,8 @@
     {:html5-history (pushy/pushy (nav-handler this) routes/match-route)})
   (componentWillMount [this]
     (pushy/start! (om/get-state this :html5-history)))
+  (componentWillUnmount [this]
+    (pushy/stop! (om/get-state this :html5-history)))
   (render [this]
     (let [{:keys [:app/navbar]} (om/props this)]
       (html


Minor changes on router.

Minor changes on router.

--- src/uxbox/router.cljs
+++ src/uxbox/router.cljs
@@ -6,7 +6,7 @@

 (enable-console-print!)

-(declare +router+)
+(def +router+ nil)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Events
@@ -15,12 +15,6 @@
 (defn update-location
   [{:keys [handler route-params] :as params}]
   (reify
-    IPrintWithWriter
-    (-pr-writer [mv writer x]
-      (-write writer "#<event:router/update-location ")
-      (-pr-writer params writer x)
-      (-write writer ">"))
-
     rs/UpdateEvent
     (-apply-update [_ state]
       (merge state
@@ -33,10 +27,6 @@
   ([name params]
    {:pre [(keyword? name)]}
    (reify
-     IPrintWithWriter
-     (-pr-writer [mv writer _]
-       (-write writer "#<event:router/navigate>"))
-
      rs/EffectEvent
      (-apply-effect [_ state]
        (let [loc (merge {:handler name}
@@ -60,8 +50,6 @@
                               ["icons" :dashboard/icons]
                               ["colors" :dashboard/colors]]]
                ["workspace/" [[page-route :workspace/page]]]]])
-
-(def ^:static ^:private +router+ nil)

 (defn init
   []


Add email and string validators to schema ns.

--- src/uxbox/schema.cljs
+++ src/uxbox/schema.cljs
@@ -47,10 +47,20 @@
   [v]
   (fn? v))

+(def ^:const +email-re+
+  #"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
+
+(v/defvalidator email
+  "Validate if `v` is a valid email."
+  {:default-message-format "% must be a valid email."}
+  [v]
+  (clojure.core/boolean (re-seq +email-re+ v)))
+
 (def required v/required)
 (def number v/number)
 (def integer v/integer)
 (def boolean v/boolean)
+(def string v/string)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Public Api


Update tests for db name changes

Update tests for db name changes

--- test/cavm/db_test.clj
+++ test/cavm/db_test.clj
@@ -31,9 +31,9 @@
                :samples ["sample1" "sample2"]})
       nil
       false)
-    (let [exp (cdb/run-query db {:select [:name] :from [:experiments]})
-          samples (cdb/run-query db {:select [:name] :from [:exp_samples] :order-by [:i]})
-          probes (cdb/run-query db {:select [:*] :from [:probes]})
+    (let [exp (cdb/run-query db {:select [:name] :from [:dataset]})
+          samples (cdb/run-query db {:select [:name] :from [:sample] :order-by [:i]})
+          probes (cdb/run-query db {:select [:*] :from [:field]})
           data (comment (h2/genomic-read-req {'table "id1"
                           'columns ["probe1" "probe2"]
                           'samples ["sample1" "sample2"]}))]
@@ -42,8 +42,8 @@
                 [{:NAME "sample1"}
                  {:NAME "sample2"}]))
       (ct/is (= probes
-                [{:NAME "probe1" :ID 1 :EID 1}
-                 {:NAME "probe2" :ID 2 :EID 1}]))
+                [{:NAME "probe1" :ID 1 :DATASET_ID 1}
+                 {:NAME "probe2" :ID 2 :DATASET_ID 1}]))
       (comment (ct/is (= data
                 [[1.1 1.2] [2.1 2.2]]))))))

@@ -63,9 +63,9 @@
 (defn matrix2 [db]
   (ct/testing "tsv matrix from file"
     (loader db detector docroot "test/cavm/test_inputs/matrix") ; odd that loader & detector both require docroot
-    (let [exp (cdb/run-query db {:select [:name] :from [:experiments]})
-          samples (cdb/run-query db {:select [:name] :from [:exp_samples] :order-by [:i]})
-          probes (cdb/run-query db {:select [:*] :from [:probes]})]
+    (let [exp (cdb/run-query db {:select [:name] :from [:dataset]})
+          samples (cdb/run-query db {:select [:name] :from [:sample] :order-by [:i]})
+          probes (cdb/run-query db {:select [:*] :from [:field]})]
       (ct/is (= exp [{:NAME "matrix"}]))
       (ct/is (= samples
                 [{:NAME "sample1"}
@@ -73,11 +73,11 @@
                  {:NAME "sample3"}
                  {:NAME "sample4"}]))
       (ct/is (= probes
-                [{:NAME "probe1" :ID 1 :EID 1}
-                 {:NAME "probe2" :ID 2 :EID 1}
-                 {:NAME "probe3" :ID 3 :EID 1}
-                 {:NAME "probe4" :ID 4 :EID 1}
-                 {:NAME "probe5" :ID 5 :EID 1} ])))))
+                [{:NAME "probe1" :ID 1 :DATASET_ID 1}
+                 {:NAME "probe2" :ID 2 :DATASET_ID 1}
+                 {:NAME "probe3" :ID 3 :DATASET_ID 1}
+                 {:NAME "probe4" :ID 4 :DATASET_ID 1}
+                 {:NAME "probe5" :ID 5 :DATASET_ID 1} ])))))

 (defn detect-cgdata-genomic [db]
   (ct/testing "detect cgdata genomic"
@@ -87,9 +87,9 @@
 (defn matrix3 [db]
   (ct/testing "cgdata genomic matrix"
     (loader db detector docroot "test/cavm/test_inputs/cgdata_matrix")
-    (let [exp (cdb/run-query db {:select [:name] :from [:experiments]})
-          samples (cdb/run-query db {:select [:name] :from [:exp_samples] :order-by [:i]})
-          probes (cdb/run-query db {:select [:*] :from [:probes]})]
+    (let [exp (cdb/run-query db {:select [:name] :from [:dataset]})
+          samples (cdb/run-query db {:select [:name] :from [:sample] :order-by [:i]})
+          probes (cdb/run-query db {:select [:*] :from [:field]})]
       (ct/is (= exp [{:NAME "cgdata_matrix"}]))
       (ct/is (= samples
                 [{:NAME "sample1"}
@@ -97,11 +97,11 @@
                  {:NAME "sample3"}
                  {:NAME "sample4"}]))
       (ct/is (= probes
-                [{:NAME "probe1" :ID 1 :EID 1}
-                 {:NAME "probe2" :ID 2 :EID 1}
-                 {:NAME "probe3" :ID 3 :EID 1}
-                 {:NAME "probe4" :ID 4 :EID 1}
-                 {:NAME "probe5" :ID 5 :EID 1}])))))
+                [{:NAME "probe1" :ID 1 :DATASET_ID 1}
+                 {:NAME "probe2" :ID 2 :DATASET_ID 1}
+                 {:NAME "probe3" :ID 3 :DATASET_ID 1}
+                 {:NAME "probe4" :ID 4 :DATASET_ID 1}
+                 {:NAME "probe5" :ID 5 :DATASET_ID 1}])))))

 (defn detect-cgdata-probemap [db]
   (ct/testing "detect cgdata probemap"
@@ -111,19 +111,19 @@
 (defn probemap1 [db]
   (ct/testing "cgdata probemap"
     (loader db detector docroot "test/cavm/test_inputs/probes")
-    (let [probemap (cdb/run-query db {:select [:name] :from [:probemaps]})
-          probes (cdb/run-query db {:select [:*] :from [:probemap_probes]})]
+    (let [probemap (cdb/run-query db {:select [:name] :from [:probemap]})
+          probes (cdb/run-query db {:select [:*] :from [:probe]})]
       (ct/is (= probemap [{:NAME "probes"}]))
       (ct/is (= probes
-                [{:PROBE "probe1" :ID 1 :PROBEMAPS_ID 1}
-                 {:PROBE "probe2" :ID 2 :PROBEMAPS_ID 1}
-                 {:PROBE "probe3" :ID 3 :PROBEMAPS_ID 1}
-                 {:PROBE "probe4" :ID 4 :PROBEMAPS_ID 1}
-                 {:PROBE "probe5" :ID 5 :PROBEMAPS_ID 1}
-                 {:PROBE "probe6" :ID 6 :PROBEMAPS_ID 1}
-                 {:PROBE "probe7" :ID 7 :PROBEMAPS_ID 1}
-                 {:PROBE "probe8" :ID 8 :PROBEMAPS_ID 1}
-                 {:PROBE "probe9" :ID 9 :PROBEMAPS_ID 1}])))))
+                [{:NAME "probe1" :ID 1 :PROBEMAP_ID 1}
+                 {:NAME "probe2" :ID 2 :PROBEMAP_ID 1}
+                 {:NAME "probe3" :ID 3 :PROBEMAP_ID 1}
+                 {:NAME "probe4" :ID 4 :PROBEMAP_ID 1}
+                 {:NAME "probe5" :ID 5 :PROBEMAP_ID 1}
+                 {:NAME "probe6" :ID 6 :PROBEMAP_ID 1}
+                 {:NAME "probe7" :ID 7 :PROBEMAP_ID 1}
+                 {:NAME "probe8" :ID 8 :PROBEMAP_ID 1}
+                 {:NAME "probe9" :ID 9 :PROBEMAP_ID 1}])))))

 (defn detect-cgdata-clinical [db]
@@ -134,9 +134,9 @@
 (defn clinical1 [db]
   (ct/testing "cgdata clinical matrix"
     (loader db detector docroot "test/cavm/test_inputs/clinical_matrix")
-    (let [exp (cdb/run-query db {:select [:name] :from [:experiments]})
-          samples (cdb/run-query db {:select [:name] :from [:exp_samples] :order-by [:i]})
-          probes (cdb/run-query db {:select [:*] :from [:probes]})]
+    (let [exp (cdb/run-query db {:select [:name] :from [:dataset]})
+          samples (cdb/run-query db {:select [:name] :from [:sample] :order-by [:i]})
+          probes (cdb/run-query db {:select [:*] :from [:field]})]
       (ct/is (= exp [{:NAME "clinical_matrix"}]))
       (ct/is (= samples
                 [{:NAME "sample1"}
@@ -145,10 +145,10 @@
                  {:NAME "sample4"}
                  {:NAME "sample5"}]))
       (ct/is (= probes
-                [{:NAME "probe1" :ID 1 :EID 1}
-                 {:NAME "probe2" :ID 2 :EID 1}
-                 {:NAME "probe3" :ID 3 :EID 1}
-                 {:NAME "probe4" :ID 4 :EID 1}])))))
+                [{:NAME "probe1" :ID 1 :DATASET_ID 1}
+                 {:NAME "probe2" :ID 2 :DATASET_ID 1}
+                 {:NAME "probe3" :ID 3 :DATASET_ID 1}
+                 {:NAME "probe4" :ID 4 :DATASET_ID 1}])))))

 ; XXX test that cgdata defaults to genomicMatrix if not specified
 ; XXX test clinical


spacing fix

spacing fix

--- src/main/cljs/dmohs/react.clj
+++ src/main/cljs/dmohs/react.clj
@@ -38,7 +38,7 @@
                      nil))))))))

 (defmacro defc [name doc-string-or-fn-map & [fn-map]]
-          `(define false ~name ~doc-string-or-fn-map ~fn-map))
+  `(define false ~name ~doc-string-or-fn-map ~fn-map))

 (defmacro defc- [name doc-string-or-fn-map & [fn-map]]
-          `(define true ~name ~doc-string-or-fn-map ~fn-map))
+  `(define true ~name ~doc-string-or-fn-map ~fn-map))


Pretty code.

Pretty code.

--- src/ombs/db.clj
+++ src/ombs/db.clj
@@ -9,16 +9,13 @@
 ; about many-to-many https://groups.google.com/d/msg/sqlkorma/r3kR6DyQZHo/RrQS_J8kkQ8J

 (declare events)
-(sql/defentity
-  users
+(sql/defentity users
   (sql/many-to-many events :participants {:lfk :uid :rfk :eid}))

-(sql/defentity
-  events
+(sql/defentity events
   (sql/many-to-many users :participants {:lfk :eid :rfk :uid}))

-(sql/defentity
-  participants
+(sql/defentity participants
   (sql/belongs-to events {:fk :eid})
   (sql/belongs-to users {:fk :uid}))

@@ -84,5 +81,4 @@
     (do
       (sql/insert participants (sql/values {:uid (get-uid uname) :eid (get-eid ename)}))
       "Success." )
-    (str uname " already participate " ename " event."))
-  )
+    (str uname " already participate " ename " event.")) )


Change matrices websocket-handler channel to unidirectional.

Don't listen to anything being sent from the browser to the server;
instead, push out from the server only.

--- src/mtrx9/controllers/matrices.clj
+++ src/mtrx9/controllers/matrices.clj
@@ -19,8 +19,7 @@
 (defn websocket-handler [channel request]
   (let [matrix-id (get-in request [:route-params :id])
         matrix-channel (named-channel matrix-id websocket-init)]
-    (siphon matrix-channel channel)
-    (siphon channel matrix-channel)))
+    (siphon matrix-channel channel)))

 (defn show [id]
   (view/show id))


Cleanup code

Cleanup code

--- src/org/spootnik/cyanite/store.clj
+++ src/org/spootnik/cyanite/store.clj
@@ -107,18 +107,6 @@
     (when (= result :timeout)
       (throw (ex-info "Too long!" {})))
     result))
-
-(defn do-series
-  [points path data]
-  (if data
-    (let [time-map (reduce (fn [acc el]
-                             (let [time (:time el)
-                                   metric (:metric el)]
-                               (assoc acc time metric)))
-                           {} data)
-          time-series (map #(get time-map % nil) points)]
-      time-series)
-    {}))

 (defn time-to-ndx
   [^long min-point ^long rollup ^long time]


added docstrings to all arrows

added docstrings to all arrows

--- src/midje/ideas/arrow_symbols.clj
+++ src/midje/ideas/arrow_symbols.clj
@@ -1,13 +1,37 @@
 (ns ^{:doc "Lexicon of all Midje arrows, both expect arrows and prerequisite arrows."}
   midje.ideas.arrow-symbols)

-(def => "=>")
-(def =not=> "=not=>")
-(def =deny=> "=deny=>")
-(def =streams=> "=streams=>")
-(def =expands-to=> "=expands-to=>")
-(def =future=> "=future=>")
-(def =contains=> "=contains=>")
+(def ^{:doc "As a checking arrow: the left side should result in the right side.
+  As a prerequisite arrow: the fake should return the thing on the right."}
+  => "=>")
+
+(def ^{:doc "Checking arrow. The left side should NOT result in the right side."}
+  =not=> "=not=>")
+
+(def ^{:doc "Checking arrow. The left side should NOT result in the right side."}
+  =deny=> "=deny=>")
+
+(def ^{:doc "Checking arrow. The left side should macroexpand-1 to the right side."}
+  =expands-to=> "=expands-to=>")
+
+(def ^{:doc "Checking arrow. The check won't evaluate, but will
+  leave a 'WORK TO DO' reminder in the report."}
+  =future=> "=future=>")
+
+(def ^{:doc "Data prerequisite arrow.
+  Ex. (fact
+        (:a ..m..) => 1
+        (provided ..m.. =contains=> {:a 1}))"}
+  =contains=> "=contains=>")
+
+(def ^{:doc "Prerequisite arrow. The fake will return the first element
+  of the given sequence the first time the fake is evaluated, the second
+  element the second time, and so on.
+
+  Ex. (def tally [] (+ (bar) (bar) (bar)))
+      (fact (tally) => 6
+        (provided (bar) =streams=> [1 2 3]))"}
+  =streams=> "=streams=>")

 (def ^{:doc "Use this when testing Midje code that processes arrow-forms"}
      =test=> "=test=>")


Cough

Cough

--- src/sns_beanstalk_chat/handler.clj
+++ src/sns_beanstalk_chat/handler.clj
@@ -25,7 +25,6 @@
       (assoc :body (-> body
                        (io/reader :encoding "UTF-8")
                        (json/parse-stream true)))
-      (update :body json/parse-stream true)
       handle-sns-request))

 (defn handle-topic-get [{:keys [topic-mult] :as req}]


improve tests by generating fixed keywords rather than keep them constant

--- test/clj/com/rpl/specter/core_test.clj
+++ test/clj/com/rpl/specter/core_test.clj
@@ -23,11 +23,12 @@

 (defspec select-all-keyword-filter
   (for-all+
-    [v (gen/vector (max-size 5
-                     (gen-map-with-keys gen/keyword gen/int :a)))
+    [kw gen/keyword
+     v (gen/vector (max-size 5
+                     (gen-map-with-keys gen/keyword gen/int kw)))
      pred (gen/elements [odd? even?])]
-    (= (select [ALL :a pred] v)
-       (->> v (map :a) (filter pred))
+    (= (select [ALL kw pred] v)
+       (->> v (map kw) (filter pred))
        )))

 (defspec select-pos-extreme-pred
@@ -105,11 +106,13 @@

 (defspec update-with-context
   (for-all+
-    [m (max-size 10 (gen-map-with-keys gen/keyword gen/int :a :b))
+    [kw1 gen/keyword
+     kw2 gen/keyword
+     m (max-size 10 (gen-map-with-keys gen/keyword gen/int kw1 kw2))
      pred (gen/elements [odd? even?])]
-    (= (update [(val-selector-one :b) :a pred] + m)
-       (if (pred (:a m))
-          (assoc m :a (+ (:a m) (:b m)))
+    (= (update [(val-selector-one kw2) kw1 pred] + m)
+       (if (pred (kw1 m))
+          (assoc m kw1 (+ (kw1 m) (kw2 m)))
           m
           ))))


add USD to budgets test

add USD to budgets test

--- test/clj_money/models/budgets_test.clj
+++ test/clj_money/models/budgets_test.clj
@@ -24,7 +24,11 @@
             :last-name "Doe"
             :password "please01"}]
    :entities [{:user-id "john@doe.com"
-               :name "Personal"}]})
+               :name "Personal"}]
+   :commodities [{:name "US Dollar"
+                  :symbol "USD"
+                  :type :currency
+                  :entity-id "Personal"}]})

 (def budget-context
   base-context)
@@ -176,6 +180,10 @@
 (def budget-item-context
   (-> base-context
       (update-in [:entities] #(conj % {:name "Business"}))
+      (update-in [:commodities] #(conj % {:name "US Dollar"
+                                          :symbol "USD"
+                                          :entity-id "Business"
+                                          :type :currency}))
       (merge {:accounts [{:name "Salary"
                           :type :income}
                          {:name "Rent"


update test to match behavior

update test to match behavior

--- test/clj_money/models/imports_test.clj
+++ test/clj_money/models/imports_test.clj
@@ -40,7 +40,8 @@
         expected [{:entity-name "import entity"
                    :user-id (:id user)
                    :progress {}
-                   :image-ids (map :id (:images context))}]]
+                   :image-ids (map :id (:images context))
+                   :entity-exists? false}]]
     (pprint-diff expected actual)
     (is (= expected actual))))


Fix bug in manual shrinking preventing changes at 1 PCT mutation rate

--- test/onyx/generative/manual_shrink.clj
+++ test/onyx/generative/manual_shrink.clj
@@ -2,7 +2,7 @@

 (defn mutate-bitmap [bitmap pct]
   (map (fn [bit]
-         (if (and (> (rand-int 100) (- 100 pct)) bit)
+         (if (and (< (rand) (/ pct 100)) bit)
            (not bit)
            bit))
        bitmap))
@@ -11,6 +11,7 @@
   (repeat (count cmds) true))

 (defn mutate [bitmap pct]
+  ;(println "bitmap is " bitmap)
   (update bitmap
           :phases
           (fn [phases]
@@ -24,6 +25,7 @@
           (map list phase bitmap))))

 (defn filter-generated [generated bitmaps]
+  ;(println "Phases " (:phases generated))
   (update generated
           :phases
           (fn [phases]
@@ -36,25 +38,30 @@
   (- (phases-count (:phases generated))))

 (defn print-generated-count [{:keys [phases uuid-seed]}]
-  (println "cmds cnt " (count (apply concat phases))))
+  (println "cmds cnt " (phases-count phases)))
+
+(defn bitmap-phases-count [phases]
+  (count (remove false? (apply concat phases))))

 (defn shrink-annealing [test-fn generated iterations]
   (let [initial-bitmap {:phases (map initial-bitmap (:phases generated))}
-        initial-count (count (remove false? (apply concat (:phases initial-bitmap))))]
+        initial-count (bitmap-phases-count (:phases initial-bitmap))]
     (loop [bitmap initial-bitmap
            iteration iterations]
       (if-not (zero? iteration)
-        (let [current-count (count (remove false? (apply concat (:phases bitmap))))
+        (let [current-count (bitmap-phases-count (:phases bitmap))
               ;; start at 10% and work down to flipping one on average
               pct (max (* 20 (/ iteration iterations))
                        (* 1 (/ initial-count current-count)))
+              ;_ (println "pct" pct)
               mutated-bitmap (mutate bitmap pct)
+              ;_ (println "Mutated " mutated-bitmap)
               mutate-generated (filter-generated generated mutated-bitmap)]
           (println "Before mutate count:")
           (println current-count)
           (println "After mutate count:")
           (print-generated-count mutate-generated)
-          (println "PCT" pct)
+          (println "PCT" (double pct))
           (if (and (> (fitness mutate-generated) (fitness generated))
                    (not (test-fn mutate-generated)))
             (recur mutated-bitmap (dec iteration))


add support for irregular imperfect

add support for irregular imperfect

--- src/babel/english/morphology.cljc
+++ src/babel/english/morphology.cljc
@@ -317,8 +317,48 @@
          stem (replace infinitive #"^to " "")]
      (str "will " stem))

-   ;; irregular imperfect
-   ;; TODO
+   ;; <irregular imperfect>
+   (let [number (get-in word '(:agr :number))
+         person (get-in word '(:agr :person))]
+     (and (= (get-in word [:infl]) :imperfect)
+          (string? (get-in word [:imperfect :1sing]))
+          (and (= person :1st) (= number :sing))))
+   (get-in word [:imperfect :1sing])
+
+   (let [number (get-in word '(:agr :number))
+         person (get-in word '(:agr :person))]
+     (and (= (get-in word [:infl]) :imperfect)
+          (string? (get-in word [:imperfect :2sing]))
+          (and (= person :2nd) (= number :sing))))
+   (get-in word [:imperfect :2sing])
+
+   (let [number (get-in word '(:agr :number))
+         person (get-in word '(:agr :person))]
+     (and (= (get-in word [:infl]) :imperfect)
+          (string? (get-in word [:imperfect :3plur]))
+          (and (= person :3rd) (= number :plur))))
+   (get-in word [:imperfect :3plur])
+   (let [number (get-in word '(:agr :number))
+         person (get-in word '(:agr :person))]
+     (and (= (get-in word [:infl]) :imperfect)
+          (string? (get-in word [:imperfect :1plur]))
+          (and (= person :1st) (= number :plur))))
+   (get-in word [:imperfect :1plur])
+
+   (let [number (get-in word '(:agr :number))
+         person (get-in word '(:agr :person))]
+     (and (= (get-in word [:infl]) :imperfect)
+          (string? (get-in word [:imperfect :2plur]))
+          (and (= person :2nd) (= number :plur))))
+   (get-in word [:imperfect :2plur])
+
+   (let [number (get-in word '(:agr :number))
+         person (get-in word '(:agr :person))]
+     (and (= (get-in word [:infl]) :imperfect)
+          (string? (get-in word [:imperfect :3plur]))
+          (and (= person :3rd) (= number :plur))))
+   (get-in word [:imperfect :3plur])
+   ;; </irregular imperfect>

    ;; regular imperfect
    (and (= (get-in word '(:infl)) :imperfect)


future with -re verbs

future with -re verbs

--- src/babel/francais/morphology.clj
+++ src/babel/francais/morphology.clj
@@ -235,6 +235,10 @@
                  ir-type (re-find #"ir$" infinitive)
                  re-type (re-find #"re$" infinitive)
                  stem (string/replace infinitive #"[iaeé]r$" "")
+                 stem (if re-type
+                        ;; prendre -> prend
+                        (string/replace infinitive #"re$" "")
+                        stem)
                  last-stem-char-is-i (re-find #"ir$" infinitive)
                  last-stem-char-is-e (re-find #"er$" infinitive)
                  person (get-in word '(:agr :person))
@@ -244,43 +248,51 @@

               (and (= person :1st) (= number :sing) er-type)
               (str stem "erai")
-
               (and (= person :1st) (= number :sing) ir-type)
               (str stem "iré")
+              (and (= person :1st) (= number :sing) re-type)
+              (str stem "rai")

               (and (= person :2nd) (= number :sing) ir-type)
               (str stem "iras")
               (and (= person :2nd) (= number :sing) er-type)
               (str stem "eras")
+              (and (= person :2nd) (= number :sing) re-type)
+              (str stem "ras")

               (and (= person :3rd) (= number :sing) ir-type)
               (str stem "ira")
               (and (= person :3rd) (= number :sing) er-type)
               (str stem "era")
+              (and (= person :3rd) (= number :sing) re-type)
+              (str stem "ra")

               (and (= person :1st) (= number :plur) er-type)
               (str stem "erons")
-
               (and (= person :1st) (= number :plur) ir-type)
               (str stem "irons")
+              (and (= person :1st) (= number :plur) re-type)
+              (str stem "rons")

               ;; <second person plural future>
               (and (= person :2nd) (= number :plur) er-type)
               (str stem "erez")
-
               (and (= person :2nd) (= number :plur) ir-type)
               (str stem "irez")
+              (and (= person :2nd) (= number :plur) re-type)
+              (str stem "rez")
               ;; </second person plural future>

               ;; <third person plural future>
               (and (= person :3rd) (= number :plur)
                    er-type)
               (str stem "eront")
-
               (and (= person :3rd) (= number :plur)
                    ir-type)
               (str stem "iront")
-
+              (and (= person :3rd) (= number :plur)
+                   re-type)
+              (str stem "ront")
               ;; </third person plural future>

               :else


+(defn gen-mark3): test with a spec having a :root form.

--- src/babel/italiano/benchmark.cljc
+++ src/babel/italiano/benchmark.cljc
@@ -99,5 +99,14 @@
                small
                do-this-many)))

+(defn gen-mark3 [do-this-many]
+  (let [do-this-many (Integer. do-this-many)]
+    (benchmark {:synsem {:subcat '()
+                         :essere true
+                         :sem {:tense :past
+                               :aspect :perfect}}
+                :root {:italiano {:italiano "andare"}}}
+               small
+               do-this-many)))


use new {:tokens/:parses} map output from (italiano.workbook/parse)

--- src/babel/italiano/benchmark.cljc
+++ src/babel/italiano/benchmark.cljc
@@ -31,12 +31,13 @@
                                                          :synsem {:cat :verb}}))]
                                (println (str "generated: " (fo expr)))
                                (println (str "starting parsing.."))
-                               (let [parsed (time (take 1 (parse (fo expr))))]
-                                 (if (empty? parsed)
+                               (let [parsed (time (take 1 (parse (fo expr))))
+                                     parses (reduce concat (map :parses parsed))]
+                                 (if (empty? parses)
                                    (throw (exception (str "could not parse: " (fo expr) " with semantics:"
                                                           (strip-refs (get-in expr [:synsem :sem]))))))

-                                 (println (str "parsed: " (fo (first parsed))))
+                                 (println (str "parsed: " (fo (first parses))))
                                  (println ""))))))))
 (defn -main [times]
   (run-benchmark times))


A small formatting tweak.

A small formatting tweak.

--- src/blutwurst/tuple_generator.clj
+++ src/blutwurst/tuple_generator.clj
@@ -95,7 +95,11 @@
         complex-generators (create-complex-property-generators spec table generated-data)]
        ; TODO: log missing generators
     (fn []
-      (->> (concat dependency-selectors complex-generators value-generators self-generators sequence-generators)
+      (->> (concat dependency-selectors
+                   complex-generators
+                   value-generators
+                   self-generators
+                   sequence-generators)
            (map #(%))
            (apply merge)))))


[core] Fix minor typo in a migration

[core] Fix minor typo in a migration

--- src/braid/core/server/migrate.clj
+++ src/braid/core/server/migrate.clj
@@ -65,7 +65,7 @@
       {:db/ident :quest-record/id
        :db/valueType :db.type/uuid
        :db/cardinality :db.cardinality/one
-       :db/unique :db.unique/identit}
+       :db/unique :db.unique/identity}
       {:db/ident :quest-record/quest-id
        :db/valueType :db.type/keyword
        :db/cardinality :db.cardinality/one}


Add link for feed autodiscovery

Add link for feed autodiscovery

http://technotes.iangreenleaf.com/posts/2013-10-17-rss-the-least-wrong-w
ay.html

--- src/clj/chili_dog_night/views.clj
+++ src/clj/chili_dog_night/views.clj
@@ -29,6 +29,7 @@
     (h/include-css "//fonts.googleapis.com/css?family=Playfair+Display:400,400italic,700,700italic,900,900italic")
     (h/include-css "/css/styles.css")
     [:title (str title " | " "Chili Dog Night")]
+    [:link {:rel "alternate" :type "application/rss+xml" :href "/rss" :title "Chili Dog Night"}]
     head]
    [:body
     (header)


sneaky bug for image on the fs where artist is not considered.

post-filtering tracks to artist_canonical fixes this.

subtle.....

--- src/clj/cljspazzer/http/album.clj
+++ src/clj/cljspazzer/http/album.clj
@@ -52,7 +52,9 @@
     result))

 (defn album-image [artist-id album-id]
-  (let [tracks (s/tracks-by-album s/the-db album-id)
+  (let [tracks (filter (fn [t]
+                         (= (utils/canonicalize artist-id) (:artist_canonical t)))
+                       (s/tracks-by-album s/the-db album-id))
         img (first (images-for-tracks tracks))]
     (if (nil? img)
       (let [cache-image (images/image-from-cache artist-id album-id)]


fix handling of records with ALL in cljs

--- src/clj/com/rpl/specter/navs.cljc
+++ src/clj/com/rpl/specter/navs.cljc
@@ -59,6 +59,13 @@

 (defn- all-transform-list [structure next-fn]
   (doall (sequence (comp (map next-fn) (filter not-NONE?)) structure)))
+
+(defn- all-transform-record [structure next-fn]
+  (reduce
+    (fn [res kv] (conj res (next-fn kv)))
+    structure
+    structure
+    ))

 (extend-protocol AllTransformProtocol
   nil
@@ -129,13 +136,10 @@
   (all-transform [structure next-fn]
     (non-transient-map-all-transform structure next-fn (empty structure)))

-  #?(:clj clojure.lang.IRecord :cljs cljs.core/IRecord)
+  #?(:clj clojure.lang.IRecord)
+  #?(:clj
   (all-transform [structure next-fn]
-    (reduce
-      (fn [res kv] (conj res (next-fn kv)))
-      structure
-      structure
-      ))
+    (all-transform-record structure next-fn)))

   #?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
   (all-transform [structure next-fn]
@@ -184,25 +188,28 @@
   #?(:cljs default)
   #?(:cljs
      (all-transform [structure next-fn]
-       (let [empty-structure (empty structure)]
-         (cond
-           (and (list? empty-structure) (not (queue? empty-structure)))
-           (all-transform-list structure next-fn)
-
-           (map? structure)
-           (reduce-kv
-             (fn [m k v]
-               (let [newkv (next-fn [k v])]
-                 (if (void-transformed-kv-pair? newkv)
-                  m
-                  (assoc m (nth newkv 0) (nth newkv 1)))))
-                  empty-structure
-                  structure)
-
-           :else
-           (into empty-structure
-                 (comp (map next-fn) (filter not-NONE?))
-                 structure))))))
+       (if (record? structure)
+         ;; this case is solely for cljs since extending to IRecord doesn't work for cljs
+         (all-transform-record structure next-fn)
+         (let [empty-structure (empty structure)]
+           (cond
+             (and (list? empty-structure) (not (queue? empty-structure)))
+             (all-transform-list structure next-fn)
+
+             (map? structure)
+             (reduce-kv
+               (fn [m k v]
+                 (let [newkv (next-fn [k v])]
+                   (if (void-transformed-kv-pair? newkv)
+                    m
+                    (assoc m (nth newkv 0) (nth newkv 1)))))
+                    empty-structure
+                    structure)
+
+             :else
+             (into empty-structure
+                   (comp (map next-fn) (filter not-NONE?))
+                   structure)))))))


Better exception message extraction.

Better exception message extraction.

--- src/cljs/cljs_bootstrap/core.cljs
+++ src/cljs/cljs_bootstrap/core.cljs
@@ -36,11 +36,11 @@
   "Iteratively extracts messages inside (nested #error objects), returns
   a string. Be sure to pass #error object here."
   [err]
-  (loop [e err msgs (.-message err)]
+  (loop [e err msgs [(.-message err)]]
     (if-let [next-err (.-cause e)]
-      (recur next-err (str msgs " - " (.-message next-err)))
-      (if-not (nil? msgs)
-        msgs
+      (recur next-err (conj msgs (.-message next-err)))
+      (if (seq msgs)
+        (clojure.string/join " - " msgs)
         ""))))

 (defn ^:export exception->str


403 -> unauthorized redirect

403 -> unauthorized redirect

--- src/cljs/swarmpit/controller.cljs
+++ src/cljs/swarmpit/controller.cljs
@@ -25,8 +25,9 @@
 (defn get
   ([api success-fx]
    (get api success-fx (fn [{:keys [status]}]
-                         (if (= status 401)
-                           (dispatch {:handler :unauthorized})
+                         (case status
+                           401 (dispatch {:handler :unauthorized})
+                           403 (dispatch {:handler :unauthorized})
                            (dispatch {:handler :error})))))
   ([api success-fx error-fx]
    (ajax/GET api
@@ -76,7 +77,7 @@

 (defmethod dispatch :service-create-image
   [{:keys [handler]}]
-  (get (routes/path-for-backend :registries-list)
+  (get (routes/path-for-backend :registries)
        (fn [registries]
          (get (routes/path-for-backend :dockerhub-users-list)
               (fn [users]


add clear error on missing version.edn

add clear error on missing version.edn

--- src/clojupyter/kernel/version.clj
+++ src/clojupyter/kernel/version.clj
@@ -12,7 +12,8 @@
 (def ^:private version-data
   (fn []
     (when-let [f (or (io/resource VERSION-FILENAME)
-                     (io/file (str "resources/" VERSION-FILENAME)))]
+                     (io/file (str "resources/" VERSION-FILENAME))
+                     (throw (Exception. "version.edn not found")))]
       (-> f slurp edn/read-string))))

 (defn version-string*


Remove core.async reference from nanomsg.benchmark ns.

--- src/clojure/nanomsg/benchmark.clj
+++ src/clojure/nanomsg/benchmark.clj
@@ -1,8 +1,6 @@
 (ns nanomsg.benchmark
   (:require [nanomsg.core :as nn]
-            [octet.core :as buf]
-            ;; [nanomsg.async :as nna]
-            [clojure.core.async :as async])
+            [octet.core :as buf])
   (:gen-class))

 (defn- sleep


Make functions to fix weird ParinferResult behavior

--- src/clojure/nightcode/editors.clj
+++ src/clojure/nightcode/editors.clj
@@ -290,6 +290,14 @@
       (.apply text-area))
   (set-font-size! text-area @font-size))

+(defn paren-mode [text x line]
+  (let [res (Parinfer/parenMode text (int x) (int line) nil)]
+    {:x (.-cursorX res) :text (.-text res)}))
+
+(defn indent-mode [text x line]
+  (let [res (Parinfer/indentMode text (int x) (int line) nil)]
+    {:x (.-cursorX res) :text (.-text res)}))
+
 (defn init-parinfer!
   [text-area extension]
   (when (contains? utils/clojure-exts extension)
@@ -298,30 +306,30 @@
           old-x (.getCaretOffsetFromLineStart text-area)
           old-line (.getCaretLineNumber text-area)
           old-text (.getText text-area)
-          result (Parinfer/parenMode old-text old-x old-line nil)
-          new-text (.-text result)]
+          result (paren-mode old-text old-x old-line)
+          new-text (:text result)
+          new-x (:x result)
+          new-pos (+ old-pos (- new-x old-x))]
       (.setText text-area new-text)
-      (.setCaretPosition text-area old-pos)
+      (.setCaretPosition text-area new-pos)
       (.discardAllEdits text-area)
       (.setDirty text-area (not= old-text new-text)))
     ; add a listener to run indent mode when a key is pressed
     (.addKeyListener text-area
       (reify KeyListener
         (keyReleased [this e]
-          (when-not (contains? #{KeyEvent/VK_DOWN
-                                 KeyEvent/VK_UP
-                                 KeyEvent/VK_RIGHT
-                                 KeyEvent/VK_LEFT}
+          (when-not (contains? #{KeyEvent/VK_DOWN KeyEvent/VK_UP
+                                 KeyEvent/VK_RIGHT KeyEvent/VK_LEFT}
                                (.getKeyCode e))
             (let [old-pos (.getCaretPosition text-area)
                   old-x (.getCaretOffsetFromLineStart text-area)
                   old-line (.getCaretLineNumber text-area)
                   old-text (.getText text-area)
                   result (if (= (.getKeyCode e) KeyEvent/VK_ENTER)
-                           (Parinfer/parenMode old-text old-x old-line nil)
-                           (Parinfer/indentMode old-text old-x old-line nil))
-                  new-text (.-text result)
-                  new-x (.-cursorX result)
+                           (paren-mode old-text old-x old-line)
+                           (indent-mode old-text old-x old-line))
+                  new-text (:text result)
+                  new-x (:x result)
                   new-pos (+ old-pos (- new-x old-x))]
               (.setText text-area new-text)
               (.setCaretPosition text-area new-pos))))


Added about page

Added about page

--- src/clojure/staircase/handler.clj
+++ src/clojure/staircase/handler.clj
@@ -181,7 +181,8 @@
   (routes
     (GET "/" [] (views/index))
     (GET "/history/:id/:idx" [] (views/index))
-    (GET "/tools" [capability] (response (get-tools conf capability)))
+    (GET "/about" [] (views/index))
+    (GET "/tools" [capabilities] (response (get-tools conf capabilities)))
     (GET "/tools/:id" [id] (if-let [tool (get-tool conf id)]
                              (response tool)
                              {:status 404}))


Improved shape component for proper handle shapes in groups.

--- src/uxbox/ui/workspace/canvas.cljs
+++ src/uxbox/ui/workspace/canvas.cljs
@@ -8,7 +8,7 @@
             [uxbox.rstore :as rs]
             [uxbox.state :as st]
             [uxbox.xforms :as xf]
-            [uxbox.shapes :as shapes]
+            [uxbox.shapes :as sh]
             [uxbox.util.lens :as ul]
             [uxbox.library.icons :as _icons]
             [uxbox.data.projects :as dp]
@@ -49,35 +49,60 @@
 ;; Shape
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+(declare shape)
+
 (defn shape-render
-  [own shape selected]
-  (let [{:keys [id x y width height] :as shape} shape
-        selected? (contains? selected id)]
+  [own item selected]
+  (let [{:keys [id x y width height group] :as item} item
+        selected? (contains? selected id)
+        local (:rum/local own)]
     (letfn [(on-mouse-down [event]
-              (when-not (:blocked shape)
-                (let [local (:rum/local own)]
+              (when-not (:blocked item)
+                ;; (let [local (:rum/local own)]
+                ;;   (swap! local assoc :init-coords [x y])
+                ;;   (reset! wb/shapes-dragging? true))
+                (cond
+                  (and group (:locked (sh/resolve-parent item)))
+                  nil
+
+                  (and (not selected?) (empty? selected))
+                  (do
+                    (dom/stop-propagation event)
+                    (swap! local assoc :init-coords [x y])
+                    (reset! wb/shapes-dragging? true)
+
+                    (rs/emit! (dw/select-shape id)))
+
+                  (and (not selected?) (not (empty? selected)))
+                  (do
+                    (dom/stop-propagation event)
+                    (swap! local assoc :init-coords [x y])
+                    (reset! wb/shapes-dragging? true)
+                    (if (.-ctrlKey event)
+                      (rs/emit! (dw/select-shape id))
+                      (rs/emit! (dw/deselect-all)
+                                (dw/select-shape id))))
+
+                  :else
+                  (do
+                    (dom/stop-propagation event)
+                    (swap! local assoc :init-coords [x y])
+                    (reset! wb/shapes-dragging? true)))))
+
+            (on-mouse-up [event]
+              (cond
+                (and group (:locked (sh/resolve-parent item)))
+                nil
+
+                :else
+                (do
                   (dom/stop-propagation event)
-                  (swap! local assoc :init-coords [x y])
-                  (reset! wb/shapes-dragging? true))
-                (cond
-                  (and (not selected?)
-                       (empty? selected))
-                  (rs/emit! (dw/select-shape id))
-
-                  (and (not selected?)
-                       (not (empty? selected)))
-                  (if (.-ctrlKey event)
-                    (rs/emit! (dw/select-shape id))
-                    (rs/emit! (dw/deselect-all)
-                              (dw/select-shape id))))))
-            (on-mouse-up [event]
-              (dom/stop-propagation event)
-              (reset! wb/shapes-dragging? false))]
+                  (reset! wb/shapes-dragging? false))))]
       (html
        [:g.shape {:class (when selected? "selected")
                   :on-mouse-down on-mouse-down
                   :on-mouse-up on-mouse-up}
-        (shapes/-render shape nil)]))))
+        (sh/-render item #(shape % selected))]))))

 (def ^:static shape
   (mx/component


avoid race condition when writing externs.shadow.js

the dir might not exist yet if other cache writes are queued

--- src/main/shadow/build/closure.clj
+++ src/main/shadow/build/closure.clj
@@ -312,6 +312,7 @@

     ;; not actually required but makes it easier to verify
     (let [file (data/cache-file state "externs.shadow.js")]
+      (io/make-parents file)
       (spit file content))

     (SourceFile/fromCode "externs.shadow.js" content)