Fleshing out visitors.

Fleshing out visitors.

--- src/dependency_reader/reader.clj
+++ src/dependency_reader/reader.clj
@@ -79,6 +79,17 @@
            ;####TODO!!!!
          }))

+(defn- visit-method
+  [class-info access name ^String desc signature exceptions]
+  (let [fixed-exception-names (vec (map fix-type-name exceptions))
+        existing-dependencies (:dependencies class-info)
+        argument-types        (vec (map #(.getClassName %) (org.objectweb.asm.Type/getArgumentTypes desc)))
+        return-type           (.getClassName (org.objectweb.asm.Type/getReturnType desc))]
+    (merge class-info
+           {
+             :dependencies (add-dependency (add-dependencies (add-dependencies existing-dependencies fixed-exception-names :uses) argument-types :uses) return-type :uses)
+           })))
+
 (defn class-info
   "Takes an input stream of class bytes and returns the dependencies it contains as a map with this shape:

@@ -117,6 +128,10 @@
                                   (visitField [access field-name desc signature value]
                                     (swap! result visit-field access field-name desc signature value)
                                     field-visitor)
+                                  (visitMethod [access name desc signature exceptions]
+                                    (swap! result visit-method access name desc signature exceptions)
+                                    ;method-visitor)
+                                    nil)
                            )]
     (.accept class-reader class-visitor 0)
     @result))


simple fix for adzerk/boot-cljs#44

simple fix for adzerk/boot-cljs#44

--- src/adzerk/boot_cljs/middleware.clj
+++ src/adzerk/boot_cljs/middleware.clj
@@ -99,7 +99,7 @@
   (let [[path file] ((juxt core/tmppath core/tmpfile) main)
         base-name   (-> file .getName deps/strip-extension)
         js-path     (.getPath (io/file tmp-out (str base-name ".js")))
-        cljs-path   (.getPath (util/replace-path path (str base-name ".cljs")))
+        cljs-path   (.getPath (io/file (str "boot/cljs/" base-name ".cljs")))
         cljs-file   (doto (io/file tmp-src cljs-path) io/make-parents)
         cljs-ns     (symbol (util/path->ns cljs-path))
         main-edn    (read-string (slurp file))
@@ -150,13 +150,12 @@
           output-to   (output-path-for shim-path)
           output-dir  (util/get-name (:output-dir opts))
           cljs-paths  (map core/tmppath (:cljs files))
-          main*       (-> main core/tmppath deps/strip-extension)
           rooted-path #(util/rooted-relative docroot (core/tmppath %))
           scripts     (-> (:incs files)
                           (->> (mapv rooted-path))
                           (conj (io/file output-dir "goog" "base.js"))
                           (conj (util/get-name output-to)))]
-      (->> (write-body (file->goog main*))
+      (->> (write-body (file->goog "boot/cljs/main"))
            (format shim-js shim-name (apply str (map write-src scripts)))
            (spit shim-path))
       (assoc-in ctx [:opts :output-to] output-to))))


macro variant

macro variant

--- core.clj
+++ core.clj
@@ -100,9 +100,10 @@
   (let [sym (symbol (last (re-seq #"[^\.]+" (str tag))))
         once (gensym (str "_once_" sym))
         pair-sym (symbol (str "Pair-" sym))
+        qualified-pair-sym (symbol (str "tween.core.Pair-" sym))
         wm-f #(with-meta % {:tag tag :volatile-mutable true})
         pool-m (zipmap [:p :c :r] (map (comp symbol str) ["<>" "*" "!"] (repeat pair-sym)))
-        entry (conj methods {:pair {:tag pair-sym :pool pool-m}})]
+        entry (conj methods {:pair {:tag qualified-pair-sym :pool pool-m}})]

     `(do
         (defonce ~once
@@ -121,14 +122,15 @@
 (def-pool 1000 WaitCursor start initiated)

 (defn wait [n]
-  (let [cursor (*WaitCursor 0 false)]
+  (let [cursor (*WaitCursor (float 0) false)]
     (fn []
       (when-not (.initiated cursor)
         (set! (.initiated cursor) true)
         (set! (.start cursor) Time/time))
-      (if (pos? (- (+ (.start cursor) n) Time/time))
+      (if (pos? (- (+ (.start cursor) (float n)) Time/time))
         true
-        (!WaitCursor cursor)))))
+        (!WaitCursor cursor)
+        ))))

@@ -142,24 +144,6 @@
 (def <over> (*TimeLineCursor 0 false 0.0))

 (defn timeline [fns]
-  (assert (vector? fns) "timeline requires a vector")
-  (let [cnt (count fns)
-        ^MonoBehaviour coro-root (mono-obj)
-        ^TimeLineCursor cursor (*TimeLineCursor 0 false 0.0)]
-    (.StartCoroutine coro-root
-      (reify IEnumerator
-        (MoveNext [this]
-          (set! (.v cursor)
-                (try ((get fns (.i cursor)))
-                     (catch Exception e false)))
-          (if (.v cursor) true
-            (if (<= (.i cursor) cnt)
-                (set! (.i cursor) (inc (.i cursor)))
-                (!TimeLineCursor cursor))))
-        (get_Current [this] (.v cursor))))
-    (fn [] false)))
-
-(defn lazy-timeline [fns]
   (let [current (volatile! (first fns))
         fns (volatile! (rest fns))
         ^MonoBehaviour coro-root (mono-obj)
@@ -168,34 +152,51 @@
       (reify IEnumerator
         (MoveNext [this]
           (when-not panic
-            (set! (.v cursor) (@current))
-            (if (.v cursor) true
-              (if (do (vreset! current (first @fns) )
-                      (vswap! fns rest) @current)
-                true
-                (!TimeLineCursor cursor)))))
+            (try
+              (set! (.v cursor) (@current))
+              (if (.v cursor) true
+                (if (do (vreset! current (first @fns) )
+                        (vswap! fns rest) @current)
+                  true
+                  (!TimeLineCursor cursor)
+                  ))
+              (catch Exception e false))))
         (get_Current [this] (.v cursor))))
     (fn [] (if @current true false))))

-(defn lazier-timeline [fns]
-  (let [fns (map #(%) fns)
-        current (volatile! (first fns))
-        fns (volatile! (rest fns))
+(defn timeline-1 [fns] (timeline (map #(%) fns)))
+
+(defn array-timeline [^|System.Object[]| fns]
+  (let [cnt (long (dec (count fns)))
         ^MonoBehaviour coro-root (mono-obj)
         ^TimeLineCursor cursor (*TimeLineCursor 0 false 0.0)]
     (.StartCoroutine coro-root
       (reify IEnumerator
         (MoveNext [this]
-          (when-not panic
-            (try (set! (.v cursor) (@current))
-              (if (.v cursor) true
-                (if (do (vreset! current (first @fns))
-                        (vswap! fns rest) @current)
-                    true
-                  (!TimeLineCursor cursor)))
-              (catch Exception e false))))
+          (set! (.v cursor)
+                (try (((aget fns (.i cursor))))
+                     (catch Exception e (log e))))
+          (if (.v cursor) true
+            (if (< (.i cursor) cnt)
+                (set! (.i cursor) (inc (.i cursor)))
+                (!TimeLineCursor cursor))))
         (get_Current [this] (.v cursor))))
-    (fn [] (if @current true false))))
+    (fn [] false)))
+
+(defmacro timeline* [& fns]
+  (let [[opts fns] ((juxt (comp set filter) remove) keyword? fns)
+        ar (gensym)]
+    `(let [~ar (make-array ~'System.Object ~(count fns))]
+      ~@(map-indexed #(list 'aset ar %1 (list 'fn [] %2)) fns)
+      (~'array-timeline ~ar))
+    ))
+
+(ppexpand
+  (timeline* #(log "hello")
+    (wait 0.5)
+
+
+     #(log "hello2")))

@@ -248,10 +249,12 @@
             (with-meta %3 {:tag (or (-> %2 :pair :tag) '*Pair-Object)})
             (list (or (-> %2 :pair :pool :c) '*Pair) (:identity %2) %4))
           tags tagmaps pairsyms targets)]
+
    `(~'let [~THIS ~o
-            ~cursor (~'*TweenCursor false ~'(float Time/time) ~(:duration opts) (float 0.0) (float 0.0))
-            ~@val-binds]
+          ~cursor (~'*TweenCursor false ~'(float Time/time) ~(:duration opts) (float 0.0) (float 0.0))
+          ~@val-binds]
       (~'fn []
+
         (~'when-not ~'(.initiated cursor)
         ~'(set! (.initiated cursor) true)
         ~'(set! (.start cursor) (- Time/time (.overage <over>)) )
@@ -343,43 +346,33 @@
 (def run true)

 (defn hue [^UnityEngine.Material m ^UnityEngine.GameObject o]
-  (lazier-timeline (cycle [
-    (fn [] (wait (+ (rand) 0.3)))
-    (fn [] (tween {:material-color (UnityEngine.Color. (?f) (?f) (?f))} m 0.5 {:in :pow3}))
-    (fn [] (tween
-      {:local {
-        :scale (Vector3. 2.0 2.0 2.0)
-        :position (v3+ (.position (.transform o))
-                       (Vector3. 0.0 2.0 0.0))}} o 1.0 {:in :pow5}))
-    ;(fn [] (wait (+ (rand) 0.1)))
-    (fn [] (tween {:material-color (UnityEngine.Color. 1 1 1)} m 0.5 {:in :pow3}))
-    (fn [] (tween
-     {:local {
-        :scale (Vector3. 1.0 1.0 1.0)
-        :position (v3+ (.position (.transform o))
-                      (Vector3. 0.0 0.0 0.0))}} o 0.5 :pow5))])))
+  (timeline-1
+    (cycle [
+      (fn [] (wait (+ (rand) 0.3)))
+      (fn [] (tween {:material-color (UnityEngine.Color. (?f) (?f) (?f))} m 0.5 {:in :pow3}))
+      (fn [] (tween
+        {:local {
+          :scale (Vector3. 2.0 2.0 2.0)
+          :position (v3+ (.position (.transform o))
+                         (Vector3. 0.0 2.0 0.0))}} o 1.0 {:in :pow5}))
+      ;(fn [] (wait (+ (rand) 0.1)))
+      (fn [] (tween {:material-color (UnityEngine.Color. 1 1 1)} m 0.5 {:in :pow3}))
+      (fn [] (tween
+       {:local {
+          :scale (Vector3. 1.0 1.0 1.0)
+          :position (v3+ (.position (.transform o))
+                        (Vector3. 0.0 0.0 0.0))}} o 0.5 :pow5))])))

 (defn start-demo [_]
   (clear-cloned!)
-  (dorun (for [x (range 20)
-               z (range 20)
+  (dorun (for [x (range 13)
+               z (range 13)
                :let [o (clone! :ball (V* (->v3 x 0 z) 2.0)) ]]
     (hue (.material (.GetComponent o UnityEngine.Renderer)) o))) )

-
-(defn fast-demo [_]
-  (clear-cloned!)
-  (let [o-arr
-        (into-array System.Object
-          (for [x (range 20) z (range 20)
-            :let [o (clone! :ball (V* (->v3 x 0 z) 2.0)) ]] o))]
-    ) )
-
-(fast-demo nil)
-
-(lazy-timeline [
-(tween
+'(timeline [
+  (tween
   {:light {
     :range (float (+ 15 (rand 50)))
     :color (color (rand-vec 1.0 1.0 1.0))}}


Remove 1.2 check, since it's also done in sweet.clj now.

--- src/midje/repl.clj
+++ src/midje/repl.clj
@@ -19,10 +19,6 @@
             [midje.emission.boundaries :as emission-boundary]
             [midje.emission.colorize :as color]
             [midje.emission.api :as emit]))
-
-(when (and (config/running-in-repl?) (ecosystem/clojure-1-2-X?))
-  (println (color/fail "The Midje repl tools don't work on Clojure 1.2.X")))
-(ecosystem/when-1-3+

 (fact-data/make-getters *ns* "fact-")

@@ -528,4 +524,3 @@
               (autotest)))))
   true)

-)  ;; when-1-3+


Get-job should distinguish between code 400 and 404

--- src/emender_jenkins/rest_api.clj
+++ src/emender_jenkins/rest_api.clj
@@ -33,7 +33,8 @@
     :disable-job           "disable_job"
     :create-job            "create_job"
     :delete-job            "delete_job"
-    :update-job            "update_job"})
+    :update-job            "update_job"
+    :get-job               "get_job"})

 ; HTTP codes used by several REST API responses
 (def http-codes {
@@ -275,11 +276,10 @@
         (if job-name
             (let [job-metadata (results/find-job-with-name job-name)]
                  (if job-metadata
-                     (send-response job-metadata request))
-                     (-> (job-does-not-exist-response job-name "get-job")
-                         (send-error-response request :not-found)))
-            (-> (job-does-not-exist-response job-name "get-job")
-                (send-error-response request :bad-request)))))
+                     (send-response job-metadata request)
+                     (-> (create-error-response job-name :get-job "Test results does not exist")
+                         (send-error-response request :not-found))))
+            (send-job-not-specified-response request :get-job))))

 (defn get-jobs
     [request]


Convert layers.clj to use util/empty-array where appropriate

--- src/cortex/layers.clj
+++ src/cortex/layers.clj
@@ -30,8 +30,8 @@
     (when-not (coll? shape)
       (error "logistic layer constructor requires a shape vector"))
     (cortex.impl.layers.Logistic.
-      (m/ensure-mutable (m/new-array :vectorz shape))
-      (m/ensure-mutable (m/new-array :vectorz shape)))))
+      (util/empty-array shape)
+      (util/empty-array shape))))

 (defn dropout
   "Creates a dropout module of the given shape.
@@ -41,10 +41,10 @@
     (when-not (coll? shape)
       (error "logistic layer constructor requires a shape vector"))
     (cortex.impl.layers.Dropout.
-      (m/ensure-mutable (m/new-array :vectorz shape))
-      (m/ensure-mutable (m/new-array :vectorz shape))
+      (util/empty-array shape)
+      (util/empty-array shape)
       (double probability)
-      (m/ensure-mutable (m/new-array :vectorz shape)))))
+      (util/empty-array shape))))

 (defn scale
   "Creates a scaling layer with the specified shape and multiplication factor"
@@ -62,8 +62,8 @@
     (when-not (coll? shape)
       (error "softmax layer constructor requires a shape vector"))
     (cortex.impl.layers.Softmax.
-        (m/ensure-mutable (m/new-array :vectorz shape))
-        (m/ensure-mutable (m/new-array :vectorz shape)))))
+        (util/empty-array shape)
+        (util/empty-array shape))))

 (defn relu
   "Creates a rectified linear (ReLU) module of the given shape.
@@ -74,9 +74,9 @@
     (when-not (coll? shape)
       (error "relu layer constructor requires a shape vector"))
     (cortex.impl.layers.RectifiedLinear.
-        (m/ensure-mutable (m/new-array :vectorz shape))
-        (m/ensure-mutable (m/new-array :vectorz shape))
-        (m/ensure-mutable (m/new-array :vectorz shape))
+        (util/empty-array shape)
+        (util/empty-array shape)
+        (util/empty-array shape)
         negval)))

 (defn linear
@@ -91,15 +91,15 @@
           n-inputs (long n-inputs)]
       (when-not (== n-outputs (m/dimension-count bias 0)) (error "Mismatched weight and bias shapes"))
       (-> wm
-        (assoc :weight-gradient (m/new-vector :vectorz (* n-outputs n-inputs)))
-        (assoc :bias-gradient (m/new-vector :vectorz n-outputs))
-        (assoc :input-gradient (m/new-vector :vectorz n-inputs))))))
+        (assoc :weight-gradient (util/empty-array [(* n-outputs n-inputs)]))
+        (assoc :bias-gradient (util/empty-array [n-outputs]))
+        (assoc :input-gradient (util/empty-array [n-inputs]))))))

 (defn linear-layer
   "Creates a linear layer with a new randomised weight matrix for the given number of inputs and outputs"
   ([n-inputs n-outputs]
     (linear (util/weight-matrix n-outputs n-inputs)
-            (m/new-vector :vectorz n-outputs))))
+            (util/empty-array [n-outputs]))))

 (defn split
   "Creates a split later using a collection of modules. The split layer returns the outputs of each
@@ -127,13 +127,13 @@
   ([shape {:keys [learn-rate normaliser-factor] :as options}]
     (when-not (coll? shape)
       (error "normaliser layer constructor requires a shape vector"))
-    (let [output (m/new-array :vectorz shape)
-          input-gradient (m/new-array :vectorz  shape)
-          mean (m/new-array :vectorz shape)
-          sd (m/new-array :vectorz shape)
-          acc-ss (m/new-array :vectorz shape)
-          acc-mean (m/new-array :vectorz shape)
-          tmp (m/new-array :vectorz shape)
+    (let [output (util/empty-array shape)
+          input-gradient (util/empty-array shape)
+          mean (util/empty-array shape)
+          sd (util/empty-array shape)
+          acc-ss (util/empty-array shape)
+          acc-mean (util/empty-array shape)
+          tmp (util/empty-array shape)
           ]
       (m/fill! sd 1.0)
       (m/fill! acc-ss 1.0)


Namespaced keyword (#212)

Namespaced keyword (#212)

--- src/cljs/bundled/lumo/analyzer.cljs
+++ src/cljs/bundled/lumo/analyzer.cljs
@@ -217,7 +217,7 @@
                path    (.-src res)
                cache   nil #_(when (:cache-analysis opts)
                          (cache-file res ns-info output-dir))]
-           (when-not (get-in @env/*compiler* [::namespaces (:ns ns-info) :defs])
+           (when-not (get-in @env/*compiler* [::ana/namespaces (:ns ns-info) :defs])
              (if (or skip-cache (not cache) (requires-analysis? res output-dir))
                (binding [ana/*cljs-ns* 'cljs.user
                          ana/*cljs-file* path


Improve paredit again

Improve paredit again

--- src/clojure/paredit_widget/core.clj
+++ src/clojure/paredit_widget/core.clj
@@ -62,13 +62,13 @@
    [nil "\b"] :paredit-backward-delete
    [nil "DEL"] :paredit-forward-delete
    [nil "\""] :paredit-doublequote ;; \"
-   ["M" "("] :paredit-wrap-round
-   ["M" "s"] :paredit-splice-sexp
-   ["M" "r"] :paredit-raise-sexp
    ["C" "9"] :paredit-backward-slurp-sexp
    ["C" "0"] :paredit-forward-slurp-sexp
    ["C" "["] :paredit-backward-barf-sexp
    ["C" "]"] :paredit-forward-barf-sexp
+   ["M" "("] :paredit-wrap-round
+   ["M" "s"] :paredit-splice-sexp
+   ["M" "r"] :paredit-raise-sexp
    ["M" "S"] :paredit-split-sexp
    ["M" "J"] :paredit-join-sexps
    ["M" "Left"] :paredit-expand-left
@@ -77,6 +77,8 @@
 (def ^:const advanced-alternative-keymap
   {[nil "⌫"] :paredit-backward-delete
    [nil "⌦"] :paredit-forward-delete
+   ["C" "Open Bracket"] :paredit-backward-barf-sexp
+   ["C" "Close Bracket"] :paredit-forward-barf-sexp
    ["M" "←"] :paredit-expand-left
    ["M" "→"] :paredit-expand-right})


Include contribution panel

Include contribution panel

--- src/discuss/core.cljs
+++ src/discuss/core.cljs
@@ -8,6 +8,7 @@
             [discuss.references.integration]
             [discuss.utils.extensions]
             [discuss.utils.common :as lib]
+            [discuss.components.contribute :as contribute]
             [discuss.components.tooltip :as tooltip]
             [discuss.views :as views]))

@@ -28,6 +29,9 @@
 (om/root tooltip/view {}
          {:target (.getElementById js/document (lib/prefix-name "tooltip"))})

+(om/root contribute/view {}
+         {:target (.getElementById js/document (lib/prefix-name "contribute"))})
+
 (om/root debug/debug-view lib/app-state
          {:target (.getElementById js/document "debug")})


GET entities as tall CSVs

GET entities as tall CSVs

--- src/kixi/hecuba/api/entities.clj
+++ src/kixi/hecuba/api/entities.clj
@@ -63,13 +63,231 @@
         (allowed?* programme_id project_id programmes projects roles request-method)
         true))))

+;; hang on a minute, do we need the whole schema or shall we aggregate everything
+;; in the property_data field?!
+(def property-data-schema
+  [:description
+   :monitoring_policy
+   :address_street
+   :address_city
+   :address_county
+   :address_code
+   :created_at
+   :updated_at
+   :address_country
+   :terrain
+   :address_region
+   :degree_day_region
+   :ownership
+   :fuel_poverty
+   :property_value
+   :property_value_basis
+   :retrofit_start_date
+   :retrofit_completion_date
+   :project_summary
+   :energy_strategy
+   :project_team
+   :design_strategy
+   :other_notes
+   :property_type
+   :property_type_other
+   :built_form
+   :built_form_other
+   :age
+   :construction_date
+   :conservation_area
+   :listed
+   :address_street_two
+   :property_code
+   :monitoring_hierarchy
+   :project_phase
+   :construction_start_date
+   :practical_completion_date
+   :photo_file_name
+   :photo_content_type
+   :photo_file_size
+   :photo_updated_at
+   :completeness
+   :entity_completeness_6m
+   :latitude
+   :longitude
+   :technology_icons
+   :address_code_masked])
+
+(def content-only-schema
+  [])
+
+(def document-schema
+  [:id
+   :content-type
+   :name
+   :file_name])
+
+(def photo-schema
+  [:path])
+
+(def entity-schema
+  [:id
+   :address_country
+   :address_county
+   :address_region
+   :address_street_two
+   :name
+   :project_id
+   :user_id
+   :property_code
+   :retrofit_completion_date
+   { :name :property_data
+     :type :nested-item
+     :schema property-data-schema }
+   { :name :documents
+     :type :associated-items
+     :schema document-schema }
+   { :name :notes
+     :type :associated-items
+     :schema content-only-schema }
+   { :name :photos
+     :type :associated-items
+     :schema photo-schema }
+   ])
+
+(defn attribute-type [attr]
+  (if (keyword? attr)
+    :attribute
+    (:type attr)))
+
+(defn explode-nested-item [association item-string]
+  "Explodes a nested item, that is represented in the object coming from
+  the datastore as a json encoded string. Returns a list of vectors of
+  two elements, the first being the attribute key, and the second the value.
+  The key is expanded to <nested item name>_<attribute name>"
+  (let [item (json/decode item-string)
+        association-name   (:name   association)
+        association-schema (:schema association)]
+    (map
+     (fn [attr]
+       [(str (name association-name) "_" (name attr)) (item (name attr))])
+     association-schema)))
+
+(defn explode-associated-items [association items]
+  "Explodes the elements of a (one to many) association, that is represented
+  in the object coming from the datastore as a list of json encoded strings.
+  Returns a list of vectors of two elements, the first being the attribute key,
+  and the second the value.
+  The keys are expanded like <association name>_<associated item index>_<attribute name>"
+  (let [association-name   (name (:name association))
+        association-schema (:schema association)]
+    (apply concat
+    (map-indexed
+      (fn [index item-string]
+         (let [item-name         (str association-name "_" index)
+               named-association (assoc association :name item-name)]
+           (if (empty? association-schema)
+             [item-name item-string]
+             (explode-nested-item named-association item-string))))
+      items))))
+
+(defn explode-and-sort-by-schema [item schema]
+  "Take a (profile) item from the datastore and converts into a list
+  of pairs (represented as a vector) where the first element is the
+  exploded key for the attribute and the second is the value"
+  (let [exploded-item
+         (mapcat
+           (fn [attr]
+             (let [t (attribute-type attr)]
+               (case t
+                 :attribute          (list [(name attr) (item attr)])
+                 :nested-item        (explode-nested-item attr (item (:name attr)))
+                 :associated-items   (explode-associated-items attr (item (:name attr))))))
+           schema)]
+    exploded-item))
+
+(defn extract-attribute [attr-key input]
+  "Extracts a hash-map containing a single key and its value from the input.
+  The key is expected to be a keyword, while input is supposed to be a hash-map
+  with strings as keys"
+  (let [attr-name (name attr-key)
+        attr-value (input attr-name)]
+  {attr-key attr-value}))
+
+(defn extract-nested-item [attr input]
+  "Extracts a nested item from input, returning a hashmap with a single pair,
+  where the key is the nested item association name, and the value is a json
+  string representing all the attributes of the nested item.
+  attr is expected to be a hash-map with at least :name and :schema keys,
+  while input is expected to be a hash-map representing the profile, with strings as keys"
+  (let [association-name   (:name   attr)
+        association-schema (:schema attr)
+        nested-item (reduce
+                      (fn [nested-item nested-attr]
+                        (let [nested-attr-name (name nested-attr)
+                              exploded-attr-name (str (name association-name) "_" nested-attr-name)]
+                          (conj nested-item { nested-attr (input exploded-attr-name)})))
+                      {}
+                      association-schema)]
+    {association-name nested-item}))
+
+(defn extract-associated-item [association-name association-schema input index]
+  "Extracts the item belonging to a 'has many' association from input, at position index."
+  (reduce
+    (fn [associated-item associated-item-attr]
+      (let [associated-item-attr-name (name associated-item-attr)
+            exploded-attr-name (str (name association-name) "_" index "_" associated-item-attr-name)]
+        (conj associated-item {associated-item-attr (input exploded-attr-name)})))
+    {}
+    association-schema))
+
+(defn extract-associated-items [attr input]
+  "Extracts a collection representing a 'has many' association from input.
+  It returns a list of hash-maps, each representing one of the items from
+  the association.
+  attr is expected to be a hash-map with at least :name and :schema keys,
+  while input is expected to be a hash-map representing the whole profile, with strings as keys"
+  (let [association-name   (:name attr)
+        association-schema (:schema attr)
+        attribute-names    (doall (keys input))
+        items-id-pattern   (re-pattern (str (name association-name) "_(\\d+)_"))
+        items-ids (into #{} (->> attribute-names
+                                 (map #(when-some [x (re-find items-id-pattern %)] (last x)))
+                                 (filter #(not (nil? %)))))
+        associated-items (map #(extract-associated-item association-name association-schema input %) items-ids) ]
+    {association-name associated-items}))
+
+(defn parse-by-schema [input schema]
+  "Parses input according to schema, assuming it was shaped as a
+  'tall' CSV profile.
+  This means that the first column contains attribute names, and the
+  second column contains values. Attribute names are presented in
+  'exploded' format, in order to properly address associations and
+  nesting.
+  Example:
+
+  attribute type | attribute name              | exploded name              |
+  standard       | timestamp                   | timestamp                  |
+  nested item    | profile_data, bedroom_count | profile_data_bedroom_count |
+  association    | storeys, first storey_type  | storeys_0_storey_type      |"
+  (reduce
+    (fn [item attr]
+      (let [t (attribute-type attr)
+            imploded-attribute (case t
+              :attribute               (extract-attribute attr input)
+              :nested-item             (extract-nested-item attr input)
+              :associated-items        (extract-associated-items attr input))]
+        (conj item imploded-attribute)))
+    {}
+    schema))
+
 (defn index-post! [store ctx]
   (db/with-session [session (:hecuba-session store)]
-    (let [request       (-> ctx :request)
-          entity        (-> request decode-body)
-          project_id    (-> entity :project_id)
-          property_code (-> entity :property_code)
-          username      (sec/session-username (-> ctx :request :session))
+    (let [request       (:request ctx)
+          decoded-body  (decode-body request)
+          entity        (if (= "text/csv" (:content-type request))
+                          (let [body-map (into {} decoded-body)]
+                            (parse-by-schema body-map entity-schema))
+                          decoded-body)
+          project_id    (:project_id entity)
+          property_code (:property_code entity)
+          username      (sec/session-username (:session request))
           user_id       (:id (users/get-by-username session username))]
       (when (and project_id property_code)
         (when-not (empty? (-> (db/execute session (hayt/select :projects (hayt/where [[= :id project_id]]))) first))
@@ -100,13 +318,20 @@

 (defn resource-handle-ok [store ctx]
   (db/with-session [session (:hecuba-session store)]
-    (let [request      (:request ctx)
+    (let [{item ::item
+          {mime :media-type} :representation} ctx
+          request      (:request ctx)
           route-params (:route-params request)
           ids          (map :id (db/execute session (hayt/select :devices (hayt/where [[= :entity_id (:entity_id route-params)]]))))
-          item         (::item ctx)]
-      (util/render-item request (-> item
-                                    (assoc :device_ids ids)
-                                    (dissoc :user_id :devices))))))
+          clean-item   (-> item
+                           (assoc :device_ids ids)
+                           (dissoc :user_id :devices))
+          formatted-item (if (= "text/csv" mime)
+                           (let [exploded-item (explode-and-sort-by-schema clean-item entity-schema)]
+                             exploded-item)
+                           clean-item)]
+      (println "ENTITY: " formatted-item)
+      (util/render-item request formatted-item))))

 (defn resource-put! [store ctx]
   (db/with-session [session (:hecuba-session store)]
@@ -139,7 +364,8 @@

 (defresource resource [store]
   :allowed-methods #{:get :delete :put}
-  :available-media-types #{"application/json" "application/edn"}
+  :available-media-types #{"text/csv" "application/json" "application/edn"}
+  :known-content-type? #{"text/csv" "application/json"}
   :authorized? (authorized? store)
   :allowed? (resource-allowed? store)
   :exists? (partial resource-exists? store)


Add displayName and exampleArg properties to quescent wrappers.

--- src/quiescent.cljs
+++ src/quiescent.cljs
@@ -48,9 +48,14 @@
                  (q/set-prop! -componentDidUpdate (:componentDidUpdate m))
                  (:componentWillUnmount m)
                  (q/set-prop! -componentWillUnmount (:componentWillUnmount m)))
-        react-component (.createClass js/React react-map)]
-    (fn [value & static-args]
-      (react-component #js {:value value :statics static-args}))))
+        react-component (.createClass js/React react-map)
+        q-wrapper (fn [value & static-args]
+                    (react-component #js {:value value :statics static-args}))]
+    (when-let [displayName (.-displayName react-map)]
+      (set! (.-displayName q-wrapper) displayName))
+    (when-let [example (:exampleValue m)]
+      (set! (.-exampleArg q-wrapper) example))
+    q-wrapper))

 (def WrapperComponent
   "Wrapper component used to mix-in lifecycle access"


Added more lifecycle wrappers...

Added more lifecycle wrappers...

The `componentWillMount` and `componentWillUpdate` are helpful if you
need to setup/cleanup event handlers outside of React. An example would
be a component that listens for history events to do some routing. Or a
component that listens for key events on the document or window object
to hide or show a modal dialog.

--- src/quiescent.cljs
+++ src/quiescent.cljs
@@ -73,7 +73,19 @@
             (this-as this
               (when-let [f (aget (.-props this) "onMount")]
                 (binding [*component* this]
-                  (f node)))))}))
+                  (f node)))))
+          :componentWillMount
+          (fn []
+            (this-as this
+              (when-let [f (aget (.-props this) "onWillMount")]
+                (binding [*component* this]
+                  (f)))))
+          :componentWillUnmount
+          (fn []
+            (this-as this
+              (when-let [f (aget (.-props this) "onWillUnmount")]
+                (binding [*component* this]
+                  (f)))))}))

 (defn on-update
   "Wrap a component, specifying a function to be called on the
@@ -103,6 +115,24 @@
                          :onUpdate f
                          :onMount f}))

+(defn on-will-mount
+  "Wrap a component, specifying a function to be called on the
+  componentWillMount lifecycle event.
+
+  The function will be called with no arguments."
+  [child f]
+  (WrapperComponent #js {:wrappee child
+                         :onWillMount f}))
+
+(defn on-will-unmount
+  "Wrap a component, specifying a function to be called on the
+  componentWillUnmount lifecycle event.
+
+  The function will be called with no arguments."
+  [child f]
+  (WrapperComponent #js {:wrappee child
+                         :onWillUnmount f}))
+
 (defn render
   "Given a ReactJS component, immediately render it, rooted to the
   specified DOM node."


Require clojure.string instead of using it directly

--- src/com/wsscode/pathom/profile.cljc
+++ src/com/wsscode/pathom/profile.cljc
@@ -1,5 +1,6 @@
 (ns com.wsscode.pathom.profile
   (:require
+    [clojure.string :as str]
     [clojure.core.async :refer [<! go chan put!]]
     [#?(:clj  com.wsscode.common.async-clj
         :cljs com.wsscode.common.async-cljs) :refer [let-chan]]
@@ -56,7 +57,7 @@

 (defn node-name [x]
   (cond
-    (vector? x) (clojure.string/join "_" (map node-name x))
+    (vector? x) (str/join "_" (map node-name x))
     :else (str x)))

 (defn node-value [x]


Only convert worker output between JS and CLJS if it's not JS

--- src/main/audio_utils/worker.cljs
+++ src/main/audio_utils/worker.cljs
@@ -80,16 +80,23 @@
     (connect [this destination])
     (disconnect [this])
     (process-audio [this data]
-      (.postMessage js/self (doto #js []
-                              (aset "name" "main-process-audio")
-                              (aset "data" data))))))
+      (let [convert? (not (array? data))]
+        (.postMessage js/self (doto #js []
+                                (aset "name" "main-process-audio")
+                                (aset "converted?" convert?)
+                                (aset "data" (cond-> data
+                                               convert?
+                                               clj->js))))))))

 (defn main-exit-node
   [worker data-fn]
   (set! (.-onmessage worker)
         (fn [msg]
-          (let [name    (aget (.-data msg) "name")
-                data    (aget (.-data msg) "data")]
+          (let [name       (aget (.-data msg) "name")
+                converted? (aget (.-data msg) "converted?")
+                data       (aget (.-data msg) "data")]
             (when (= name "main-process-audio")
               (when data-fn
-                (data-fn data)))))))
+                (data-fn (cond-> data
+                           converted?
+                           js->clj))))))))


Remove irrelevant requires

Remove irrelevant requires

--- src/main/cljs/lean_map/core.cljs
+++ src/main/cljs/lean_map/core.cljs
@@ -1,6 +1,4 @@
 (ns cljs.lean-map.core
-  (:require [collection-check.core :as cc]
-            [clojure.test.check.generators :as gen])
   (:refer-clojure :exclude [Box ->Box BitmapIndexedNode ->BitmapIndexedNode
                             HashCollisionNode ->HashCollisionNode
                             PersistentHashMap ->PersistentHashMap


Add missing `did-update` to rum specs (#216)

--- src/rum/specs.cljc
+++ src/rum/specs.cljc
@@ -3,5 +3,5 @@
 (def mixins
   #{:init :will-mount :before-render :wrap-render :did-mount
     :after-render :did-remount :should-update :will-update
-    :did-catch :will-unmount :child-context :class-properties
-    :static-properties})
+    :did-update :did-catch :will-unmount :child-context
+    :class-properties :static-properties})


Keyword coersion

Keyword coersion

--- src/inkspot/color.clj
+++ src/inkspot/color.clj
@@ -1,6 +1,7 @@
 (ns inkspot.color
-  (:require [clojure.string :as string])
-  (:use [inkspot.common :only [parse-int parse-double]])
+  (:require [clojure.string :as string]
+            [inkspot.common :refer [parse-int parse-double]]
+            [inkspot.color-chart.lindsay :as lindsay])
   ^:clj
   (:import [java.awt Color]))

@@ -73,6 +74,10 @@
     #"rgb\((.*),(.*),(.*)\)" :>> color-vec
     #"rgba\((.*),(.*),(.*),(.*)\)" :>> color-vec))

+(defn keyword->color [k]
+  (when-let [v (lindsay/swatch k)]
+    (coerce v)))
+
 (extend-type ^{:cljs cljs.core.PersistentVector} clojure.lang.PersistentVector
   IColor
   (red    [[r _ _ _]] r)
@@ -87,7 +92,7 @@
   (green  [n] (green (int->color n)))
   (blue   [n] (blue (int->color n)))
   (alpha  [n] (alpha (int->color n)))
-  (coerce [n] (to-color n)))
+  (coerce [n] (int->color n)))

 (extend-type java.lang.String
   IColor
@@ -95,7 +100,15 @@
   (green  [s] (green (string->color s)))
   (blue   [s] (blue (string->color s)))
   (alpha  [s] (alpha (string->color s)))
-  (coerce [s] (to-color s)))
+  (coerce [s] (string->color s)))
+
+(extend-type clojure.lang.Keyword
+  IColor
+  (red    [s] (red (keyword->color s)))
+  (green  [s] (green (keyword->color s)))
+  (blue   [s] (blue (keyword->color s)))
+  (alpha  [s] (alpha (keyword->color s)))
+  (coerce [s] (keyword->color s)))

 ^:clj
 (extend-type java.awt.Color
@@ -136,4 +149,4 @@
           sum (->>
                 (map scale colors proportions)
                 (reduce (partial map +)))]
-      (coerce (mapv #(int (/ % cnt)) sum)))))
+      (coerce (mapv #(int (/ % cnt)) sum)))))


Remove reduntant logging.

Remove reduntant logging.

--- src/clj/quil_site/controllers/sketches.clj
+++ src/clj/quil_site/controllers/sketches.clj
@@ -69,7 +69,6 @@
                  (map second)
                  first))]
     (let [size (-> sketch-source read-all find-defsketch get-size)]
-      (clojure.pprint/pprint (find-defsketch (read-all sketch-source)))
       (if (and (or (list? size) (vector? size))
                (every? number? size))
         (vec (take 2 size))


force heroku rebuild

force heroku rebuild

--- src/cljs/fractalify/fractals/handlers.cljs
+++ src/cljs/fractalify/fractals/handlers.cljs
@@ -213,3 +213,4 @@
       (-> db
           (u/remove-first-in [:fractals :fractals-user :items] id-entry)
           (update-in [:fractals :fractals-user :total-items] dec)))))
+


add-text! and change-text!

add-text! and change-text!

--- src/cljs/infinitelives/pixi/pixelfont.cljs
+++ src/cljs/infinitelives/pixi/pixelfont.cljs
@@ -65,6 +65,14 @@
             (recur l (+ xp w 1.0 koff) yp c (conj sprite-set sprite))
             (conj sprite-set sprite)))))))

+(defn add-text! [batch font-key text]
+  (doseq [spr (make-char-sprite-set font-key text)]
+    (.addChild batch spr)))
+
+(defn change-text! [batch font-key text]
+  (clear-text! batch)
+  (add-text! batch font-key text))
+
 (defn make-text [font-key text & {:keys [tint scale anchor rotation
                                          x y visible
                                          xhandle yhandle]


routing

routing

--- src/cljs/tumblrsearch/components/main.cljs
+++ src/cljs/tumblrsearch/components/main.cljs
@@ -22,43 +22,42 @@
                               :left     (str (:x item) "px")}}
              (dom/img #js {:src (:url (:photo item))})))))

-(defn- build-offset-grid [current-items window-width]
-  (let [col-n (quot window-width *IMAGE-SIZE*)
-        left-offset (-> (.. js/window -innerWidth)
-                        (mod *IMAGE-SIZE*) (/ 2) (int))]
-    (loop [items   current-items
-           coll    []
-           idx     0
-           offsets (zipmap (range col-n) (repeat 0))]
-      (if (empty? items) coll
-        (let [item  (first items)
-              title (s/replace (:slug item)  #"-"  " ")
-              photo (-> item :photos first :alt_sizes second)]
-          (if (or (nil? (:height photo)) (nil? (:width photo)))
-            ; nil size found - drop the image
-            (recur (rest items) coll idx offsets)
-            ; image ok - place image in grid
-            (let [offset-n    (mod idx col-n)
-                  offset      (apply min-key second offsets)
-                  offset-x    (+ left-offset (* *IMAGE-SIZE* (first offset)))
-                  offset-y    (second offset)
-                  new-height  (int (* (:height photo) (/ *IMAGE-SIZE* (:width photo))))
-                  new-offsets (update-in offsets [(first offset)] + new-height)
-                  new-item {:index idx
-                            :title title
-                            :photo photo
-                            :post_url (:post_url item)
-                            :x offset-x
-                            :y offset-y
-                            }]
-              (recur
-                (rest items)
-                (conj coll new-item)
-                (inc idx)
-                new-offsets))))))))
+(defn- build-offset-grid [current-items col-n]
+  (loop [items   current-items
+         coll    []
+         idx     0
+         offsets (zipmap (range col-n) (repeat 0))]
+    (if (empty? items) coll
+      (let [item  (first items)
+            title (s/replace (:slug item)  #"-"  " ")
+            photo (-> item :photos first :alt_sizes second)]
+        (if (or (nil? (:height photo)) (nil? (:width photo)))
+          ; nil size found - drop the image
+          (recur (rest items) coll idx offsets)
+          ; image ok - place image in grid
+          (let [offset-n    (mod idx col-n)
+                offset      (apply min-key second offsets)
+                offset-x    (* *IMAGE-SIZE* (first offset))
+                offset-y    (second offset)
+                new-height  (int (* (:height photo) (/ *IMAGE-SIZE* (:width photo))))
+                new-offsets (update-in offsets [(first offset)] + new-height)
+                new-item {:index idx
+                          :title title
+                          :photo photo
+                          :post_url (:post_url item)
+                          :x offset-x
+                          :y offset-y
+                          }]
+            (recur
+              (rest items)
+              (conj coll new-item)
+              (inc idx)
+              new-offsets)))))))

 (defcomponent component [{:keys [current-items window-width]} owner]
   (render [_]
-    (dom/div {:className "images"}
-      (om/build-all item-view
-        (build-offset-grid current-items window-width)))))
+    (let [col-n (quot window-width *IMAGE-SIZE*)]
+     (dom/div {:className "images"
+               :style {:width (str (* col-n *IMAGE-SIZE*) "px")}}
+        (om/build-all item-view
+          (build-offset-grid current-items col-n))))))


Move python/jdk into os setup

Move python/jdk into os setup

--- src/jepsen/voltdb.clj
+++ src/jepsen/voltdb.clj
@@ -8,6 +8,7 @@
                     [independent  :as independent]
                     [nemesis      :as nemesis]
                     [net          :as net]
+                    [os           :as os]
                     [tests        :as tests]
                     [util         :as util :refer [meh timeout]]]
             [jepsen.os            :as os]
@@ -32,15 +33,25 @@
 (def username "voltdb")
 (def base-dir "/opt/voltdb")

+(defn os
+  "Given OS, plus python & jdk8"
+  [os]
+  (reify os/OS
+    (setup! [_ test node]
+      (os/setup! os test node)
+      (debian/install ["python2.7"])
+      (c/exec :update-alternatives :--install "/usr/bin/python" "python"
+              "/usr/bin/python2.7" 1)
+      (debian/install-jdk8!)
+      (info "JDK8 installed"))
+
+    (teardown! [_ test node]
+      (os/teardown! os test node))))
+
 (defn install!
   "Install the given tarball URL"
   [node url force?]
   (c/su
-    (debian/install ["python2.7"])
-    (c/exec :update-alternatives :--install "/usr/bin/python" "python"
-            "/usr/bin/python2.7" 1)
-    (debian/install-jdk8!)
-    (info "JDK8 installed")
     (cu/install-tarball! node url base-dir force?)
     (c/exec :mkdir (str base-dir "/log"))
     (cu/ensure-user! username)
@@ -578,6 +589,6 @@
         :nodes                        Nodes to run against"
   [opts]
   (-> tests/noop-test
-      (assoc :os (if (:skip-os? opts) os/noop debian/os))
+      (assoc :os (if (:skip-os? opts) os/noop (os debian/os)))
       (assoc :db (db (:tarball opts) (:force-download? opts)))
       (merge opts)))


Enterprise has no footer.

Enterprise has no footer.

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -33,6 +33,7 @@
             [frontend.components.landing :as landing]
             [frontend.components.org-settings :as org-settings]
             [frontend.components.common :as common]
+            [frontend.config :as config]
             [frontend.instrumentation :as instrumentation]
             [frontend.state :as state]
             [frontend.utils :as utils :include-macros true]
@@ -131,8 +132,9 @@
                (om/build header/header app-without-container-data)
                [:div.main-body
                 (om/build dom-com app)]
-               [:footer.main-foot
-                (footer/footer)]
+               (when-not (config/enterprise?)
+                 [:footer.main-foot
+                  (footer/footer)])
                (when-not logged-in?
                  (om/build shared/sticky-help-link app))]])))))))


forgot still need title on logout btn even w/o tip

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -74,7 +74,8 @@
                                                                    (.-href)
                                                                    (url/url)
                                                                    :path)}]
-            [:a.action-logout {:on-click #(.submit (om/get-node owner "logout-form"))}
+            [:a.action-logout {:on-click #(.submit (om/get-node owner "logout-form"))
+                               :title "Logout"}
              (common/icon :logout)]]
            [:a.action-login {:href (auth/auth-url)
                              :data-right (when-not login-button-learned? "Sign Up")


Performance improvements

Performance improvements

No need to assoc into a map here. Slows things down for big batches,
needs to calculate hash then has to recalculate it when getting it.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -55,7 +55,7 @@
   (merge
    event
    (when (and children (not (:onyx/side-effects-only? (:onyx.core/task-map event))))
-     (doseq [raw-segment (keys children)]
+     (doseq [[raw-segment tagged] children]
        (when (:ack-val raw-segment)
          (let [link (operation/peer-link event (:acker-id raw-segment) :acker-peer-site)]
            (extensions/internal-ack-message
@@ -64,7 +64,7 @@
             link
             (:id raw-segment)
             (:completion-id raw-segment)
-            (fuse-ack-vals (:onyx.core/task-map event) (:ack-val raw-segment) (get children raw-segment)))))))))
+            (fuse-ack-vals (:onyx.core/task-map event) (:ack-val raw-segment) tagged))))))))

 (defn join-output-paths [all to-add downstream]
   (cond (= to-add :all) (into #{} downstream)
@@ -164,7 +164,9 @@
   (let [segments (p-ext/apply-fn event input)]
     (if (sequential? segments) segments (vector segments))))

+
 (defn apply-fn-single [{:keys [onyx.core/batch onyx.core/decompressed] :as event}]
+  ; PERF: Tight inner loop where a lot of time is spent
   (merge
    event
    (reduce
@@ -173,10 +175,10 @@
             results (map (partial build-next-segment thawed) segments)
             tagged (acker/prefuse-vals (map :ack-val results))]
         (-> rets
-            (update-in [:onyx.core/results] concat results)
-            (assoc-in [:onyx.core/children thawed] tagged))))
+            (update-in [:onyx.core/results] into results)
+            (update-in [:onyx.core/children] conj [thawed tagged]))))
     {:onyx.core/results []
-     :onyx.core/children {}}
+     :onyx.core/children []}
     decompressed)))

 (defn apply-fn-batch [{:keys [onyx.core/batch onyx.core/decompressed] :as event}]


Add worst case equals comparison to benchmark

--- src/bench/cljs/lean_map/bench.cljs
+++ src/bench/cljs/lean_map/bench.cljs
@@ -87,6 +87,14 @@
             neq-m (assoc m (get test-keys step) -100)]
         (simple-benchmark [] (= m neq-m) sample)))))

+(defmethod map-bench :worst-equals [_ _ {:keys [small-map medium-map large-map]}]
+  (println "Worst Case Equals (same map different location in memory)")
+  (let [maps [small-map medium-map large-map]
+        samples [small-map-sample medium-map-sample large-map-sample]]
+    (doseq [[m sample] (partition 2 (interleave maps samples))]
+      (let [cm (into (empty m) m)]
+        (simple-benchmark [] (= m cm) sample)))))
+
 (defmethod map-bench :sequence [_ _ {:keys [small-map medium-map large-map]}]
   (println "sequence")
   (let [maps [small-map medium-map large-map]
@@ -121,7 +129,7 @@
                      (range large-map-size)))

 (println "Current Maps")
-(let [benchmarks  [:assoc :dissoc :dissoc-fail :hash :equals :equals-fail :sequence :reduce]
+(let [benchmarks  [:assoc :dissoc :dissoc-fail :hash :equals :equals-fail :worst-equals :sequence :reduce]
       empty-map cem
       data {:small-map (sized-map empty-map small-map-size)
             :medium-map (sized-map empty-map medium-map-size)
@@ -129,7 +137,7 @@
   (run-benchmarks benchmarks empty-map data))

 (println "Lean Maps")
-(let [benchmarks  [:assoc :dissoc :dissoc-fail :hash :equals :equals-fail :sequence :reduce]
+(let [benchmarks  [:assoc :dissoc :dissoc-fail :hash :equals :equals-fail :worst-equals :sequence :reduce]
       empty-map lem
       data {:small-map (sized-map empty-map small-map-size)
             :medium-map (sized-map empty-map medium-map-size)


demo github header template

demo github header template


Minor: remove unnecessary reference to global app state

--- src/cljs/mandelbrot_cljs/core.cljs
+++ src/cljs/mandelbrot_cljs/core.cljs
@@ -55,7 +55,7 @@
         startx  (aget (:mousedown-event @app-state) "pageX")
         starty  (aget (:mousedown-event @app-state) "pageY")
         finishx (aget e "pageX")
-        finishy (aget e "pageY")]
+        finishy {aget e "pageY"}]

     (if (or (< (modulus (- startx finishx)) 10)
             (< (modulus (- starty finishy)) 10)) ; Does this look like a click?
@@ -157,7 +157,7 @@
                                    (assoc :rendered-rectangle rendered-rectangle))))

-            (put! messages [:add-to-rendering-data-history (:rendering-data @app-state)])
+            (put! messages [:add-to-rendering-data-history (:rendering-data body)])
             (put! messages [:update-stats stats])))

         :add-to-rendering-data-history (when-not (= body (last @rendering-data-history))


add endorsement icon

add endorsement icon

--- src/cljs/salava/user/ui/modal.cljs
+++ src/cljs/salava/user/ui/modal.cljs
@@ -37,7 +37,7 @@
      (t :user/Publishandshare)]]])

 (defn badge-grid-element [element-data]
-  (let [{:keys [id image_file name description issuer_content_name issuer_content_url]} element-data]
+  (let [{:keys [id image_file name description issuer_content_name issuer_content_url user_endorsements_count]} element-data]
     ;[:div {:class "col-xs-12 col-sm-6 col-md-4" :key id}
      [:div {:class "media grid-container"}
       [:div.media-content
@@ -53,7 +53,9 @@
                            :on-click #(set-new-view [:badge :info] {:badge-id id})}
           name]]
         [:div.media-issuer
-         [:p issuer_content_name]]]]]
+         [:p issuer_content_name]]
+        (when (pos? user_endorsements_count)
+        [:div.text-center [:i.fa.fa-handshake-o]])]]]
               ;]
               ))


(PDB-2634) Add jsonb path helper funcs

(PDB-2634) Add jsonb path helper funcs

cherry picked from 7c8e952b6dcfd8f4a76666293342a31e48f2524c

--- src/puppetlabs/puppetdb/jdbc.clj
+++ src/puppetlabs/puppetdb/jdbc.clj
@@ -354,6 +354,37 @@
    :post [(string? %)]}
   (str (name field)
        (when (= order :descending) " DESC")))
+
+(defn escape-single-quotes
+  "Quote a string for SQL single quotes"
+  [s]
+  (str/replace s "'" "''"))
+
+(defn single-quote
+  "Given a string quote with single quotes and do proper SQL string escaping."
+  [s]
+  (str "'" (escape-single-quotes s) "'"))
+
+(defn escape-double-quotes
+  "Quote a string for SQL double quotes"
+  [s]
+  (str/replace s "\"" "\"\""))
+
+(defn double-quote
+  "Given a string quote with double quotes and do proper SQL string escaping."
+  [s]
+  (str "\"" (escape-double-quotes s) "\""))
+
+(defn create-json-path-extraction
+  "Given a base json field and a path of keys to traverse, construct the proper
+  SQL query of the form base->'key'->'key2'..."
+  [field path]
+   (str field
+        (when (seq path)
+          (->> (map single-quote path)
+               (str/join "->")
+               ;; prefix for the first arrow in field->'key1'...
+               (str "->")))))

 (pls/defn-validated paged-sql :- String
   "Given a sql string and a map of paging options, return a modified SQL string


Rename tabset menu items trigger

Rename tabset menu items trigger

--- src/lt/objs/tabs.cljs
+++ src/lt/objs/tabs.cljs
@@ -502,11 +502,11 @@
 (behavior ::tabset-menu
           :triggers #{:menu!}
           :reaction (fn [this ev]
-                      (-> (menu/menu (sort-by :order (object/raise-reduce this :tabset-menu-items [])))
+                      (-> (menu/menu (sort-by :order (object/raise-reduce this :menu+ [])))
                           (menu/show-menu (.-clientX ev) (.-clientY ev)))))

 (behavior ::tabset-menu-items
-          :triggers #{:tabset-menu-items}
+          :triggers #{:menu+}
           :reaction (fn [this items]
                       (conj items
                             {:label "New tabset"


Function callable? added into schedule_test.clj

--- test/clj_mrazik/schedule_test.clj
+++ test/clj_mrazik/schedule_test.clj
@@ -14,3 +14,12 @@
   (:require [clojure.test :refer :all]
             [clj-mrazik.schedule :refer :all]))

+;
+; Common functions used by tests.
+;
+
+(defn callable?
+    "Test if given function-name is bound to the real function."
+    [function-name]
+    (clojure.test/function? function-name))
+


s/'()/[]/

s/'()/[]/

--- src/babel/italiano/morphology.cljc
+++ src/babel/italiano/morphology.cljc
@@ -108,8 +108,8 @@

 ;; TODO: this is an overly huge method that needs to be rewritten to be easier to understand and maintain.
 (defn get-string-1 [word]
-  (let [person (get-in word '(:agr :person))
-        number (get-in word '(:agr :number))]
+  (let [person (get-in word [:agr :person])
+        number (get-in word [:agr :number])]
     (cond
       (and (string? (get-in word [:a]))
            (string? (get-in word [:b])))
@@ -211,14 +211,14 @@
        (= (get-in word '(:agr :number)) :plur)
        (= (get-in word '(:cat)) :adjective)
        (re-find #"o$" (get-in word [:italiano])))
-      (string/replace (get-in word '(:italiano))
+      (string/replace (get-in word [:italiano])
                       #"[o]$" "e") ;; nero => nere
       (and
        (= (get-in word '(:agr :gender)) :fem)
        (= (get-in word '(:agr :number)) :plur)
        (= (get-in word '(:cat)) :adjective)
        (re-find #"e$" (get-in word [:italiano])))
-      (string/replace (get-in word '(:italiano))
+      (string/replace (get-in word [:italiano])
                       #"[e]$" "i") ;; difficile => difficili

       ;; handle lexical exceptions (plural nouns):
@@ -235,8 +235,8 @@
        (= (get-in word '(:agr :number)) :plur)
        (= :noun (get-in word '(:cat)))
        (not (= true (get-in word '(:pronoun))))
-       (get-in word '(:italiano)))
-      (string/replace (get-in word '(:italiano))
+       (get-in word [:italiano]))
+      (string/replace (get-in word [:italiano])
                       #"[eo]$" "i") ;; dottore => dottori; medico => medici

       ;; regular feminine nouns ending in 'e':
@@ -245,9 +245,9 @@
        (= (get-in word '(:agr :gender)) :fem)
        (= (get-in word '(:agr :number)) :plur)
        (= (get-in word '(:cat)) :noun)
-       (get-in word '(:italiano))
+       (get-in word [:italiano])
        (re-find #"e$" (get-in word [:italiano])))
-      (string/replace (get-in word '(:italiano))
+      (string/replace (get-in word [:italiano])
                       #"[e]$" "i") ;; madre => madri

       ;; regular feminine nouns not ending in 'e'
@@ -256,8 +256,8 @@
        (= (get-in word '(:agr :gender)) :fem)
        (= (get-in word '(:agr :number)) :plur)
        (= (get-in word '(:cat)) :noun)
-       (get-in word '(:italiano)))
-      (string/replace (get-in word '(:italiano))
+       (get-in word [:italiano]))
+      (string/replace (get-in word [:italiano])
                       #"[aà]$" "e") ;; donna => donne

       ;; TODO: move this down to other adjectives.
@@ -268,7 +268,7 @@
        (= (get-in word '(:agr :gender)) :fem)
        (= (get-in word '(:agr :number)) :plur)
        (= (get-in word '(:cat)) :adjective))
-      (string/replace (get-in word '(:italiano))
+      (string/replace (get-in word [:italiano])
                       #"[eo]$" "e") ;; nero => nere

       ;; TODO: move this down to other adjectives.
@@ -291,12 +291,12 @@
        (= (get-in word '(:agr :gender)) :fem)
        (= (get-in word '(:agr :number)) :sing)
        (= (get-in word '(:cat)) :adjective))
-      (string/replace (get-in word '(:italiano))
+      (string/replace (get-in word [:italiano])
                       #"[eo]$" "a") ;; nero => nera

       (and (= :infinitive (get-in word '(:infl)))
-           (string? (get-in word '(:italiano))))
-      (get-in word '(:italiano))
+           (string? (get-in word [:italiano])))
+      (get-in word [:italiano])

       (and
        (get-in word [:a])
@@ -306,16 +306,16 @@
        (trim (get-string-1 (get-in word [:b]))))

      (and
-      (string? (get-in word '(:italiano)))
+      (string? (get-in word [:italiano]))
       (= :top (get-in word '(:agr :sing) :top)))
-     (str (get-in word '(:italiano)))
+     (str (get-in word [:italiano]))

      ;; TODO: possibly remove this: not sure it's doing anything.
      (= true (get-in word [:exception]))
      (get-in word [:italiano])

      (= (get-in word '(:infl)) :top)
-     (str (get-in word '(:italiano)))
+     (str (get-in word [:italiano]))

      (and
       (get-in word [:a])
@@ -346,13 +346,13 @@
       (= (get-in word '(:agr :gender)) :fem)
       (= (get-in word '(:agr :number)) :sing)
       (= (get-in word '(:cat)) :noun))
-     (get-in word '(:italiano))
+     (get-in word [:italiano])

      (and
       (= (get-in word '(:agr :gender)) :masc)
       (= (get-in word '(:agr :number)) :sing)
       (= (get-in word '(:cat) :adjective)))
-     (get-in word '(:italiano)) ;; nero
+     (get-in word [:italiano]) ;; nero

      (and
       (= (get-in word '(:agr :gender)) :masc)
@@ -370,8 +370,8 @@
       (string? (get-in word '(:fem :plur))))
      (get-in word '(:fem :plur))

-     (string? (get-in word '(:italiano)))
-     (get-in word '(:italiano))
+     (string? (get-in word [:italiano]))
+     (get-in word [:italiano])

      (or
       (not (= :none (get-in word [:a] :none)))
@@ -408,8 +408,8 @@
         info-a (log/debug (str "get-string: a: " a))
         info-b (if b (log/debug (str "get-string: b: " b)))

-        it-b (log/debug "it-a is string? " (string? (get-in a '(:italiano))))
-        it-b (log/debug "it-b is string? " (string? (get-in b '(:italiano))))
+        it-b (log/debug "it-a is string? " (string? (get-in a [:italiano])))
+        it-b (log/debug "it-b is string? " (string? (get-in b [:italiano])))

         cat-a (log/debug (str "cat a:" (get-in a '(:cat))))
         cat-b (log/debug (str "cat b:" (get-in b '(:cat))))
@@ -419,15 +419,15 @@
       ;; TODO: replace with articles.edn or similar rather than
       ;; a big clojure (cond).
       (and (= a "gli")
-           (string? (get-in b '(:italiano)))
-           (not (or (re-find #"^[aeiou]" (get-in b '(:italiano)))
-                    (re-find #"^s[t]" (get-in b '(:italiano))))))
+           (string? (get-in b [:italiano]))
+           (not (or (re-find #"^[aeiou]" (get-in b [:italiano]))
+                    (re-find #"^s[t]" (get-in b [:italiano])))))
       (trim (str "i " b))

       (and (= a "i")
-           (string? (get-in b '(:italiano)))
-           (or (re-find #"^[aeiou]" (get-in b '(:italiano)))
-               (re-find #"^s[t]" (get-in b '(:italiano)))))
+           (string? (get-in b [:italiano]))
+           (or (re-find #"^[aeiou]" (get-in b [:italiano]))
+               (re-find #"^s[t]" (get-in b [:italiano]))))
       (trim (str "gli " b))

       (and (= a "il")
@@ -480,13 +480,13 @@
            (string? b))
       (str "dei " b)

-      (and (= (get-in a '(:italiano)) "di i")
+      (and (= (get-in a [:italiano]) "di i")
            (string? b))
       (str "dei " b)

-      (and (= (get-in a '(:italiano)) "di i")
-           (string? (get-in b '(:italiano))))
-      (str "dei " (get-string-1 (get-in b '(:italiano))))
+      (and (= (get-in a [:italiano]) "di i")
+           (string? (get-in b [:italiano])))
+      (str "dei " (get-string-1 (get-in b [:italiano])))

       (and (= a "di il")
            (string? b))
@@ -516,8 +516,8 @@
       (str "gli " b)

       (and (= a "i")
-           (string? (get-in b '(:italiano)))
-           (re-find #"^[aeiou]" (get-in b '(:italiano))))
+           (string? (get-in b [:italiano]))
+           (re-find #"^[aeiou]" (get-in b [:italiano])))
       (str "gli " b)

       (and (= a "i")
@@ -617,12 +617,12 @@
       (and (string? a) (string? b))
       (trim (str a " " b))

-      (and (string? a) (string? (get-in b '(:italiano))))
-      (trim (str a " " (get-in b '(:italiano))))
-
-      (and (string? (get-in a '(:italiano)))
+      (and (string? a) (string? (get-in b [:italiano])))
+      (trim (str a " " (get-in b [:italiano])))
+
+      (and (string? (get-in a [:italiano]))
            (string? b))
-      (trim (str (get-in a '(:italiano)) " " b))
+      (trim (str (get-in a [:italiano]) " " b))

       (and (string? a)
            (map? b))


more clear log/warns

more clear log/warns

--- src/babel/italiano/morphology.cljc
+++ src/babel/italiano/morphology.cljc
@@ -1419,11 +1419,19 @@
                                                                     (cond
                                                                       (= a :fail)
                                                                       (do
-                                                                        (log/warn (str ":fail in generate exception: exception rule:" (:label path-and-merge-fn) "; lexeme:" (strip-refs lexeme)))
+                                                                        (log/warn (str ":fail in exception rule:"
+                                                                                (:label path-and-merge-fn)
+                                                                                "; lexeme:"
+                                                                                (or (strip-refs (get-in lexeme [:italiano :italiano]))
+                                                                                (strip-refs (get-in lexeme [:italiano])))))
                                                                         :fail)
                                                                       (= b :fail)
                                                                       (do
-                                                                        (log/warn (str ":fail in generate exception: exception rule:" (:label path-and-merge-fn) "; lexeme:" (strip-refs lexeme)))
+                                                                        (log/warn (str ":fail in exception rule:"
+                                                                                (:label path-and-merge-fn)
+                                                                                "; lexeme:"
+                                                                                (or (strip-refs (get-in lexeme [:italiano :italiano]))
+                                                                                (strip-refs (get-in lexeme [:italiano])))))
                                                                         :fail)
                                                                       true
                                                                       (unify a b)))


Change lexicoders into deftypes.

Change lexicoders into deftypes.

--- src/merkle_db/key.clj
+++ src/merkle_db/key.clj
@@ -280,8 +280,27 @@

 ;; ## Bytes Lexicoder

-(defrecord BytesLexicoder
-  []
+(deftype BytesLexicoder [])
+
+
+(def bytes-lexicoder
+  "Lexicoder for passing through raw byte arrays."
+  (->BytesLexicoder))
+
+
+(ns-unmap *ns* '->BytesLexicoder)
+
+
+(defmethod lexicoder :bytes
+  [config]
+  (when (seq (config-params config))
+    (throw (ex-info
+             (str "Bytes lexicoder config takes no parameters: " (pr-str config))
+             {:config config})))
+  bytes-lexicoder)
+
+
+(extend-type BytesLexicoder

   Lexicoder

@@ -308,60 +327,15 @@
         data'))))

-(alter-meta! #'->BytesLexicoder assoc :private true)
-(alter-meta! #'map->BytesLexicoder assoc :private true)
-
-
-(def bytes-lexicoder
-  "Lexicoder for passing through raw byte arrays."
-  (->BytesLexicoder))
-
-
-(defmethod lexicoder :bytes
-  [config]
-  (when (seq (config-params config))
-    (throw (ex-info
-             (str "Bytes lexicoder config takes no parameters: " (pr-str config))
-             {:config config})))
-  bytes-lexicoder)
-
-

 ;; ## String Lexicoder
+
+(deftype StringLexicoder [^Charset charset])
+

 (def ^:private default-string-charset
   "Default character set to lexicode strings with."
   StandardCharsets/UTF_8)
-
-
-(defrecord StringLexicoder
-  [^Charset charset]
-
-  Lexicoder
-
-  (lexicoder-config
-    [_]
-    (if (= charset default-string-charset)
-      :string
-      [:string (str charset)]))
-
-  (encode*
-    [_ value]
-    (when (empty? value)
-      (throw (IllegalArgumentException.
-               "Cannot encode empty strings")))
-    (.getBytes (str value) charset))
-
-  (decode*
-    [_ data offset len]
-    (when (empty? data)
-      (throw (IllegalArgumentException.
-               "Cannot decode empty byte arrays")))
-    (String. ^bytes data (long offset) (long len) charset)))
-
-
-(alter-meta! #'->StringLexicoder assoc :private true)
-(alter-meta! #'map->StringLexicoder assoc :private true)

 (defn string-lexicoder*
@@ -373,6 +347,9 @@
 (def string-lexicoder
   "Lexicoder for UTF-8 character strings."
   (string-lexicoder* default-string-charset))
+
+
+(ns-unmap *ns* '->StringLexicoder)

 (defmethod lexicoder :string
@@ -386,8 +363,53 @@
     string-lexicoder))

+(extend-type StringLexicoder
+
+  Lexicoder
+
+  (lexicoder-config
+    [this]
+    (if (= (.charset this) default-string-charset)
+      :string
+      [:string (str (.charset this))]))
+
+  (encode*
+    [this value]
+    (when (empty? value)
+      (throw (IllegalArgumentException.
+               "Cannot encode empty strings")))
+    (.getBytes (str value) ^Charset (.charset this)))
+
+  (decode*
+    [this data offset len]
+    (when (empty? data)
+      (throw (IllegalArgumentException.
+               "Cannot decode empty byte arrays")))
+    (String. ^bytes data (long offset) (long len) ^Charset (.charset this))))
+
+

 ;; ## Long Lexicoder
+
+(deftype LongLexicoder [])
+
+
+(def long-lexicoder
+  "Lexicoder for long integer values."
+  (->LongLexicoder))
+
+
+(ns-unmap *ns* '->LongLexicoder)
+
+
+(defmethod lexicoder :long
+  [config]
+  (when (config-params config)
+    (throw (ex-info
+             (str "Long lexicoder config takes no parameters: " (pr-str config))
+             {:config config})))
+  long-lexicoder)
+

 (defn- flip-long-sign
   "Flip the sign bit on a long value."
@@ -402,8 +424,7 @@
   (bit-and 0xFF (bit-shift-right l (* i 8))))

-(defrecord LongLexicoder
-  []
+(extend-type LongLexicoder

   Lexicoder

@@ -441,29 +462,30 @@
         (flip-long-sign value)))))

-(alter-meta! #'->LongLexicoder assoc :private true)
-(alter-meta! #'map->LongLexicoder assoc :private true)
-
-
-(def long-lexicoder
-  "Lexicoder for long integer values."
-  (->LongLexicoder))
-
-
-(defmethod lexicoder :long
+
+;; ## Double Lexicoder
+
+(deftype DoubleLexicoder [])
+
+
+(def double-lexicoder
+  "Lexicoder for double-precision floating point values."
+  (->DoubleLexicoder))
+
+
+(ns-unmap *ns* '->DoubleLexicoder)
+
+
+(defmethod lexicoder :double
   [config]
   (when (config-params config)
     (throw (ex-info
-             (str "Long lexicoder config takes no parameters: " (pr-str config))
+             (str "Double lexicoder config takes no parameters: " (pr-str config))
              {:config config})))
-  long-lexicoder)
-
-
-
-;; ## Double Lexicoder
-
-(defrecord DoubleLexicoder
-  []
+  double-lexicoder)
+
+
+(extend-type DoubleLexicoder

   Lexicoder

@@ -490,29 +512,30 @@
           (bit-not (flip-long-sign bits)))))))

-(alter-meta! #'->DoubleLexicoder assoc :private true)
-(alter-meta! #'map->DoubleLexicoder assoc :private true)
-
-
-(def double-lexicoder
-  "Lexicoder for double-precision floating point values."
-  (->DoubleLexicoder))
-
-
-(defmethod lexicoder :double
+
+;; ## Instant Lexicoder
+
+(deftype InstantLexicoder [])
+
+
+(def instant-lexicoder
+  "Lexicoder for instants in time."
+  (->InstantLexicoder))
+
+
+(ns-unmap *ns* '->InstantLexicoder)
+
+
+(defmethod lexicoder :instant
   [config]
   (when (config-params config)
     (throw (ex-info
-             (str "Double lexicoder config takes no parameters: " (pr-str config))
+             (str "Instant lexicoder config takes no parameters: " (pr-str config))
              {:config config})))
-  double-lexicoder)
-
-
-
-;; ## Instant Lexicoder
-
-(defrecord InstantLexicoder
-  []
+  instant-lexicoder)
+
+
+(extend-type InstantLexicoder

   Lexicoder

@@ -533,51 +556,10 @@
     (Instant/ofEpochMilli (decode* long-lexicoder data offset len))))

-(alter-meta! #'->InstantLexicoder assoc :private true)
-(alter-meta! #'map->InstantLexicoder assoc :private true)
-
-
-(def instant-lexicoder
-  "Lexicoder for instants in time."
-  (->InstantLexicoder))
-
-
-(defmethod lexicoder :instant
-  [config]
-  (when (config-params config)
-    (throw (ex-info
-             (str "Instant lexicoder config takes no parameters: " (pr-str config))
-             {:config config})))
-  instant-lexicoder)
-
-

 ;; ## Sequence Lexicoder

-(defrecord SequenceLexicoder
-  [element-coder]
-
-  Lexicoder
-
-  (lexicoder-config
-    [_]
-    [:seq (lexicoder-config element-coder)])
-
-  (encode*
-    [_ value]
-    (->> value
-         (map #(escape-bytes (encode* element-coder %)))
-         (join-bytes)))
-
-  (decode*
-    [_ data offset len]
-    (->> (split-bytes data offset len)
-         (mapv #(let [udata (unescape-bytes %)]
-                  (decode* element-coder udata 0 (alength udata)))))))
-
-
-(alter-meta! #'->SequenceLexicoder assoc :private true)
-(alter-meta! #'map->SequenceLexicoder assoc :private true)
+(deftype SequenceLexicoder [element-coder])

 (defn sequence-lexicoder
@@ -587,6 +569,9 @@
   (->SequenceLexicoder element-coder))

+(ns-unmap *ns* '->SequenceLexicoder)
+
+
 (defmethod lexicoder :seq
   [config]
   (when (not= 1 (count (config-params config)))
@@ -596,40 +581,31 @@
   (sequence-lexicoder (lexicoder (second config))))

+(extend-type SequenceLexicoder
+
+  Lexicoder
+
+  (lexicoder-config
+    [this]
+    [:seq (lexicoder-config (.element-coder this))])
+
+  (encode*
+    [this value]
+    (->> value
+         (map #(escape-bytes (encode* (.element-coder this) %)))
+         (join-bytes)))
+
+  (decode*
+    [this data offset len]
+    (->> (split-bytes data offset len)
+         (mapv #(let [udata (unescape-bytes %)]
+                  (decode* (.element-coder this) udata 0 (alength udata)))))))
+
+

 ;; ## Tuple Lexicoder

-(defrecord TupleLexicoder
-  [coders]
-
-  Lexicoder
-
-  (lexicoder-config
-    [_]
-    (vec (cons :tuple (map lexicoder-config coders))))
-
-  (encode*
-    [_ value]
-    (when (not= (count value) (count coders))
-      (throw (IllegalArgumentException.
-               (format "Cannot encode tuple which does not match lexicoder count %d: %s"
-                       (count coders) (pr-str value)))))
-    (join-bytes (mapv #(escape-bytes (encode* %1 %2)) coders value)))
-
-  (decode*
-    [_ data offset len]
-    (let [elements (split-bytes data offset len)]
-      (when (not= (count coders) (count elements))
-        (throw (IllegalArgumentException.
-                 (format "Cannot decode tuple which does not match lexicoder count %d: %s"
-                         (count coders) (pr-str elements)))))
-      (mapv #(let [udata (unescape-bytes %2)]
-               (decode* %1 udata 0 (alength udata)))
-            coders elements))))
-
-
-(alter-meta! #'->TupleLexicoder assoc :private true)
-(alter-meta! #'map->TupleLexicoder assoc :private true)
+(deftype TupleLexicoder [coders])

 (defn tuple-lexicoder
@@ -639,6 +615,9 @@
   (->TupleLexicoder (vec coders)))

+(ns-unmap *ns* '->TupleLexicoder)
+
+
 (defmethod lexicoder :tuple
   [config]
   (when-not (config-params config)
@@ -648,8 +627,57 @@
   (apply tuple-lexicoder (map lexicoder (rest config))))

+(extend-type TupleLexicoder
+
+  Lexicoder
+
+  (lexicoder-config
+    [this]
+    (vec (cons :tuple (map lexicoder-config (.coders this)))))
+
+  (encode*
+    [this value]
+    (when (not= (count (.coders this)) (count value))
+      (throw (IllegalArgumentException.
+               (format "Cannot encode tuple which does not match lexicoder count %d: %s"
+                       (count (.coders this)) (pr-str value)))))
+    (join-bytes (mapv #(escape-bytes (encode* %1 %2)) (.coders this) value)))
+
+  (decode*
+    [this data offset len]
+    (let [elements (split-bytes data offset len)]
+      (when (not= (count (.coders this)) (count elements))
+        (throw (IllegalArgumentException.
+                 (format "Cannot decode tuple which does not match lexicoder count %d: %s"
+                         (count (.coders this)) (pr-str elements)))))
+      (mapv #(let [udata (unescape-bytes %2)]
+               (decode* %1 udata 0 (alength udata)))
+            (.coders this) elements))))
+
+

 ;; ## Reverse Lexicoder
+
+(deftype ReverseLexicoder [coder])
+
+
+(defn reverse-lexicoder
+  "Wraps the given lexicoder to reverse the ordering of keys encoded with it."
+  [coder]
+  (->ReverseLexicoder coder))
+
+
+(ns-unmap *ns* '->ReverseLexicoder)
+
+
+(defmethod lexicoder :reverse
+  [config]
+  (when (not= 1 (count (config-params config)))
+    (throw (ex-info
+             (str "Reverse lexicoder config takes exactly one parameter: " (pr-str config))
+             {:config config})))
+  (reverse-lexicoder (lexicoder (second config))))
+

 (defn- flip-byte
   "Returns the inverse of a byte value, accounting for the sign bit."
@@ -660,45 +688,25 @@
     (if (< 127 b) (- b 256) b)))

-(defrecord ReverseLexicoder
-  [coder]
+(extend-type ReverseLexicoder

   Lexicoder

   (lexicoder-config
-    [_]
-    [:reverse (lexicoder-config coder)])
-
-  (encode*
-    [_ value]
-    (let [encoded ^bytes (encode* coder value)
+    [this]
+    [:reverse (lexicoder-config (.coder this))])
+
+  (encode*
+    [this value]
+    (let [encoded ^bytes (encode* (.coder this) value)
           rdata (byte-array (alength encoded))]
       (dotimes [i (alength encoded)]
         (aset-byte rdata i (flip-byte (aget encoded i))))
       rdata))

   (decode*
-    [_ data offset len]
+    [this data offset len]
     (let [encoded (byte-array len)]
       (dotimes [i (alength encoded)]
         (aset-byte encoded i (flip-byte (aget ^bytes data (+ offset i)))))
-      (decode* coder encoded 0 len))))
-
-
-(alter-meta! #'->ReverseLexicoder assoc :private true)
-(alter-meta! #'map->ReverseLexicoder assoc :private true)
-
-
-(defn reverse-lexicoder
-  "Wraps the given lexicoder to reverse the ordering of keys encoded with it."
-  [coder]
-  (->ReverseLexicoder coder))
-
-
-(defmethod lexicoder :reverse
-  [config]
-  (when (not= 1 (count (config-params config)))
-    (throw (ex-info
-             (str "Reverse lexicoder config takes exactly one parameter: " (pr-str config))
-             {:config config})))
-  (reverse-lexicoder (lexicoder (second config))))
+      (decode* (.coder this) encoded 0 len))))


fix bug in displaying component pages in UI

--- src/clj/backtype/storm/ui/core.clj
+++ src/clj/backtype/storm/ui/core.clj
@@ -668,7 +668,7 @@
        (-> (topology-page id (:window m))
            ui-template))
   (GET "/topology/:id/component/:component" [id component & m]
-       (-> (component-page id (Integer/parseInt component) (:window m))
+       (-> (component-page id component (:window m))
            ui-template))
   (GET "/topology/:id/task/:task" [id task & m]
        (-> (task-page id (Integer/parseInt task) (:window m))


Remove def of state/db because it will be nill at the time of the def

--- src/clj/traveler/datomic/utils.clj
+++ src/clj/traveler/datomic/utils.clj
@@ -7,8 +7,6 @@
             [inflections.core :refer [plural]]
             [traveler.schema :as t-schema]
             [traveler.state :as t-state]))
-
-(def db t-state/db)

 (def tx-entity! (partial hatch/tx-clean-entity! t-schema/partitions t-schema/valid-attrs))

@@ -27,11 +25,11 @@
 (defn ent
   "Get an entity by attribute value"
   [attr value]
-  (map #(d/entity (d/db db) (first %))
+  (map #(d/entity (d/db t-state/db) (first %))
        (d/q '[:find ?e
               :in $ ?attr-in ?attr
               :where [?e ?attr-in ?attr]]
-            (d/db db)
+            (d/db t-state/db)
             attr value)))

 (defn count-ents
@@ -41,51 +39,51 @@
    (d/q '[:find (count ?e)
           :in $ ?a
           :where [?e ?a]]
-        (d/db db)
+        (d/db t-state/db)
         attr)))

 (defn ents
   "Return all entities that have specific attribute
   with option to limit or limit and offset them"
   ([attr]
-   (map #(d/entity (d/db db) (first %))
+   (map #(d/entity (d/db t-state/db) (first %))
         (sort (d/q '[:find ?e
                      :in $ ?a
                      :where [?e ?a]]
-                   (d/db db)
+                   (d/db t-state/db)
                    attr))))
   ([attr limit]
-   (map #(d/entity (d/db db) (first %))
+   (map #(d/entity (d/db t-state/db) (first %))
         (take limit (sort (d/q '[:find ?e
                                  :in $ ?a
                                  :where [?e ?a]]
-                               (d/db db)
+                               (d/db t-state/db)
                                attr)))))
   ([attr limit offset]
-   (map #(d/entity (d/db db) (first %))
+   (map #(d/entity (d/db t-state/db) (first %))
         (take limit (drop offset (sort (d/q '[:find ?e
                                               :in $ ?a
                                               :where [?e ?a]]
-                                            (d/db db)
+                                            (d/db t-state/db)
                                             attr)))))))

 (defn find-ents
   "Find an entity using a case-insensitive regex match"
   [attr match]
-  (map #(d/entity (d/db db) (first %))
+  (map #(d/entity (d/db t-state/db) (first %))
        (d/q '[:find ?e
               :in $ ?attr ?matcher
               :where
               [?e ?attr ?ln]
               [(re-find ?matcher ?ln)]]
-            (d/db db)
+            (d/db t-state/db)
             attr (re-pattern (str "(?i:.*" match ".*)")))))

 (defn user->db
   "Take pre-validated user map from liberator request
   and transact to database"
   [user]
-  (tx-entity! db :user (hatch/slam-all user :user)))
+  (tx-entity! t-state/db :user (hatch/slam-all user :user)))

 (defn ent->map
   "Convert an entity to a map using an output-model"


table created

table created

--- src/cljs/github_profile/views.cljs
+++ src/cljs/github_profile/views.cljs
@@ -81,13 +81,24 @@

 (defn thead-row []
   (fn []
-   [:th [:td "td-val"]]
-   #_(let [{:keys [react-key cols] :as props} (om/props this)]
-     (html [:tr (map (fn [v] (th {:val (str v)})) cols)]))))
+    [:tr
+     [:th "th-0"]
+     [:th "th-val-1"]]))
+
+(defn tbody-row []
+  (fn []
+    (let [td-vals ["val-0" "val-1"]]
+      [:tr (map-indexed
+            (fn [i v]
+              [:td
+               (conj {:key i}
+                     {:style {:border "1px" :borderStyle "solid"}}
+                     {:onClick (fn [_] (println "onClick" v))})
+               v]) td-vals)])))

 (defn table []
   (let [id "id"
-        tname "tnamee"
+        tname "table-name"
         ;; sqlfn ""
         ;; cols
         ]
@@ -95,18 +106,11 @@
       [:div
        [:div tname]
        [:table
-        [:thead (thead-row)]
-        #_(let [hm {:keyfn :sqlfn}
-              tbody-fn (or (id {:salaries (om/factory TBodySalaries hm)})
-                           (fn [_] (str "ERROR: Unknown id: '" id "'."
-                                        " tbody-fn undefined.")))]
-          #_(println
-             "=" (= props {:id id :tname tname :cols cols :sqlfn sqlfn})
-             "(type props)" (type props)
-             "(type {:id id :tname tname :cols cols :sqlfn sqlfn})"
-             (type {:id id :tname tname :cols cols :sqlfn sqlfn}))
-          ;; merge must be done - can't use 'props' ???
-          (tbody-fn (merge {} props)))]])))
+        [:thead [thead-row]]
+        [:tbody
+         [tbody-row]
+         [tbody-row]]
+        ]])))

 ;; main

@@ -119,7 +123,8 @@
   (let [active-panel (re-frame/subscribe [:active-panel])]
     (fn []
       [:div
-       [loading-throbber]
-       [user-name-and-avatar]
-       (panels @active-panel)
+       [table]
+       #_[loading-throbber]
+       #_[user-name-and-avatar]
+       #_(panels @active-panel)
        ])))


Deserialization tests for datascript.

Deserialization tests for datascript.

--- src/cljs/link_collective/core.cljs
+++ src/cljs/link_collective/core.cljs
@@ -6,6 +6,7 @@
             [geschichte.sync :refer [client-peer]]
             [konserve.store :refer [new-mem-store]]
             [cljs.core.async :refer [put! chan <! >! alts! timeout close!] :as async]
+            [cljs.reader :refer [read-string]]
             [kioo.om :refer [content set-attr do-> substitute listen]]
             [kioo.core :refer [handle-wrapper]]
             [om.core :as om :include-macros true])
@@ -40,23 +41,65 @@
 (def val-ch (chan))

-(let [schema {:aka {:db/cardinality :db.cardinality/many}}
-      conn   (d/create-conn schema)]
-  (:db-after (d/transact @conn [ { :db/id -1
-                                  :name  "Maksim"
-                                  :age   45
-                                  :aka   ["Maks Otto von Stirlitz", "Jack Ryan"] } ]))
-  #_(d/q '[ :find  ?n ?a
-          :where [?e :aka "Maks Otto von Stirlitz"]
-                 [?e :name ?n]
-                 [?e :age  ?a] ]
-       @conn))
+#_(let [post {:title "Spiegel Online"
+            :content "http://spiegel.de #spon"
+            :author "kordano"
+            :ts (js/Date.)}
+      post-id (uuid post)
+      comment {:content "this is boring :-/"
+               :author "bob@polyc0l0r.net"
+               :ts (js/Date.)}
+      comment-id (uuid comment)
+      vote {:author "bob@polyc0l0r.net" :type :down}
+      vote-id (uuid vote)]
+  (go (<! (s/create-repo! stage "eve@polyc0l0r.net" "link-collective discourse."
+                          {:posts {post-id post}
+                           :hashtags {(uuid :#spon) :#spon}
+                           :hashtags->posts {(uuid :#spon) #{post-id}}
+                           :comments {comment-id comment}
+                           :posts->comments {post-id #{comment-id}}
+                           :votes {vote-id vote}
+                           :posts->votes {post-id #{vote-id}}}
+                          "master"))))

+(let [schema {:votes {:db/cardinality :db.cardinality/many}
+              :comments {:db/cardinality :db.cardinality/many}
+              :hashtags {:db/cardinality :db.cardinality/many}}
+      conn   (d/create-conn schema)
+      init-db (:db-after (d/transact @conn [{:db/id -1
+                                             :title "Spiegel Online"
+                                             :content "http://spiegel.de #spon"
+                                             :author "bob@polyc0l0r.net"
+                                             :ts (js/Date.)
+                                             :hashtags [:#spon]
+                                             :comments [{:content "this is boring :-/"
+                                                         :author "kordano@polyc0l0r.net"
+                                                         :ts (js/Date.)}]
+                                             :votes [{:author "kordano@polyc0l0r.net"
+                                                      :type :down}]}])) ]
+  (pr-str init-db)
+  #_(go (<! (s/create-repo! stage
+                            "eve@polyc0l0r.net"
+                            "link-collective discourse."
+                            init-db
+                            "master")))
+  #_(d/q '[:find ?c ?e
+         :where
+         [?e :author "bob@polyc0l0r.net"]
+         [?e :content ?c]]
+       init-db))
+
+
+(cljs.reader/register-tag-parser! "datascript.Datom" d/map->Datom)
+(cljs.reader/register-tag-parser! "datascript.DB" d/map->DB)
+
+
+(implements? IRecord (read-string "#datascript.DB{:schema {:votes {:db/cardinality :db.cardinality/many}, :comments {:db/cardinality :db.cardinality/many}, :hashtags {:db/cardinality :db.cardinality/many}}, :ea {1 {:comments #{#datascript.Datom{:e 1, :a :comments, :v {:content \"this is boring :-/\", :author \"kordano@polyc0l0r.net\", :ts #inst \"2014-05-26T17:29:27.972-00:00\"}, :tx 536870913, :added true}}, :title #{#datascript.Datom{:e 1, :a :title, :v \"Spiegel Online\", :tx 536870913, :added true}}, :content #{#datascript.Datom{:e 1, :a :content, :v \"http://spiegel.de #spon\", :tx 536870913, :added true}}, :ts #{#datascript.Datom{:e 1, :a :ts, :v #inst \"2014-05-26T17:29:27.972-00:00\", :tx 536870913, :added true}}, :hashtags #{#datascript.Datom{:e 1, :a :hashtags, :v :#spon, :tx 536870913, :added true}}, :votes #{#datascript.Datom{:e 1, :a :votes, :v {:author \"kordano@polyc0l0r.net\", :type :down}, :tx 536870913, :added true}}, :author #{#datascript.Datom{:e 1, :a :author, :v \"bob@polyc0l0r.net\", :tx 536870913, :added true}}}}, :av {:title {\"Spiegel Online\" #{#datascript.Datom{:e 1, :a :title, :v \"Spiegel Online\", :tx 536870913, :added true}}}, :content {\"http://spiegel.de #spon\" #{#datascript.Datom{:e 1, :a :content, :v \"http://spiegel.de #spon\", :tx 536870913, :added true}}}, :author {\"bob@polyc0l0r.net\" #{#datascript.Datom{:e 1, :a :author, :v \"bob@polyc0l0r.net\", :tx 536870913, :added true}}}, :ts {#inst \"2014-05-26T17:29:27.972-00:00\" #{#datascript.Datom{:e 1, :a :ts, :v #inst \"2014-05-26T17:29:27.972-00:00\", :tx 536870913, :added true}}}, :hashtags {:#spon #{#datascript.Datom{:e 1, :a :hashtags, :v :#spon, :tx 536870913, :added true}}}, :comments {{:content \"this is boring :-/\", :author \"kordano@polyc0l0r.net\", :ts #inst \"2014-05-26T17:29:27.972-00:00\"} #{#datascript.Datom{:e 1, :a :comments, :v {:content \"this is boring :-/\", :author \"kordano@polyc0l0r.net\", :ts #inst \"2014-05-26T17:29:27.972-00:00\"}, :tx 536870913, :added true}}}, :votes {{:author \"kordano@polyc0l0r.net\", :type :down} #{#datascript.Datom{:e 1, :a :votes, :v {:author \"kordano@polyc0l0r.net\", :type :down}, :tx 536870913, :added true}}}}, :max-eid 1, :max-tx 536870913}"))

 #_(go (def store
         (<! (new-mem-store
-             (atom {#uuid "0912a672-6bc2-5297-9ffa-948998517273"
+             #_(atom {#uuid "0912a672-6bc2-5297-9ffa-948998517273"
                     {:transactions
                      [[#uuid "2b21fbe0-e8a8-563d-bfba-e4b6022d056f"
                        #uuid "123ed64b-1e25-59fc-8c5b-038636ae6c3d"]],
@@ -108,30 +151,9 @@

       (def stage (<! (s/create-stage! "eve@polyc0l0r.net" peer eval-fn)))

-      (async/tap (get-in @stage [:volatile :val-mult]) val-ch))
+      #_(async/tap (get-in @stage [:volatile :val-mult]) val-ch))

-
-#_(let [post {:title "Spiegel Online"
-            :content "http://spiegel.de #spon"
-            :author "kordano"
-            :ts (js/Date.)}
-      post-id (uuid post)
-      comment {:content "this is boring :-/"
-               :author "bob@polyc0l0r.net"
-               :ts (js/Date.)}
-      comment-id (uuid comment)
-      vote {:author "bob@polyc0l0r.net" :type :down}
-      vote-id (uuid vote)]
-  (go (<! (s/create-repo! stage "eve@polyc0l0r.net" "link-collective discourse."
-                          {:posts {post-id post}
-                           :hashtags {(uuid :#spon) :#spon}
-                           :hashtags->posts {(uuid :#spon) #{post-id}}
-                           :comments {comment-id comment}
-                           :posts->comments {post-id #{comment-id}}
-                           :votes {vote-id vote}
-                           :posts->votes {post-id #{vote-id}}}
-                          "master"))))

 (comment


adding

adding

--- src/cljs/shop/components/home.cljs
+++ src/cljs/shop/components/home.cljs
@@ -199,15 +199,19 @@
                                       year (.-value (om/get-node owner "year"))
                                       price (.-value (om/get-node owner "price"))
                                       countryId  (.-value (select-all ".country"))
-                                      genreId  (.-value (select-all ".genre"))]
+                                      genreId  (.-value (select-all ".genre"))
+                                      country  (.-innerHTML (select-all (str ".country > option[value='" countryId "']")))
+                                      genre  (.-innerHTML (select-all (str ".genre > option[value='" genreId "']")))
+                                      ]
                                     (when (and(not= name "") (not= price "") (not= year ""))
                                       (POST "game" {:format :json
                                                   :response-format (json-response-format {:keywords? true})
                                                   :params {:price price :name name :year year :countryId countryId :genreId genreId}
                                                   :handler (fn [response]
+                                                    (println (shop.state/games))
                                                     (let [
                                                       key (:generated_key (first response))
-                                                      newGame {:price price :gameid key :name name :year year :countryId countryId :genreId genreId}]
+                                                      newGame {:price price :gameid key :name name :year year :genre genre :country country}]
                                                       (om/update! state [:games] (set(conj (shop.state/games) newGame)))
                                                       (om/update! state [:allGames] (set(conj (shop.state/allGames) newGame)))
                                                       )


Raise a specific error when trying to transact invalid sequences.

This specifically checks for things like :db/add foo bar (nil),
which will otherwise fail elsewhere after being exploded.

--- src/datomish/transact/explode.cljc
+++ src/datomish/transact/explode.cljc
@@ -60,11 +60,19 @@
                 :op    entity }))

       (sequential? v)
-      (if (ds/multival? (db/schema db) a*) ;; dm/schema
-        (mapcat (partial explode-entity-a-v db entity eid a) v) ;; Allow sequences of nested maps, etc.  This does mean [[1]] will work.
-        (raise "Sequential values " v " but attribute " a " is :db.cardinality/one"
-               {:error :transact/entity-sequential-cardinality-one
-                :op    entity }))
+      (if (some nil? v)
+        ;; This is a hard one to track down, with a steep stack back in `transact/ensure-entity-form`, so
+        ;; we error specifically here rather than expanding further.
+        (raise "Sequential attribute value for " a " contains nil."
+               {:error :transact/sequence-contains-nil
+                :op entity
+                :attribute a
+                :value v})
+        (if (ds/multival? (db/schema db) a*) ;; dm/schema
+          (mapcat (partial explode-entity-a-v db entity eid a) v) ;; Allow sequences of nested maps, etc.  This does mean [[1]] will work.
+          (raise "Sequential values " v " but attribute " a " is :db.cardinality/one"
+                 {:error :transact/entity-sequential-cardinality-one
+                  :op    entity })))

       true
       [[:db/add eid a* v]])))


Accumulate is a better word than ground for summing up the durations.

--- src/overtunes/songs/canone_alla_quarta.clj
+++ src/overtunes/songs/canone_alla_quarta.clj
@@ -41,8 +41,8 @@

 (defn melody [notes]
   (let [functionalise #(update-all % [:time :pitch] natural-map)
-        ground-time (update :time sums)]
-    (-> notes ground-time functionalise)))
+        accumulate-time (update :time sums)]
+    (-> notes accumulate-time functionalise)))

 (def leader
   (let [call


Whitespace.

Whitespace.

--- src/philly_show_checker/server/scraper.clj
+++ src/philly_show_checker/server/scraper.clj
@@ -1,17 +1,17 @@
 (ns philly-show-checker.server.scraper
-  (:require [philly-show-checker.server.db    :as db]
-            [clojure.string                   :as string]
-            [clojurewerkz.quartzite.scheduler :as scheduler]
-            [clojurewerkz.quartzite.jobs      :as jobs]
-            [clojurewerkz.quartzite.triggers  :as triggers]
+  (:require [philly-show-checker.server.db                     :as db]
+            [clojure.string                                    :as string]
+            [clojurewerkz.quartzite.scheduler                  :as scheduler]
+            [clojurewerkz.quartzite.jobs                       :as jobs]
+            [clojurewerkz.quartzite.triggers                   :as triggers]
             [clojurewerkz.quartzite.schedule.calendar-interval :as interval]
-            [org.httpkit.client               :as http-client]))
+            [org.httpkit.client                                :as http-client]))
+
+(def jobs (atom {}))

 (defn ->scraper-job-name
   [^clojure.lang.Symbol venue-name]
   (symbol (string/join "" (map string/capitalize (string/split (name venue-name) #"-")))))
-
-(def jobs (atom {}))

 (defmacro defscraper
   [venue-name url html-parser-fn]


Fixed final call to ultrarunner

Fixed final call to ultrarunner

--- src/clj/forma/hadoop/jobs/scatter.clj
+++ src/clj/forma/hadoop/jobs/scatter.clj
@@ -277,12 +277,7 @@
 (defmain ultrarunner
   [tmp-root static-path final-path out-path]
   (let [est-map (forma-run-parameters "500-16")]
-    (workflow [tmp-root]
-              bucketstatic
-              ([:tmp-dirs static-path]
-                 (?- (hfs-seqfile static-path)
-                     (static-src est-map pail-path)))
-
+    (workflow [tmp-root]
               genbetas
               ([:tmp-dirs beta-path]
                  (?- (hfs-seqfile beta-path)


Added lat and lon to static dataset processing.

--- src/clj/forma/hadoop/jobs/scatter.clj
+++ src/clj/forma/hadoop/jobs/scatter.clj
@@ -35,12 +35,13 @@
                                       (static-chunktap "hansen")
                                       (hfs-seqfile *ecoid-path*)
                                       (hfs-seqfile *gadm-path*)])]
-    (?<- (hfs-textline out-path :sinkparts 3)
-         [?country ?mod-h ?mod-v ?sample ?line ?hansen ?ecoid ?vcf ?gadm]
+    (?<- (hfs-textline out-path :sinkparts 3 :sink-template "%s/")
+         [?country ?lat ?lon ?mod-h ?mod-v ?sample ?line ?hansen ?ecoid ?vcf ?gadm]
          (vcf _ ?mod-h ?mod-v ?sample ?line ?vcf)
          (hansen _ ?mod-h ?mod-v ?sample ?line ?hansen)
          (ecoid _ ?mod-h ?mod-v ?sample ?line ?ecoid)
          (gadm _ ?mod-h ?mod-v ?sample ?line ?gadm)
+         (m/modis->latlon ?mod-h ?mod-v ?sample ?line :> ?lat ?lon)
          (converter ?country ?gadm)
          (>= ?vcf 25))))


simpilfy if to when in sc-one example

simpilfy if to when in sc-one example

--- docs/sc-book/sc-one.clj
+++ docs/sc-book/sc-one.clj
@@ -643,8 +643,7 @@
                       :pan (ranged-rand -1 1)))
         (println "rest"))
       (Thread/sleep 200)
-      (if @cont
-        (recur)))))
+      (when @cont (recur)))))

 ;; to stop


Add a /home route that has the repl view on it

--- src/todo_repl_webapp/handler.clj
+++ src/todo_repl_webapp/handler.clj
@@ -43,6 +43,7 @@

 (defroutes app-routes
   (GET "/" [] "todo repl landing page")
+  (GET "/home" [] (do (println "get /")
                   (views/home (tasks))))
   (POST "/eval" [evalInput]
     (do


Move eval.js include to bottom of body

Move eval.js include to bottom of body

The button click events weren't being recognized when eval.js was included in the head.

--- src/todo_repl_webapp/handler.clj
+++ src/todo_repl_webapp/handler.clj
@@ -13,8 +13,7 @@
           [:title "todo-repl"]
           (page/include-css "css/bootstrap.min.css")
           (page/include-js "http://code.jquery.com/jquery-1.10.1.min.js"
-                           "js/boostrap.min.js"
-                           "js/eval.js")]
+                           "js/bootstrap.min.js")]
         [:body
           [:div.col-md-7.col-md-offset-2
             [:h1 "todo-repl"]
@@ -26,7 +25,8 @@
                           [:br]
                           (form/submit-button {:id "todoSubmitButton"}
                                               "Eval"))]
-          [:div#display.col-md-7.col-md-offset-2]]))
+          [:div#display.col-md-7.col-md-offset-2]
+          (page/include-js "js/eval.js")]))
 (defn eval-page [x & xs]
   (html [:h1 "Eval"]
         [:h2 x]))


boxes

boxes

--- src/nextbus/core.cljs
+++ src/nextbus/core.cljs
@@ -45,15 +45,17 @@
 (defn render-monitors [mons]
   (into [:div.monitors] (map (partial vector render-monitor) mons)))

-;; -------------------------
-;; Views
+;;;;;;;;;;;
+;  views  ;
+;;;;;;;;;;;

 (defn home-page []
   [:div [:h2 "Next bus"]
    [render-monitors @monitors]])

-;; -------------------------
-;; Initialize app
+;;;;;;;;;;;;;;;;;;;;
+;  initialize app  ;
+;;;;;;;;;;;;;;;;;;;;

 (defn mount-root []
   (reagent/render [home-page] (.getElementById js/document "app")))


Add swagger docs

Add swagger docs

--- src/restaurant_inspections_api/schemas.clj
+++ src/restaurant_inspections_api/schemas.clj
@@ -163,7 +163,11 @@

                    "/businesses" {:get {:responses {200 {:schema Business
                                                          :description "Found it!"}}
-                                        :summary "adds two numbers together"}}
+                                        :parameters {:query {(s/optional-key :countyNumber) s/Int
+                                                              (s/optional-key :zipCodes) s/Str
+                                                              (s/optional-key :perPage) s/Int
+                                                              (s/optional-ket :page) s/Int}}
+                                        :summary "Get all businesses"}}

                    "/businesses/:licenseNumber" {:get {:responses {200 {:schema Business
                                                                         :description "Found it!"}}