Add child context

Add child context

--- src/atom_finder/questions/superfluous_parens.clj
+++ src/atom_finder/questions/superfluous_parens.clj
@@ -37,6 +37,13 @@
          (atom-lookup :operator-precedence)]]
   (find-atoms paren-types root)))

+(defn child-or-nil
+  "If this node has one child return it, otherwise return nil"
+  [node]
+  (let [[kid & others] (children node)]
+    (when (empty? others)
+      kid)))
+
 (defn find-all-parens-in-project
   [edn-file]
   (println (str (now)))
@@ -47,8 +54,9 @@
            {:file (atom-finder-relative-path file)}
            (->> file parse-file find-parens
                 (map-values (partial map (fn [node]
-                                           (merge {:parent-type (opname-or-typename (parent node))
-                                                   :node-type (opname-or-typename node)}
+                                           (merge {:parent-type (-> node parent opname-or-typename)
+                                                   :node-type (-> node opname-or-typename)
+                                                   :child-type (some-> node child-or-nil opname-or-typename)}
                                                   (dissoc (loc node) :length :start-line)
                                                   )))))
            )))
@@ -60,8 +68,8 @@

 (defn main-superfluous-parens
   []
-  (let [edn-file "tmp/all-parens_2018-10-28_context.edn"
-        csv-file "src/analysis/data/all-parens_2018-10-28_context.csv"
+  (let [edn-file "tmp/all-parens_2018-10-29_02_child.edn"
+        csv-file "src/analysis/data/all-parens_2018-10-29_02_child.csv"
         ]
     (find-all-parens-in-project edn-file)
     ;(summarize-all-nodes edn-file csv-file)


CMR-5098 Fixes system-int-test build dependency.

--- system-int-test/test/cmr/system_int_test/bootstrap/rebalance_collections_test.clj
+++ system-int-test/test/cmr/system_int_test/bootstrap/rebalance_collections_test.clj
@@ -10,7 +10,6 @@
    [cmr.system-int-test.data2.core :as d]
    [cmr.system-int-test.data2.granule :as dg]
    [cmr.system-int-test.system :as s]
-   [cmr.metadata-db.int-test.utility :as mdb-util]
    [cmr.metadata-db.services.concept-service :as concept-service]
    [cmr.system-int-test.utils.bootstrap-util :as bootstrap]
    [cmr.system-int-test.utils.dev-system-util :as dev-sys-util]
@@ -486,7 +485,7 @@
      (ingest/delete-concept deleted-coll-concept)
      (index/wait-until-indexed)
      (side/eval-form `(tk/advance-time! ~(* (concept-service/days-to-keep-tombstone) 24 3600)))
-     (is (= 204 (mdb-util/old-revision-concept-cleanup)))
+     (is (= 204 (:status (mdb/cleanup-old-revisions))))

      ;; Rebalance to small-collections
      (bootstrap/start-rebalance-collection (:concept-id deleted-coll) {:target "small-collections"})


adding prediction; break classification -> feats

--- src/clojure/zensols/model/execute_classifier.clj
+++ src/clojure/zensols/model/execute_classifier.clj
@@ -12,6 +12,7 @@
   (:use [clojure.pprint :only [pprint]])
   (:require [clojure.tools.logging :as log]
             [clojure.string :as str])
+  (:require [zensols.tabres.display-results :as dr])
   (:require [zensols.actioncli.resource :refer (resource-path)]
             [zensols.model.classifier :as cl]
             [zensols.model.weka :as weka]))
@@ -234,6 +235,29 @@
                                      :attrib attrib}
                                 e)))))))))

+(defn- classify-features
+  "Classify a single instance using a trained model.
+
+  * **model** a model created
+  from [[zensols.model.eval-classifier/train-model]] or [[read-model]]"
+  [model features]
+  (log/debugf "classifying features: %s" features)
+  (with-model-conf (:model-conf model)
+    (let [{classifier :classifier
+           feature-metas :feature-metas} model
+          model-conf (model-config)
+          trans-fn (or (:classifications-map-fn model-conf) identity)
+          ;; must use copy constructor or it gives bad results
+          instances (weka/clone-instances (:instances model))
+          attribs (map name feature-metas)
+          return-keys (:model-return-keys model-conf)]
+      (log/tracef "instances: %s" (type instances))
+      (set-instance-values (.instance instances 0) features)
+      (->> (cl/classify-instance classifier instances return-keys)
+           first
+           (merge (if (contains? return-keys :features) {:features features}))
+           trans-fn))))
+
 (defn classify
   "Classify a single instance using a trained model.

@@ -242,26 +266,51 @@
   [model & data]
   (log/debugf "classifying: %s" data)
   (with-model-conf (:model-conf model)
-    (let [{classifier :classifier
-           feature-metas :feature-metas
-           ;; this was the context that was persisted with the model
+    (let [{;; this was the context that was persisted with the model
            context :context} model
           _ (log/tracef "context: <%s>" context)
           model-conf (model-config)
-          trans-fn (or (:classifications-map-fn model-conf) identity)
           create-features-fn (or (:create-features-fn model-conf)
                                  (throw (ex-info "No create-features-fn defined in model"
                                                  {:model-name (:name model-conf)})))
           _ (log/debugf "create-features-fn: %s" create-features-fn)
           cfargs (concat data (list context))
           _ (log/debugf "arg count: %d" (count cfargs))
-          features (apply create-features-fn cfargs)
-          ;; must use copy constructor or it gives bad results
-          instances (weka/clone-instances (:instances model))
-          attribs (map name feature-metas)
-          return-keys (:model-return-keys model-conf)]
-      (set-instance-values (.instance instances 0) features)
-      (->> (cl/classify-instance classifier instances return-keys)
-           first
-           (merge (if (contains? return-keys :features) {:features features}))
-           trans-fn ))))
+          features (apply create-features-fn cfargs)]
+      (classify-features model features))))
+
+(defn predict
+  "Create predictions using the provided model.
+
+  Keys
+  ----
+  * **:set-type** the set to draw the test data, which defaults to `:test`"
+  [model & {:keys [set-type] :or {set-type :test}}]
+  (let [{:keys [feature-metas-fn display-feature-metas-fn
+                class-feature-meta-fn create-feature-sets-fn]} (model-config)
+        display-feature-metas-fn (or display-feature-metas-fn feature-metas-fn)
+        feature-metas (display-feature-metas-fn)
+        class-feature-meta (class-feature-meta-fn)
+        pred-keys [:pred-label :correct-label :correct? :confidence]
+        keys (concat pred-keys (map first feature-metas))]
+    (->> (create-feature-sets-fn :set-type :test)
+         (map (fn [anon]
+                (log/debugf "classifying: <%s>" anon)
+                (let [{:keys [label distributions]}
+                      (classify-features model anon)
+                      confidence (get distributions label)
+                      correct-label (get anon (first class-feature-meta))
+                      correct? (= correct-label label)
+                      anon (merge anon
+                                  (zipmap pred-keys
+                                          [label correct-label correct? confidence]))]
+                  (zipmap keys (map #(get anon %) keys)))))
+         (hash-map :columns keys :data))))
+
+(defn display-predictions [preds]
+ (let [{:keys [columns data]} preds
+       col-names (map name columns)]
+   (->> data
+        (map (fn [row]
+               (map #(get row %) columns)))
+        (#(dr/display-results % :column-names col-names)))))


Remove commented autocompleter code

Remove commented autocompleter code

--- src/lt/plugins/elm_light/autocompleter/core.cljs
+++ src/lt/plugins/elm_light/autocompleter/core.cljs
@@ -130,10 +130,7 @@
                          (if (seq chs)
                            (do
                              (listen-for-hint-results ed chs (init-show-hint-ch ed))
-                             (js/CodeMirror.on line-handle "change" on-line-change)
-                             ;;(ctx/in! [:editor.keys.hinting.active] ed)
-                             ;;(ctx/out!  [:editor.keys.hinting.active])
-                             )
+                             (js/CodeMirror.on line-handle "change" on-line-change))
                            (maybe-close-hinter ed)))))


Troubleshooting heroku workers

Troubleshooting heroku workers

--- src/org/gensym/viddy/workerrun.clj
+++ src/org/gensym/viddy/workerrun.clj
@@ -19,7 +19,7 @@

 (defn -main []
   (let [db-spec (dbconn/db-spec  (System/getenv "DATABASE_URL"))]
-    (start db-spec)
+    (comment (start db-spec))
     (println "Worker started.")
     (.start (Thread. #()))))


1.3-ifying examples.mackey-glass-int.

1.3-ifying examples.mackey-glass-int.

--- src/examples/mackey_glass_int.clj
+++ src/examples/mackey_glass_int.clj
@@ -12,7 +12,7 @@

 (ns examples.mackey-glass-int
   (:use [clojush][local-file])
-  (:require [clojure.contrib.math :as math]
+  (:require [clojure.math.numeric-tower :as math]
 	    [clojure.string :as s]))

 (defn read-data []


Break out confusion matrix analyzing into its own function.

--- project/analyze-data/src/analyze_data/core.clj
+++ project/analyze-data/src/analyze_data/core.clj
@@ -24,11 +24,27 @@
     :knn {:k 3, :distance-fn cosine-distance}
     :naive-bayes {}))

+(defn analyze-confusion-matrix
+  [dataset confusion-matrix]
+  (let [{:keys [y classes]} dataset]
+    (with-out-str
+      (println "Classes:")
+      (doseq [c classes]
+        (let [class-count (count (filter (partial = (.indexOf classes c)) y))]
+          (println "  " (str c ":") class-count)))
+      (println "Confusion matrix:")
+      (doseq [c classes]
+        (println "  " (str c ":") (confusion-matrix c)))
+      (println "Accuracy:" (->> confusion-matrix accuracy float (format "%.2f")))
+      (println "F1 Scores:")
+      (let [f1-scores (map (partial f1-score confusion-matrix) classes)]
+        (doseq [[c f1] (zipmap classes f1-scores)]
+          (println "  " (str c ":") (->> f1 float (format "%.2f"))))))))
+
 (defn train
   [dataset-file model-type]
   (m/set-current-implementation :vectorz)
   (let [dataset (read-object dataset-file)
-        {:keys [y classes]} dataset
         k 10
         confusion-matrix (apply k-fold-cross-validation
                                 k
@@ -36,15 +52,4 @@
                                 dataset
                                 (get-options model-type))]
     (println (name model-type) (str k "-fold cross-validation on") dataset-file)
-    (println "Classes:")
-    (doseq [c classes]
-      (let [class-count (count (filter (partial = (.indexOf classes c)) y))]
-        (println "  " (str c ":") class-count)))
-    (println "Confusion matrix:")
-    (doseq [c classes]
-      (println "  " (str c ":") (confusion-matrix c)))
-    (println "Accuracy:" (->> confusion-matrix accuracy float (format "%.2f")))
-    (println "F1 Scores:")
-    (let [f1-scores (map (partial f1-score confusion-matrix) classes)]
-      (doseq [[c f1] (zipmap classes f1-scores)]
-        (println "  " (str c ":") (->> f1 float (format "%.2f")))))))
+    (println (analyze-confusion-matrix dataset confusion-matrix))))


Make user-hours fn private.

Make user-hours fn private.

--- src/time_tracker/invoices/core.clj
+++ src/time_tracker/invoices/core.clj
@@ -29,7 +29,7 @@
   (let [user-id->zero (zipmap required-user-ids (repeat 0.00M))]
     (reduce add-hours user-id->zero (vals timers))))

-(defn user-hours
+(defn- user-hours
   "Generates a seq of {:id :rate :hours}.
   There will be a row for every user in `users`."
   [users timers user-id->rate]
@@ -140,4 +140,4 @@
        [:paragraph "Amount due: " (money (:amount-due printable-invoice))]
        [:phrase "Notes:"]
        [:paragraph (:notes printable-invoice)]]
-      out)))+      out)))


Extended the test for dissoc-if-nil

Extended the test for dissoc-if-nil

Added a test case for multiple keys, only some of which are nil.

--- test/com/puppetlabs/test/utils.clj
+++ test/com/puppetlabs/test/utils.clj
@@ -107,11 +107,13 @@
           (maptrans {[:a :b] :foo} {:a {:foo 3} :b {:foo 3}})))))

 (deftest dissoc-if-nil-test
-  (let [testmap {:a 1 :b nil}]
+  (let [testmap {:a 1 :b nil :c 1 :d nil}]
     (testing "should remove the key if the value is nil"
       (is (= (dissoc testmap :b) (dissoc-if-nil testmap :b))))
     (testing "should not remove the key if the value is not nil"
-      (is (= testmap (dissoc-if-nil testmap :a))))))
+      (is (= testmap (dissoc-if-nil testmap :a))))
+    (testing "should remove multiple keys if their values are nil"
+      (is (= (dissoc testmap :b :d) (dissoc-if-nil testmap :a :b :c :d))))))

 (deftest missing?-test
   (let [sample {:a "asdf" :b "asdf" :c "asdf"}]


convert from a when-not to a when (pos?)

--- src/tile_game/grid.cljs
+++ src/tile_game/grid.cljs
@@ -46,7 +46,7 @@
      "Shuffle"]]])

 (defn render-tile [[x y] tile command]
-  (when-not (zero? tile)
+  (when (pos? tile)
     (let [fill-color (nth colors tile)]
       [:g {:key (str "tile-" tile) :on-click #(async/put! command tile)}
        [:rect {:x (+ x 0.05) :y (+ y 0.05) :width 0.9 :height 0.9 :fill fill-color}]


Remove a bit of duplication

Remove a bit of duplication

--- src/maestro/elasticsearch.clj
+++ src/maestro/elasticsearch.clj
@@ -114,6 +114,10 @@
     {:include ["application" "end" "environment" "message" "phase" "region" "start" "status" "user"
                "new-state.hash" "new-state.image-details"
                "previous-state.hash" "previous-state.image-details"]}))
+
+(defn- map-to-source-with-id
+  [hits]
+  (map (fn [h] (assoc (:_source h) :id (:_id h))) hits))

 (defn get-deployments
   [{:keys [application environment full? from region size start-from start-to status]}]
@@ -126,7 +130,7 @@
         response (esd/search @conn index-name deployment-type :filter {:and {:filters filters}} :size (or size 10) :from (or from 0) :sort {:start "desc"} :_source (source-filter full?))]
     (->> response
          esrsp/hits-from
-         (map (fn [h] (assoc (:_source h) :id (:_id h)))))))
+         map-to-source-with-id)))

 (defn create-task
   [task-id deployment-id document]
@@ -150,7 +154,7 @@
   [deployment-id]
   (nil-if-no-deployment deployment-id (->> (esd/search @conn index-name task-type :query (q/match-all) :filter (parent-filter deployment-type deployment-id) :sort {:sequence "asc"} :size 10000)
                                            esrsp/hits-from
-                                           (map (fn [h] (assoc (:_source h) :id (:_id h))))
+                                           map-to-source-with-id
                                            (map #(dissoc % :sequence)))))

 (defn deployment-logs
@@ -158,67 +162,59 @@
   (nil-if-no-deployment deployment-id (let [filters (add-since-date-filter [(parent-filter deployment-type deployment-id)] :date since)]
                                         (->> (esd/search @conn index-name log-type :query (q/match-all) :filter {:and {:filters filters}} :sort {:date "asc"} :size 10000)
                                              esrsp/hits-from
-                                             (map (fn [h] (assoc (:_source h) :id (:_id h))))))))
+                                             map-to-source-with-id))))
+
+(defn- map-user-facets
+  [result]
+  (map (fn [f] {:user (:term f) :count (:count f)}) (get-in result [:facets :user :terms])))

 (defn deployments-by-user
   []
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:user (user-facet)})
-        facets (get-in result [:facets :user :terms])]
-    (map (fn [f] {:user (:term f) :count (:count f)}) facets)))
+  (map-user-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:user (user-facet)})))

 (defn failed-deployments-by-user
   []
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (failed-status-filter)) :size 0 :facets {:user (user-facet)})
-        facets (get-in result [:facets :user :terms])]
-    (map (fn [f] {:user (:term f) :count (:count f)}) facets)))
+  (map-user-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (failed-status-filter)) :size 0 :facets {:user (user-facet)})))
+
+(defn- map-application-facets
+  [result]
+  (map (fn [f] {:application (:term f) :count (:count f)}) (get-in result [:facets :application :terms])))

 (defn deployments-by-user-by-application
   [user]
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (user-filter user)]}}) :size 0 :facets {:application (application-facet)})
-        facets (get-in result [:facets :application :terms])]
-    (map (fn [f] {:application (:term f) :count (:count f)}) facets)))
+  (map-application-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (user-filter user)]}}) :size 0 :facets {:application (application-facet)})))

 (defn deployments-by-application
   []
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:application (application-facet)})
-        facets (get-in result [:facets :application :terms])]
-    (map (fn [f] {:application (:term f) :count (:count f)}) facets)))
+  (map-application-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:application (application-facet)})))
+
+(defn- map-date-facets
+  [result]
+  (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) (get-in result [:facets :date :entries])))

 (defn deployments-by-year
   []
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:date (start-date-facet "year")})
-        facets (get-in result [:facets :date :entries])]
-    (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) facets)))
+  (map-date-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:date (start-date-facet "year")})))

 (defn deployments-by-month
   []
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:date (start-date-facet "month")})
-        facets (get-in result [:facets :date :entries])]
-    (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) facets)))
+  (map-date-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:date (start-date-facet "month")})))

 (defn deployments-by-day
   []
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:date (start-date-facet "day")})
-        facets (get-in result [:facets :date :entries])]
-    (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) facets)))
+  (map-date-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter (completed-status-filter)) :size 0 :facets {:date (start-date-facet "day")})))

 (defn deployments-in-environment-by-year
   [environment]
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (environment-filter environment)]}}) :size 0 :facets {:date (start-date-facet "year")})
-        facets (get-in result [:facets :date :entries])]
-    (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) facets)))
+  (map-date-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (environment-filter environment)]}}) :size 0 :facets {:date (start-date-facet "year")})))

 (defn deployments-in-environment-by-month
   [environment]
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (environment-filter environment)]}}) :size 0 :facets {:date (start-date-facet "month")})
-        facets (get-in result [:facets :date :entries])]
-    (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) facets)))
+  (map-date-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (environment-filter environment)]}}) :size 0 :facets {:date (start-date-facet "month")})))

 (defn deployments-in-environment-by-day
   [environment]
-  (let [result (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (environment-filter environment)]}}) :size 0 :facets {:date (start-date-facet "day")})
-        facets (get-in result [:facets :date :entries])]
-    (map (fn [f] {:date (str (c/from-long (:time f))) :count (:count f)}) facets)))
+  (map-date-facets (esd/search @conn index-name deployment-type :query (q/filtered :query (q/match-all) :filter {:and {:filters [(completed-status-filter) (environment-filter environment)]}}) :size 0 :facets {:date (start-date-facet "day")})))

 (defn healthy?
   []


CLJS-1391: Error when building for target :nodejs

Fix bug when building for target nodejs. Check if source is map before
trying to assign source code to :source key.

--- src/main/clojure/cljs/closure.clj
+++ src/main/clojure/cljs/closure.clj
@@ -1349,7 +1349,7 @@
     (when-not (.exists out-file)
       (util/mkdirs out-file)
       (spit out-file
-            (cond-> (assoc js :source (deps/-source js))
+            (cond-> (if (map? js) (assoc js :source (deps/-source js)) js)
               (:preprocess js) (js-transforms opts)
               (:module-type js) (convert-js-module opts)
               true deps/-source)))


Add comment about test issue

Add comment about test issue

--- test/beehive/patterns_test.clj
+++ test/beehive/patterns_test.clj
@@ -114,6 +114,7 @@
       (let [f (patterns/submit-action shotgun action-fn Long/MAX_VALUE)]
         @f
         (.countDown ^CountDownLatch @action-blocking-latch)
+        ;; TODO: Need to rework to avoid occasional race condition
         (.await ^CountDownLatch @test-blocking-latch)
         (is (= 1 @f))))
     (testing "Nil returned if all services reject action"


Remove db related tests

Remove db related tests

For those to work (especially in a CI environment) we need to set up
an in-memory database and have migrations that prepare this in-memory
db. For now just comment these tests out.

--- test/clj/mdr2/db/core_test.clj
+++ test/clj/mdr2/db/core_test.clj
@@ -17,22 +17,14 @@
     (migrations/migrate ["migrate"] (select-keys env [:database-url]))
     (f)))

-(deftest test-users
-  (jdbc/with-transaction [t-conn *db* {:rollback-only true}]
-    (is (= 1 (db/create-user!
-              t-conn
-              {:id         "1"
-               :first_name "Sam"
-               :last_name  "Smith"
-               :email      "sam.smith@example.com"
-               :pass       "pass"}
-              {})))
-    (is (= {:id         "1"
-            :first_name "Sam"
-            :last_name  "Smith"
-            :email      "sam.smith@example.com"
-            :pass       "pass"
-            :admin      nil
-            :last_login nil
-            :is_active  nil}
-           (db/get-user t-conn {:id "1"} {})))))
+(comment
+  (deftest test-production
+    (jdbc/with-transaction [t-conn *db* {:rollback-only true}]
+      (is (= 1 (db/insert-production
+                t-conn
+                {:title "The War of the Worlds"
+                 :date 1898
+                 :identifier "b0c3f96e-5c32-11ed-9b6a-0242ac120002"
+                 :state "new"})))
+      (is (= {}
+             (db/get-production t-conn {:id "1"}))))))


RS | Add a log info message when bearer tokens are invalid

--- src/objective8/middleware.clj
+++ src/objective8/middleware.clj
@@ -1,5 +1,6 @@
 (ns objective8.middleware
-  (:require [clojure.string :as s]))
+  (:require [clojure.string :as s]
+            [clojure.tools.logging :as log]))

 (defn- keywordize [m]
   (into {} (for [[k v] m] [(keyword k) v])))
@@ -19,7 +20,8 @@
           bearer-name (get headers "api-bearer-name")]
       (if (valid-credentials? tokens-fn bearer-name bearer-token)
         (handler (update-in request [:headers] dissoc "api-bearer-token" "api-bearer-name"))
-        {:status 401}))))
+        (do (log/info (str "Invalid bearer token credentials"))
+            {:status 401})))))

 (defn wrap-not-found [handler not-found-handler]
   (fn [request]


CMR-6200: Updated collection preview gems to 0.2.0. (#883)

--- collection-renderer-lib/project.clj
+++ collection-renderer-lib/project.clj
@@ -10,9 +10,9 @@
    the hardcoded commit id during dev integration with cmr_metadata_preview project.
    The hardcoded commit id should be updated when MMT releases a new version of the gem."
   {:repo "https://git.earthdata.nasa.gov/scm/cmr/cmr_metadata_preview.git"
-   :version "cmr_metadata_preview-0.1.1"
+   :version "cmr_metadata_preview-0.2.0"
    :commit-id (or (System/getenv "CMR_METADATA_PREVIEW_COMMIT")
-                  "eed78761d70")})
+                  "91cd5b93d51")})

 (def gem-install-path
   "The directory within this library where Ruby gems are installed."


remove AOT from script

remove AOT from script

causes way too many issues. need a better way to isolate things
first. can't do shared AOT due to classpath conflicts.

--- src/main/shadow/cljs/npm/cli.cljs
+++ src/main/shadow/cljs/npm/cli.cljs
@@ -167,28 +167,6 @@
         (reader/read-string)
         (assoc :updated? updated?))))

-(defn remove-class-files [path]
-  (when (fs/existsSync path)
-    ;; shadow-cljs - error ENOENT: no such file or directory, unlink '...'
-    ;; I have no idea how readdir can find a file but then not find it when
-    ;; trying to delete it?
-    (doseq [file (into [] (fs/readdirSync path))
-            :let [file (path/resolve path file)]]
-      (cond
-        (str/ends-with? file ".class")
-        (when (fs/existsSync file)
-          (try
-            (fs/unlinkSync file)
-            (catch :default e
-              (prn [:failed-to-delete file]))))
-
-        (is-directory? file)
-        (remove-class-files file)
-
-        :else
-        nil
-        ))))
-
 (defn print-error [ex]
   (let [{:keys [tag] :as data}
         (ex-data ex)]
@@ -216,68 +194,12 @@
 (defn get-shared-home []
   (path/resolve (os/homedir) ".shadow-cljs" jar-version))

-(defn aot-compile []
-  (let [home-dir
-        (get-shared-home)
-
-        cp-file
-        (path/resolve home-dir "classpath.edn")
-
-        aot-lock-file
-        (path/resolve home-dir "aot.edn")
-
-        aot-classes
-        (path/resolve home-dir "aot")
-
-        aot-config
-        {:cache-root home-dir
-         :version jar-version
-         :dependencies [['thheller/shadow-cljs jar-version]]}]
-
-    (when (not (fs/existsSync cp-file))
-      ;; re-create classpath by running the java helper
-      (let [jar (js/require "shadow-cljs-jar/path")]
-        (mkdirp/sync home-dir)
-        (run-java home-dir ["-jar" jar] {:input (pr-str aot-config)
-                                         :stdio [nil js/process.stdout js/process.stderr]})
-        true))
-
-    ;; FIXME: should actually treat this as a lockfile but there should not be 2 separate instances doing this at the same time
-    ;; FIXME: could probably rework so that the jar downloader also builds AOT
-
-    (when (not (fs/existsSync aot-lock-file))
-      (mkdirp/sync aot-classes)
-
-      (let [{:keys [files] :as classpath-config}
-            (-> (util/slurp cp-file)
-                (reader/read-string))
-
-            jvm-args
-            ["-cp" (str/join cp-separator files)
-             (str "-Dclojure.compile.path=" aot-classes)
-             "clojure.main"
-             "-m" "shadow.cljs.aot-helper"]]
-
-        ;; println since this runs during npm install
-        (println "shadow-cljs - aot compile")
-        (run-java home-dir jvm-args {})
-        (fs/writeFileSync aot-lock-file "true")
-        (println "shadow-cljs - aot compilation finished")
-        ))))
-
 (defn get-jvm-opts [project-root {:keys [source-paths jvm-opts] :as config}]
-  (let [home-dir
-        (get-shared-home)
-
-        aot-path
-        (path/resolve home-dir "aot")
-
-        classpath
+  (let [classpath
         (get-classpath project-root config)

         classpath-str
         (->> (:files classpath)
-             (concat [aot-path])
              (concat source-paths)
              (str/join cp-separator))]

@@ -288,8 +210,6 @@
         )))

 (defn run-standalone [project-root config args opts]
-  (aot-compile) ;; should be cached already
-
   (let [cli-args
         (-> (get-jvm-opts project-root config)
             (conj "clojure.main" "-m" "shadow.cljs.devtools.cli" "--npm")
@@ -615,12 +535,6 @@
         (= action :init)
         (run-init opts)

-        (= action :aot)
-        (try
-          (aot-compile)
-          (catch :default e
-            (println "shadow-cljs - aot compilation failed")))
-
         :else
         (let [config-path (ensure-config)]
           (if-not config-path


add new test case

add new test case

--- dada-swt/src/main/clojure/org/dada/swt/new.clj
+++ dada-swt/src/main/clojure/org/dada/swt/new.clj
@@ -57,11 +57,12 @@

 ;;(inspect (? (dcount)(dfrom "Whales")))
 ;;(inspect (? (dsplit 2)(dfrom "Whales")))
+;;(inspect (? (dcount)(dsplit 2)(dfrom "Whales")))
 ;;(inspect (? (dsplit 2 list [(dsplit 3)])(dfrom "Whales")))
 ;;(inspect (? (dsplit 3)(dsplit 2)(dfrom "Whales")))

-;;(? (ccount)(from "Whales"))
+;; (? (ccount)(from "Whales"))
 ;; (? (split :ocean)(from "Whales"))
 ;; (? (split :type)(from "Whales"))
 ;; (? (union)(split :ocean nil [(pivot :type org.dada.demo.whales/types (keyword (sum-value-key :weight)))(sum :weight)(split :type )])(from "Whales"))


Removes sneaky print

Removes sneaky print

--- src/wordsmith/core.cljs
+++ src/wordsmith/core.cljs
@@ -49,7 +49,6 @@
       (om/update! (:titles app) :titles (p/get-all-titles)))
     om/IRender
     (render [_]
-      (print app)
       (dom/div #js {:className "container"}
         (om/build title-field app)
         (om/build left-menu app)


Removes initial-documen title

Removes initial-documen title

--- src/wordsmith/core.cljs
+++ src/wordsmith/core.cljs
@@ -227,7 +227,6 @@
 (defn set-initial-document!
   [app]
   (when (empty? (p/get-all-titles))
-    (om/update! app :title "Readme")
     (om/update! app :input
       (.. js/document (getElementById "readme") -textContent trim))))


Switched the categories up

Switched the categories up

--- src/yalp/categories.clj
+++ src/yalp/categories.clj
@@ -1,451 +1,325 @@
 (ns yalp.categories)

-(def categories
-  {:web_design "Web Design"
-   :othersalons "Nail Salons"
-   :refinishing "Refinishing Services"
-   :kosher "Kosher"
-   :plumbing "Plumbing"
+(def restaurants
+  {:kosher "Kosher"
    :ethiopian "Ethiopian"
-   :mags "Newspapers & Magazines"
-   :acupuncture "Acupuncture"
    :vegan "Vegan"
-   :bedbreakfast "Bed & Breakfast"
-   :tanningbeds "Tanning Beds"
-   :motorcyclerepair "Motorcycle Repair"
-   :butcher "Butcher"
-   :waxing "Waxing"
-   :bridal "Bridal"
-   :jazzandblues "Jazz & Blues"
    :portuguese "Portuguese"
-   :drywall "Drywall Installation & Repair"
    :hotpot "Hot Pot"
-   :electronicsrepair "Electronics Repair"
-   :distilleries "Distilleries"
-   :hair_extensions "Hair Extensions"
-   :wineries "Wineries"
-   :sportsbars "Sports Bars"
    :malaysian "Malaysian"
-   :jewelry "Jewellery"
-   :fishing "Fishing"
-   :tattoo "Tattoo"
    :japanese "Japanese"
-   :healthtrainers "Trainers"
-   :candy "Candy Stores"
-   :home_inspectors "Home Inspectors"
-   :florists "Florists"
-   :carpenters "Carpenters"
-   :taxis "Taxis"
    :scandinavian "Scandinavian"
    :mideastern "Middle Eastern"
-   :bowling "Bowling"
-   :estateplanning "Estate Planning Law"
-   :garage_door_services "Garage Door Services"
-   :pubs "Pubs"
-   :poolservice "Pool & Hot Tub Service"
-   :tanning "Tanning"
-   :sharedofficespaces "Shared Office Spaces"
-   :lifecoach "Life Coach"
+   :burgers "Burgers"
+   :taiwanese "Taiwanese"
+   :irish "Irish"
+   :argentine "Argentine"
+   :czech "Czech"
+   :diners "Diners"
+   :chickenshop "Chicken Shop"
+   :burmese "Burmese"
+   :afghani "Afghan"
+   :bangladeshi "Bangladeshi"
+   :poutineries "Poutineries"
+   :gluten_free "Gluten-Free"
+   :hotdogs "Fast Food"
+   :breakfast_brunch "Breakfast & Brunch"
+   :chinese "Chinese"
+   :british "British"
+   :indonesian "Indonesian"
+   :basque "Basque"
+   :scottish "Scottish"
+   :dimsum "Dim Sum"
+   :tapasmallplates "Tapas/Small Plates"
+   :halal "Halal"
+   :hawaiian "Hawaiian"
+   :lebanese "Lebanese"
+   :russian "Russian"
+   :latin "Latin American"
+   :iberian "Iberian"
+   :african "African"
+   :cafes "Cafes"
+   :himalayan "Himalayan/Nepalese"
+   :ukrainian "Ukrainian"
+   :colombian "Colombian"
+   :southafrican "South African"
+   :haitian "Haitian"
+   :senegalese "Senegalese"
+   :gastropubs "Gastropubs"
+   :vietnamese "Vietnamese"
+   :sushi "Sushi Bars"
+   :raw_food "Live/Raw Food"
+   :turkish "Turkish"
+   :thai "Thai"
+   :italian "Italian"
+   :delis "Delis"
+   :arabian "Arabian"
+   :caribbean "Caribbean"
+   :belgian "Belgian"
+   :pizza "Pizza"
+   :soulfood "Soul Food"
+   :seafood "Seafood"
+   :vegetarian "Vegetarian"
+   :bbq "Barbeque"
+   :brasseries "Brasseries"
+   :peruvian "Peruvian"
+   :modern_european "Modern European"
+   :cheesesteaks "Cheesesteaks"
+   :asianfusion "Asian Fusion"
+   :mexican "Mexican"
+   :austrian "Austrian"
+   :pakistani "Pakistani"
+   :persian "Persian/Iranian"
+   :comfortfood "Comfort Food"
+   :filipino "Filipino"
+   :falafel "Falafel"
+   :indpak "Indian"
+   :fishnchips "Fish & Chips"
+   :salvadoran "Salvadoran"
+   :southern "Southern"
+   :srilankan "Sri Lankan"
+   :cajun "Cajun/Creole"
+   :fondue "Fondue"
+   :egyptian "Egyptian"
+   :tapas "Tapas Bars"
+   :korean "Korean"
+   :brazilian "Brazilian"
+   :ramen "Ramen"
+   :moroccan "Moroccan"
+   :german "German"
+   :mongolian "Mongolian"
+   :salad "Salad"
+   :cuban "Cuban"
+   :creperies "Creperies"
+   :australian "Australian"
+   :singaporean "Singaporean"
+   :greek "Greek"
+   :venezuelan "Venezuelan"
+   :chicken_wings "Chicken Wings"
+   :foodstands "Food Stands"
+   :slovakian "Slovakian"
+   :spanish "Spanish"
+   :french "French"
+   :sandwiches "Sandwiches"
+   :cambodian "Cambodian"
+:mediterranean "Mediterranean"
+:steak "Steakhouses"
+:hungarian "Hungarian"
+:buffets "Buffets"
+:laotian "Laotian"
+:tex-mex "Tex-Mex"
+:polish "Polish"
+:soup "Soup"})
+
+(def shopping
+  {:discountstore "Dollar Store"
+   :mags "Newspapers & Magazines"
+   :watches "Watches"
+   :bridal "Bridal"
+   :mobilephones "Mobile Phones"
+   :jewelry "Jewellery"
+   :florists "Florists"
+   :artsandcrafts "Arts & Crafts"
    :furniture "Furniture Stores"
    :outdoorgear "Outdoor Gear"
-   :bagels "Bagels"
-   :groomer "Pet Groomers"
-   :skate_parks "Skate Parks"
    :vapeshops "Vape Shops"
    :goldbuyers "Gold Buyers"
-   :printmedia "Print Media"
-   :treeservices "Tree Services"
-   :burgers "Burgers"
-   :eventservices "Event Planning & Services"
    :stationery "Cards & Stationery"
    :medicalsupplies "Medical Supplies"
-   :shipping_centers "Shipping Centres"
-   :taiwanese "Taiwanese"
    :framing "Framing"
-   :tennis "Tennis"
-   :movers "Movers"
    :leather "Leather Goods"
-   :irish "Irish"
-   :locksmiths "Keys & Locksmiths"
    :popupshops "Pop-up Shops"
-   :argentine "Argentine"
-   :czech "Czech"
-   :stereo_installation "Car Stereo Installation"
-   :scuba "Scuba Diving"
-   :trampoline "Trampoline Parks"
-   :yoga "Yoga"
-   :diners "Diners"
    :shoes "Shoe Stores"
-   :seafoodmarkets "Seafood Markets"
-   :shutters "Shutters"
-   :carwash "Car Wash"
-   :solarinstallation "Solar Installation"
    :childcloth "Children's Clothing"
    :hobbyshops "Hobby Shops"
    :wigs "Wigs"
-   :burmese "Burmese"
-   :bikesharing "Bike Sharing"
+   :photographystores "Photography Stores & Services"
+   :fitnessequipment "Fitness/Exercise Equipment"
+   :cookingclasses "Cooking Classes"
+   :videoandgames "Videos & Video Game Rental"
+   :accessories "Accessories"
+   :skateshops "Skate Shops"
+   :uniforms "Uniforms"
+   :outlet_stores "Outlet Stores"
+   :fashion "Fashion"
+   :homeandgarden "Home & Garden"
+   :artsupplies "Art Supplies"
+   :mattresses "Mattresses"
+   :maternity "Maternity Wear"
+   :hottubandpool "Hot Tub & Pool"
+   :sportgoods "Sporting Goods"
+   :lingerie "Lingerie"
+   :custommerchandise "Customized Merchandise"
+   :hardware "Hardware Stores"
+   :luggage "Luggage"
+   :gardening "Nurseries & Gardening"
+   :bikes "Bikes"
+   :kitchenandbath "Kitchen & Bath"
+   :fabricstores "Fabric Stores"
+   :swimwear "Swimwear"
+   :appliances "Appliances"
+   :flowers "Flowers & Gifts"
+   :toys "Toy Stores"
+   :videogamestores "Video Game Stores"
+   :formalwear "Formal Wear"
+   :shoppingcenters "Shopping Centres"
+   :womenscloth "Women's Clothing"
+   :musicvideo "Music & DVDs"
+   :personal_shopping "Personal Shopping"
+   :homedecor "Home Decor"
+   :electronics "Electronics"
+   :adult "Adult"
+   :cosmetics "Cosmetics & Beauty Supply"
+   :batterystores "Battery Stores"
+   :bookstores "Bookstores"
+   :brewingsupplies "Brewing Supplies"
+   :opticians "Eyewear & Opticians"
+   :antiques "Antiques"
+   :galleries "Art Galleries"
+   :officeequipment "Office Equipment"
+   :golfequipment "Golf Equipment"
+   :christmastrees "Christmas Trees"
+   :skishops "Ski & Snowboard Shops"
+   :tobaccoshops "Tobacco Shops"
+   :vintage "Used, Vintage & Consignment"
+   :computers "Computers"
+   :giftshops "Gift Shops"
+   :vinyl_records "Vinyl Records"
+   :baby_gear "Baby Gear & Furniture"
+   :thrift_stores "Thrift Stores"
+   :costumes "Costumes"
+   :hats "Hats"
+   :wholesale_stores "Wholesale Stores"
+   :media "Books, Mags, Music & Video"
+   :drugstores "Drugstores"
+   :menscloth "Men's Clothing"
+   :fleamarkets "Flea Markets"
+   :sportswear "Sports Wear"
+   :hifi "High Fidelity Audio Equipment"
+   :deptstores "Department Stores"
+   :comicbooks "Comic Books"
+   :pawn "Pawn Shops"
+   :poolbilliards "Pool & Billiards"
+   :knittingsupplies "Knitting Supplies"
+   :musicalinstrumentsandteachers "Musical Instruments & Teachers"})
+
+(def food
+  {:butcher "Butcher"
+   :distilleries "Distilleries"
+   :wineries "Wineries"
+   :candy "Candy Stores"
+   :bagels "Bagels"
+   :seafoodmarkets "Seafood Markets"
+   :farmersmarket "Farmers' Market"
+   :donairs "Donairs"
+   :ethnicmarkets "Ethnic Food"
+   :chocolate "Chocolatiers & Shops"
+   :delicatessen "Delicatessen"
+   :coffee "Coffee & Tea"
+   :convenience "Convenience Stores"
+   :breweries "Breweries"
+   :fooddeliveryservices "Food Delivery Services"
+   :cheese "Cheese Shops"
+   :gourmet "Specialty Food"
+   :juicebars "Juice Bars & Smoothies"
+   :meats "Meat Shops"
+   :streetvendors "Street Vendors"
+   :foodtrucks "Food Trucks"
+   :diyfood "Do-It-Yourself Food"
+   :organic_stores "Organic Stores"
+   :beer_and_wine "Beer, Wine & Spirits"
+   :icecream "Ice Cream & Frozen Yogurt"
+   :internetcafe "Internet Cafes"
+   :bakeries "Bakeries"
+   :grocery "Grocery"
+   :tea "Tea Rooms"
+   :healthmarkets "Health Food Store"
+   :donuts "Doughnuts"
+   :herbsandspices "Herbs & Spices"
+   :desserts "Desserts"
+   :markets "Fruits & Veggies"})
+
+(def local
+  {:web_design "Web Design"
+   :musicproduction "Music Production Services"
+   :electronicsrepair "Electronics Repair"
+   :architects "Architects"
+   :lifecoach "Life Coach"
+   :shipping_centers "Shipping Centres"
+   :telecommunications "Telecommunications"
+   :musicinstrumentservices "Musical Instrument Services"
+   :recyclingcenter "Recycling Center"
    :publicrelations "Public Relations"
    :copyshops "Printing Services"
-   :hypnosis "Hypnosis/Hypnotherapy"
    :couriers "Couriers & Delivery Services"
-   :skincare "Skin Care"
-   :catering "Caterers"
-   :photographystores "Photography Stores & Services"
-   :donairs "Donairs"
-   :bars "Bars"
-   :afghani "Afghan"
    :selfstorage "Self Storage"
    :carpet_cleaning "Carpet Cleaning"
-   :spas "Day Spas"
+   :sewingalterations "Sewing & Alterations"
+   :snowremoval "Snow Removal"
+   :mobilephonerepair "Mobile Phone Repair"
+   :bike_repair_maintenance "Bike Repair/Maintenance"
+   :matchmakers "Matchmakers"
+   :metalfabricators "Metal Fabricators"
+   :adoptionservices "Adoption Services"
+   :reupholstery "Furniture Reupholstery"
+   :funeralservices "Funeral Services & Cemeteries"
+   :drycleaninglaundry "Dry Cleaning & Laundry"
+   :pianostores "Piano Stores"
+   :graphicdesign "Graphic Design"
+   :notaries "Notaries"
+   :appraisalservices "Appraisal Services"
+   :tenantlaw "Tenant and Eviction Law"
+   :pest_control "Pest Control"
+   :foodbanks "Food Banks"
+   :screenprinting "Screen Printing"
+   :privateinvestigation "Private Investigation"
+   :furniturerepair "Furniture Repair"
+   :childcare "Child Care & Day Care"
+   :propane "Propane"
+   :septicservices "Septic Services"
+   :nonprofit "Community Service/Non-Profit"
+   :guitarstores "Guitar Stores"
+   :vacationrentalagents "Vacation Rental Agents"
+   :homeappliancerepair "Appliances & Repair"
+   :softwaredevelopment "Software Development"
+   :junkremovalandhauling "Junk Removal & Hauling"
+   :itservices "IT Services & Computer Repair"
+   :videofilmproductions "Video/Film Production"
+   :officecleaning "Office Cleaning"
+   :shoerepair "Shoe Repair"
+   :translationservices "Translation Services"
+   :recording_studios "Recording & Rehearsal Studios"
+   :vacation_rentals "Vacation Rentals"
+   :watch_repair "Watch Repair"
+   :jewelryrepair "Jewelry Repair"
+   :marketing "Marketing"
+   :pianoservices "Piano Services"
+   :advertising "Advertising"})
+
+(def nightlife
+  {:jazzandblues "Jazz & Blues"
+   :sportsbars "Sports Bars"
+   :pubs "Pubs"
+   :bars "Bars"
    :pianobars "Piano Bars"
-   :bangladeshi "Bangladeshi"
-:poutineries "Poutineries"
-:cookingclasses "Cooking Classes"
-:chocolate "Chocolatiers & Shops"
-:gluten_free "Gluten-Free"
-:videoandgames "Videos & Video Game Rental"
-:tcm "Traditional Chinese Medicine"
-:sewingalterations "Sewing & Alterations"
-:delicatessen "Delicatessen"
-:fencing "Fencing Clubs"
-:bustours "Bus Tours"
-:photographers "Photographers"
-:daycamps "Day Camps"
-:coffee "Coffee & Tea"
-:skateshops "Skate Shops"
-:breakfast_brunch "Breakfast & Brunch"
-:uniforms "Uniforms"
-:outlet_stores "Outlet Stores"
-:chinese "Chinese"
-:massage "Massage"
-:british "British"
-:homeandgarden "Home & Garden"
-:buses "Buses"
-:roofing "Roofing"
-:snowremoval "Snow Removal"
-:gymnastics "Gymnastics"
-:discgolf "Disc Golf"
-:artsupplies "Art Supplies"
-:adultentertainment "Adult Entertainment"
-:mobilephonerepair "Mobile Phone Repair"
-:indonesian "Indonesian"
-:bike_repair_maintenance "Bike Repair/Maintenance"
-:basque "Basque"
-:convenience "Convenience Stores"
-:scottish "Scottish"
-:dimsum "Dim Sum"
-:cocktailbars "Cocktail Bars"
-:magicians "Magicians"
-:mattresses "Mattresses"
-:truck_rental "Truck Rental"
-:testprep "Test Preparation"
-:irish_pubs "Irish Pub"
-:breweries "Breweries"
-:tapasmallplates "Tapas/Small Plates"
-:maternity "Maternity Wear"
-:halal "Halal"
-:pet_sitting "Pet Boarding/Pet Sitting"
-:hawaiian "Hawaiian"
-:lebanese "Lebanese"
-:flightinstruction "Flight Instruction"
-:hottubandpool "Hot Tub & Pool"
-:fooddeliveryservices "Food Delivery Services"
-:healthretreats "Health Retreats"
-:sportgoods "Sporting Goods"
-:campgrounds "Campgrounds"
-:waterpurification "Water Purification Services"
-:auto_detailing "Auto Detailing"
-:carpetinstallation "Carpet Installation"
-:lingerie "Lingerie"
-:motorcycledealers "Motorcycle Dealers"
-:russian "Russian"
-:arcades "Arcades"
-:cheese "Cheese Shops"
-:gokarts "Go Karts"
-:hookah_bars "Hookah Bars"
-:architecturaltours "Architectural Tours"
-:latin "Latin American"
-:towing "Towing"
-:gardens "Botanical Gardens"
-:movietheaters "Cinema"
-:tires "Tires"
-:iberian "Iberian"
-:climbing "Climbing"
-:historicaltours "Historical Tours"
-:petstore "Pet Stores"
-:publicservicesgovt "Public Services & Government"
-:casinos "Casinos"
-:adoptionservices "Adoption Services"
-:weightlosscenters "Weight Loss Centres"
-:hairloss "Hair Loss Centers"
-:cabaret "Cabaret"
-:poolcleaners "Pool Cleaners"
-:festivals "Festivals"
-:furnitureassembly "Furniture Assembly"
-:aquariumservices "Aquarium Services"
-:taxservices "Tax Services"
-:hardware "Hardware Stores"
-:african "African"
-:wedding_planning "Wedding Planning"
-:guesthouses "Guest Houses"
-:psychiatrists "Psychiatrists"
-:reupholstery "Furniture Reupholstery"
-:cafes "Cafes"
-:clowns "Clowns"
-:luggage "Luggage"
-:danceclubs "Dance Clubs"
-:himalayan "Himalayan/Nepalese"
-:reststops "Rest Stops"
-:gardening "Nurseries & Gardening"
-:ukrainian "Ukrainian"
-:dogwalkers "Dog Walkers"
-:beaches "Beaches"
-:skatingrinks "Skating Rinks"
-:reiki "Reiki"
-:colombian "Colombian"
-:southafrican "South African"
-:kitchenandbath "Kitchen & Bath"
-:fabricstores "Fabric Stores"
-:funeralservices "Funeral Services & Cemeteries"
-:eventplanning "Party & Event Planning"
-:haitian "Haitian"
-:swimwear "Swimwear"
-:appliances "Appliances"
-:midwives "Midwives"
-:blinds "Shades & Blinds"
-:videographers "Videographers"
-:gourmet "Specialty Food"
-:petservices "Pet Services"
-:flowers "Flowers & Gifts"
-:carpeting "Carpeting"
-:buildingsupplies "Building Supplies"
-:dancestudio "Dance Studios"
-:senegalese "Senegalese"
-:propertymgmt "Property Management"
-:drycleaninglaundry "Dry Cleaning & Laundry"
-:toys "Toy Stores"
-:beautysvc "Beauty & Spas"
-:juicebars "Juice Bars & Smoothies"
-:videogamestores "Video Game Stores"
-:gastropubs "Gastropubs"
-:rv_dealers "RV Dealers"
-:vietnamese "Vietnamese"
-:sushi "Sushi Bars"
-:paydayloans "Cheque Cashing/Pay-day Loans"
-:pianostores "Piano Stores"
-:formalwear "Formal Wear"
-:graphicdesign "Graphic Design"
-:karaoke "Karaoke"
-:meats "Meat Shops"
-:divebars "Dive Bars"
-:swimminglessons "Swimming Lessons/Schools"
-:raw_food "Live/Raw Food"
-:fertility "Fertility"
-:streetvendors "Street Vendors"
-:turkish "Turkish"
-:thai "Thai"
-:italian "Italian"
-:diving "Diving"
-:foodtrucks "Food Trucks"
-:delis "Delis"
-:womenscloth "Women's Clothing"
-:pest_control "Pest Control"
-:screenprinting "Screen Printing"
-:privateinvestigation "Private Investigation"
-:medcenters "Medical Clinics"
-:mountainbiking "Mountain Biking"
-:sports_clubs "Sports Clubs"
-:arabian "Arabian"
-:furniturerepair "Furniture Repair"
-:bikerentals "Bike Rentals"
-:piercing "Piercing"
-:childcare "Child Care & Day Care"
-:caribbean "Caribbean"
-:parking "Parking"
-:belgian "Belgian"
-:interiordesign "Interior Design"
-:privatetutors "Private Tutors"
-:travelservices "Travel Services"
-:hostels "Hostels"
-:propane "Propane"
-:musicvideo "Music & DVDs"
-:homedecor "Home Decor"
-:lasertag "Laser Tag"
-:pizza "Pizza"
-:freediving "Free Diving"
-:soulfood "Soul Food"
-:boxing "Boxing"
-:parks "Parks"
-:adult "Adult"
-:cosmetics "Cosmetics & Beauty Supply"
-:landscaping "Landscaping"
-:seafood "Seafood"
-:dentalhygienists "Dental Hygienists"
-:windshieldinstallrepair "Windshield Installation & Repair"
-:artclasses "Art Classes"
-:vegetarian "Vegetarian"
-:batterystores "Battery Stores"
-:bbq "Barbeque"
-:bookstores "Bookstores"
-:brasseries "Brasseries"
-:organic_stores "Organic Stores"
-:hairremoval "Hair Removal"
-:septicservices "Septic Services"
-:pressurewashers "Pressure Washers"
-:peruvian "Peruvian"
-:modern_european "Modern European"
-:limos "Limos"
-:cheesesteaks "Cheesesteaks"
-:guitarstores "Guitar Stores"
-:football "Soccer"
-:makeupartists "Makeup Artists"
-:realestateagents "Real Estate Agents"
-:barbers "Barbers"
-:sextherapists "Sex Therapists"
-:brewingsupplies "Brewing Supplies"
-:investing "Investing"
-:homeappliancerepair "Appliances & Repair"
-:landmarks "Landmarks & Historical Buildings"
-:hospitals "Hospitals"
-:asianfusion "Asian Fusion"
-:mexican "Mexican"
-:austrian "Austrian"
-:pilates "Pilates"
-:home_organization "Home Organization"
-:pakistani "Pakistani"
-:carrental "Car Rental"
-:persian "Persian/Iranian"
-:windowwashing "Window Washing"
-:antiques "Antiques"
-:hospice "Hospice"
-:comfortfood "Comfort Food"
-:photoboothrentals "Photo Booth Rentals"
-:archery "Archery"
-:museums "Museums"
-:junkremovalandhauling "Junk Removal & Hauling"
-:itservices "IT Services & Computer Repair"
-:filipino "Filipino"
-:mobilehomes "Mobile Home Dealers"
-:falafel "Falafel"
-:hotels "Hotels"
-:indpak "Indian"
-:videofilmproductions "Video/Film Production"
-:mini_golf "Mini Golf"
-:fishnchips "Fish & Chips"
-:taichi "Tai Chi"
-:salvadoran "Salvadoran"
-:southern "Southern"
-:sledding "Sledding"
-:health "Health & Medical"
-:gaybars "Gay Bars"
-:srilankan "Sri Lankan"
-:icecream "Ice Cream & Frozen Yogurt"
-:cajun "Cajun/Creole"
-:skiing "Skiing"
-:fondue "Fondue"
-:chimneysweeps "Chimney Sweeps"
-:gutterservices "Gutter Services"
-:golfequipment "Golf Equipment"
-:cabinetry "Cabinetry"
-:christmastrees "Christmas Trees"
-:egyptian "Egyptian"
-:internetcafe "Internet Cafes"
-:homehealthcare "Home Health Care"
-:badminton "Badminton"
-:pet_training "Pet Training"
-:bakeries "Bakeries"
-:tapas "Tapas Bars"
-:employmentagencies "Employment Agencies"
-:skishops "Ski & Snowboard Shops"
-:grocery "Grocery"
-:hair "Hair Salons"
-:autorepair "Auto Repair"
-:shoerepair "Shoe Repair"
-:korean "Korean"
-:translationservices "Translation Services"
-:tea "Tea Rooms"
-:skydiving "Skydiving"
-:dog_parks "Dog Parks"
-:masonry_concrete "Masonry/Concrete"
-:eyelashservice "Eyelash Service"
-:autoglass "Auto Glass Services"
-:tobaccoshops "Tobacco Shops"
-:wine_bars "Wine Bars"
-:brazilian "Brazilian"
-:contractors "Contractors"
-:ramen "Ramen"
-:vacation_rentals "Vacation Rentals"
-:medicalspa "Medical Spas"
-:healthmarkets "Health Food Store"
-:vintage "Used, Vintage & Consignment"
-:rvrental "RV Rental"
-:fireplace "Fireplace Services"
-:tutoring "Tutoring Centres"
-:moroccan "Moroccan"
-:hvac "Heating & Air Conditioning/HVAC"
-:german "German"
-:homestaging "Home Staging"
-:mongolian "Mongolian"
-:salad "Salad"
-:donuts "Doughnuts"
-:realestate "Real Estate"
-:giftshops "Gift Shops"
-:cuban "Cuban"
-:creperies "Creperies"
-:vinyl_records "Vinyl Records"
-:car_dealers "Car Dealers"
-:australian "Australian"
-:singaporean "Singaporean"
-:greek "Greek"
-:baby_gear "Baby Gear & Furniture"
-:sailing "Sailing"
-:buddhist_temples "Buddhist Temples"
-:venezuelan "Venezuelan"
-:bodyshops "Body Shops"
-:optometrists "Optometrists"
-:chicken_wings "Chicken Wings"
-:martialarts "Martial Arts"
-:thrift_stores "Thrift Stores"
-:hometheatreinstallation "Home Theatre Installation"
-:costumes "Costumes"
-:hats "Hats"
-:foodstands "Food Stands"
-:insulationinstallation "Insulation Installation"
-:slovakian "Slovakian"
-:watch_repair "Watch Repair"
-:herbsandspices "Herbs & Spices"
-:wholesale_stores "Wholesale Stores"
-:spanish "Spanish"
-:media "Books, Mags, Music & Video"
-:drugstores "Drugstores"
-:jewelryrepair "Jewelry Repair"
-:french "French"
-:menscloth "Men's Clothing"
-:sandwiches "Sandwiches"
-:cambodian "Cambodian"
-:sportswear "Sports Wear"
-:hifi "High Fidelity Audio Equipment"
-:mediterranean "Mediterranean"
-:deptstores "Department Stores"
-:comedyclubs "Comedy Clubs"
-:hindu_temples "Hindu Temples"
-:comicbooks "Comic Books"
-:steak "Steakhouses"
-:hungarian "Hungarian"
-:vet "Veterinarians"
-:laotian "Laotian"
-:walkingtours "Walking Tours"
-:tex-mex "Tex-Mex"
-:poolhalls "Pool Halls"
-:pawn "Pawn Shops"
-:desserts "Desserts"
-:partysupplies "Party Supplies"
-:polish "Polish"
-:paintball "Paintball"
-:pianoservices "Piano Services"
-:soup "Soup"
-:poolbilliards "Pool & Billiards"
-:stucco "Stucco Services"
-:knittingsupplies "Knitting Supplies"
-:gardeners "Gardeners"})
+   :adultentertainment "Adult Entertainment"
+   :cocktailbars "Cocktail Bars"
+   :irish_pubs "Irish Pub"
+   :hookah_bars "Hookah Bars"
+   :danceclubs "Dance Clubs"
+   :champagne_bars "Champagne Bars"
+   :lounges "Lounges"
+   :karaoke "Karaoke"
+   :divebars "Dive Bars"
+   :gaybars "Gay Bars"
+   :wine_bars "Wine Bars"
+   :musicvenues "Music Venues"
+   :comedyclubs "Comedy Clubs"
+   :poolhalls "Pool Halls"})
+
+(def categories
+  {:restaurants restaurants
+   :shopping shopping
+   :food food
+   :local local
+   :nightlife nightlife})


inline let

inline let

--- src/zombie_run/quil.clj
+++ src/zombie_run/quil.clj
@@ -75,8 +75,7 @@
                          (q/no-stroke)                      ; cell border color
                          (q/text-size 20)

-                         (let [game @game]
-                           (display-game game)))
+                         (display-game @game))
                  :setup (fn []
                           (q/frame-rate 20))                ; Set FPS
                  :key-pressed (fn []


Fix curator exists test.

Fix curator exists test.

--- test/onyx/log/curator_test.clj
+++ test/onyx/log/curator_test.clj
@@ -68,12 +68,11 @@

         (facts "Deleted value"
                (fact
-                 (cu/data client "/ab") => (throws Exception)))
+                 (cu/data client3 "/ab2") => (throws Exception)))

         (facts "Check exists after delete"
-               (fact (cu/exists client3 "/ab2") => nil)))))
-
+               (fact (cu/exists client3 "/ab2") => nil))
+
+        (cu/close client3))))
     (finally
       (onyx.api/shutdown-env env))))
-
-


Revert "Improve escaping ANSI codes"

Revert "Improve escaping ANSI codes"

This reverts commit c4361041b7764d264c0bb3e0da91792b9f074a23.

--- src/net/sekao/nightcode/utils.clj
+++ src/net/sekao/nightcode/utils.clj
@@ -121,7 +121,7 @@
   (str/escape s {\return ""}))

 (defn remove-ansi [^String s]
-  (str/replace s #"\e\[\d*." ""))
+  (str/replace s #"\e\[\d*m" ""))

 (defn get-boot-path []
   (let [windows? (.startsWith (System/getProperty "os.name") "Windows")


improve a test #29

improve a test #29

--- test/tamaki/post/post_test.clj
+++ test/tamaki/post/post_test.clj
@@ -1,8 +1,10 @@
 (ns tamaki.post.post-test
   (:require [clojure.test :refer :all]
             [clojure.java.io :as io]
+            [me.raynes.fs :as rfs]
             [tamaki.post.post :as post]))

 (deftest loading-posts
   (testing "find the post files "
-    (is (some? (post/post-seq (io/file "dev-resources/tamaki/post"))))))+    (let [filenames (map #(rfs/base-name %)  (post/post-seq (io/file "dev-resources/tamaki/post")))]
+      (is (= #{"post.md" "childpost.md"} (set filenames))))))


Add primitive types and tuples

Add primitive types and tuples

--- src/clojure/clojurewerkz/cassaforte/new_query_api.clj
+++ src/clojure/clojurewerkz/cassaforte/new_query_api.clj
@@ -5,7 +5,8 @@
             Select$Selection Select Select$Where
             BindMarker
             Clause]
-           [com.datastax.driver.core.querybuilder ]))
+           [com.datastax.driver.core TupleType DataType]
+           ))

 ;;
 ;; Static QB Methods
@@ -99,6 +100,45 @@
        query-builder
        construct))))

+;;
+;; Tuples
+;;
+
+(def primitive-types
+  {:ascii     (DataType/ascii)
+   :bigint    (DataType/bigint)
+   :blob      (DataType/blob)
+   :boolean  (DataType/cboolean)
+   :counter   (DataType/counter)
+   :decimal   (DataType/decimal)
+   :double   (DataType/cdouble)
+   :float    (DataType/cfloat)
+   :inet      (DataType/inet)
+   :int      (DataType/cint)
+   :text      (DataType/text)
+   :timestamp (DataType/timestamp)
+   :uuid      (DataType/uuid)
+   :varchar   (DataType/varchar)
+   :varint    (DataType/varint)
+   :timeuuid  (DataType/timeuuid)})
+
+(defn list-type
+  [primitive-type]
+  (DataType/list (get primitive-types primitive-type)))
+
+(defn set-type
+  [primitive-type]
+  (DataType/set (get primitive-types primitive-type)))
+
+(defn map-type
+  [key-type value-type]
+  (DataType/map (get primitive-types key-type)
+                (get primitive-types value-type)))
+
+(defn tuple-of
+  [types values]
+  (.newValue (TupleType/of (into-array (map #(get primitive-types %) types)))
+             (object-array values)))

 ;;
 ;; Columns


Implement create keyspace

Implement create keyspace

--- src/clojure/clojurewerkz/cassaforte/new_query_api.clj
+++ src/clojure/clojurewerkz/cassaforte/new_query_api.clj
@@ -594,4 +594,39 @@
                    ((get renderers statement-name) builder statement-args))
                  (DropKeyspace. (name keyspace-name)))
          (maybe-stringify))))
+
+(def ^:private create-keyspace-options
+  {:replication    (fn [opts replication] (.replication opts replication))
+   :durable-writes (fn [opts durable-writes] (.durableWrites opts durable-writes))})
+
+(defn resolve-create-keyspace-option
+  [option-name]
+  (if-let [res (get create-keyspace-options option-name)]
+    res
+    (throw (IllegalArgumentException. (str "Create Keyspace option "
+                                           " was not found, pick one of ("
+                                           (clojure.string/join "," (keys create-keyspace-options))
+                                           ")")))))
+
+(let [order
+      {:if-not-exists 1
+       :with-options  2}
+      renderers
+      {:with-options  (fn with-options-statement [query-builder options]
+                        (reduce
+                         (fn [opts [option-name option-vals]]
+                           ((resolve-create-keyspace-option option-name) opts option-vals))
+                         (.withOptions query-builder)
+                         options))
+       :if-not-exists (fn if-not-exists-query [query-builder _]
+                        (.ifNotExists query-builder))}]
+  (defn create-keyspace
+    [keyspace-name & statements]
+    (->> statements
+         (sort-by #(get order (first %)))
+         (reduce (fn [builder [statement-name statement-args]]
+                   ((get renderers statement-name) builder statement-args))
+                 (CreateKeyspace. (name keyspace-name)))
+         (maybe-stringify))))
+
 (def ? (QueryBuilder/bindMarker))


Swap to using `:id`  instead of `:name`   (I thought I done this earlier)

--- src/re_frame/interceptor.cljc
+++ src/re_frame/interceptor.cljc
@@ -18,12 +18,12 @@

 (defn ->interceptor
   "Create an interceptor from named arguements"
-  [& {:as m :keys [name id before after]}]      ;; remove `name` in due course - only in there as a backwards compat thing
+  [& {:as m :keys [name id before after]}]      ;; XXX remove `name` in due course - only in there as a backwards compat thing
   (when debug-enabled?
-    (if name
+    (if name                                    ;; XXX remove in due course
       (console :warn  "re-frame.core/->interceptor no longer takes `:name` - has been renamed to `:id`. Please change for " name))
     (if-let [unknown-keys  (seq (clojure.set/difference
-                             (-> (dissoc m :name) keys set)         ;; XXX temporarily take out name
+                             (-> (dissoc m :name) keys set)         ;; XXX take out name in due course
                              mandatory-interceptor-keys))]
       (console :error "re-frame: ->interceptor " m " has unknown keys: " unknown-keys)))
   {:id     (or id name :unnamed)     ;; XXX remove `name` in due course


minor: adapt test to new logic

minor: adapt test to new logic

--- ssclj/jar/src/test/clojure/com/sixsq/slipstream/ssclj/usage/state_machine_test.clj
+++ ssclj/jar/src/test/clojure/com/sixsq/slipstream/ssclj/usage/state_machine_test.clj
@@ -14,5 +14,5 @@
   (leads-to :started :start :severe-wrong-transition)
   (leads-to :started :stop  :close-record)

-  (leads-to :stopped :start :reset-end)
+  (leads-to :stopped :start :insert-start)
   (leads-to :stopped :stop  :severe-wrong-transition))


CMR-1761: Fix indentation

CMR-1761: Fix indentation

--- system-int-test/test/cmr/system_int_test/search/collection_spatial_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/collection_spatial_search_test.clj
@@ -273,9 +273,9 @@
             :south -90
             :east 10
             :north 90} [whole-world on-np on-sp wide-north wide-south polygon-with-holes
-                            normal-poly normal-brs north-pole south-pole normal-point
-                            very-wide-cart wide-north-cart wide-south-cart normal-poly-cart
-                            polygon-with-holes-cart]
+                        normal-poly normal-brs north-pole south-pole normal-point
+                        very-wide-cart wide-north-cart wide-south-cart normal-poly-cart
+                        polygon-with-holes-cart]

            ;; crosses am
            [166.11,-19.14,-166.52,53.04] [whole-world across-am-poly across-am-br am-point
@@ -284,7 +284,7 @@
             :south -19.14
             :east -166.52
             :north 53.04} [whole-world across-am-poly across-am-br am-point
-                                          very-wide-cart along-am-line]
+                           very-wide-cart along-am-line]
            ;; Matches geodetic line
            [17.67,-6.94,25.56,-4] [whole-world normal-line]
            {:west 17.67


response implemented

response implemented

--- src/NoteHub/handler.clj
+++ src/NoteHub/handler.clj
@@ -42,8 +42,8 @@
   containing the markdown text (to keep all chars unescaped)"
   ([cls input] (md-node cls {} input))
   ([cls opts input]
-  [(keyword (str (name cls) ".markdown")) opts
-   [:textarea input]]))
+   [(keyword (str (name cls) ".markdown")) opts
+    [:textarea input]]))

 (when-not (storage/valid-publisher? "NoteHub")
   (storage/register-publisher "NoteHub"))
@@ -77,9 +77,10 @@
   "Sets a custom message for each needed HTTP status.
   The message to be assigned is extracted with a dynamically generated key"
   [code]
-  (let [message (get-message (keyword (str "status-" code)))]
-    (layout message
-            [:article [:h1 message]])))
+  {:status code
+   :body (let [message (get-message (keyword (str "status-" code)))]
+           (layout message
+                   [:article [:h1 message]]))})

 (defn redirect [url]
   {:status 302
@@ -93,7 +94,7 @@
 (defroutes api-routes

   (GET "/" [] (layout (get-message :api-title)
-               (md-node :article (slurp "API.md"))))
+                      (md-node :article (slurp "API.md"))))

   (GET "/note" [version noteID]
        (generate-string (api/get-note noteID)))
@@ -205,7 +206,7 @@
             (response 500))))

   (route/resources "/")
-  (route/not-found "Not Found"))
+  (route/not-found (response 404)))

 (def app
   (handler/site app-routes))


Revert "Fixup stray parens"

Revert "Fixup stray parens"

This reverts commit c9d666f6b982a7020510447024475dde613837f2.

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -736,7 +736,9 @@
                          (map (fn [url] [:a {:href url} "#"
                                          (let [n (re-find #"/\d+$" url)]
                                            (if n (subs n 1) "?"))])
-                              urls))]))]
+                              urls))]))
+               ]
+

             [:tr
              [:th "Author"]
@@ -750,7 +752,10 @@
                         (if-not (:committer_email build)
                           [:span (build-model/committer build)]
                           [:a {:href (str "mailto:" (:committer_email build))}
-                           (build-model/committer build)])]))]]]
+                           (build-model/committer build)])]))]
+
+              ]]
+

             [:div.build-actions
              (when (has-scope :write-settings data)


handle loading, empty, and logged-out states

--- src-cljs/frontend/components/doc_viewer.cljs
+++ src-cljs/frontend/components/doc_viewer.cljs
@@ -4,6 +4,7 @@
             [cljs-time.core :as time]
             [datascript :as d]
             [frontend.async :refer [put!]]
+            [frontend.auth :as auth]
             [frontend.components.common :as common]
             [frontend.datascript :as ds]
             [frontend.state :as state]
@@ -37,8 +38,63 @@
      (time/after? time (time/minus start-of-day (time/days 14))) "last week"
      :else "a while ago")))

+(defn signup-prompt [app owner]
+  (reify
+    om/IRender
+    (render [_]
+      (let [cast! (om/get-shared owner :cast!)]
+        (html
+         [:div.menu-prompt {:class (str "menu-prompt-" "username")}
+          [:div.menu-header
+           [:a.menu-close {:on-click #(cast! :overlay-closed)
+                           :role "button"}
+            (common/icon :times)]]
+          [:div.menu-prompt-body
+           [:h2 "Don't lose your creations"]
+           [:p
+            "Log in or sign up to view all of the docs you created."]
+           [:a.prompt-button {:href (auth/auth-url)
+                              :role "button"
+                              :on-click #(do
+                                           (.preventDefault %)
+                                           (cast! :track-external-link-clicked
+                                                  {:path (auth/auth-url)
+                                                   :event "Signup Clicked"
+                                                   :properties {:source "your-docs-overlay"}}))}
+            "Sign Up"]]
+          [:div.menu-footer
+           [:a.menu-footer-link {:on-click #(do
+                                              (.preventDefault %)
+                                              (cast! :overlay-closed))
+                                 :role "button"}
+            "No thanks."]]])))))

-(defn doc-viewer [app owner]
+(defn docs-list [docs owner]
+  (reify
+    om/IRender
+    (render [_]
+      (html
+       [:div
+        (for [[time-bucket bucket-docs]
+              (reverse (sort-by #(:last-updated-instant (first (last %)))
+                                (group-by #(date->bucket (:last-updated-instant %)) docs)))]
+          (list*
+           (html [:div.recent-time-group
+                  [:h2 time-bucket]])
+
+           (for [doc bucket-docs]
+             (html
+              [:div.recent-doc
+               [:a.recent-doc-thumb {:href (str "/document/" (:db/id doc))}
+                [:img {:src (str "/document/" (:db/id doc) ".svg")}]]
+               [:a.recent-doc-title {:href (str "/document/" (:db/id doc))}
+                (str (:db/id doc))]]))))]))))
+
+(defn dummy-docs [current-doc-id doc-count]
+  (repeat doc-count {:db/id current-doc-id
+                     :last-update-instant (js/Date.)}))
+
+(defn doc-viewer* [app owner]
   (reify
     om/IRender
     (render [_]
@@ -46,7 +102,16 @@
             touched-docs (get-in app [:cust :touched-docs])
             ;; Not showing created for now, since we haven't been storing that until recently
             created-docs (get-in app [:cust :created-docs])
-            docs (take 100 (reverse (sort-by :last-updated-instant (filter :last-updated-instant touched-docs))))]
+            docs (cond
+                  (nil? touched-docs)
+                  (dummy-docs (:document/id app) 5) ;; loading state
+                  (empty? touched-docs) (dummy-docs (:document/id app) 1) ;; empty state
+                  :else
+                  (->> touched-docs
+                       (filter :last-updated-instant)
+                       (sort-by :last-updated-instant)
+                       (reverse)
+                       (take 100)))]
         (html
          [:div.menu-prompt {:class (str "menu-prompt-" "doc-viewer")}
           [:div.menu-header
@@ -55,17 +120,22 @@
            [:a.menu-close {:on-click #(cast! :overlay-closed)
                            :role "button"}
             (common/icon :times)]]
-          [:div.menu-prompt-body
-           (for [[time-bucket bucket-docs]
-                 (reverse (sort-by #(:last-updated-instant (first (last %)))
-                                   (group-by #(date->bucket (:last-updated-instant %)) docs)))]
-             (list*
-              [:div.recent-time-group
-               [:h2 time-bucket]]
+          [:div.menu-prompt-body {:class (when (nil? touched-docs)
+                                           "loading")}
+           (if (seq docs)
+             (om/build docs-list docs))]])))))

-              (for [doc bucket-docs]
-                [:div.recent-doc
-                 [:a.recent-doc-thumb {:href (str "/document/" (:db/id doc))}
-                  [:img {:src (str "/document/" (:db/id doc) ".svg")}]]
-                 [:a.recent-doc-title {:href (str "/document/" (:db/id doc))}
-                  (str (:db/id doc))]])))]])))))
+;; Four states
+;; 1. Logged out
+;; 2. Loading
+;; 3. No docs
+;; 4. Docs!
+
+(defn doc-viewer [app owner]
+  (reify
+    om/IRender
+    (render [_]
+      (if (:cust app)
+        (om/build doc-viewer* app) ;; states 2, 3, 4
+        (om/build signup-prompt app) ;; state 1
+        ))))


Get binding, grid pad display working.

Get binding, grid pad display working.

--- src/afterglow/controllers/launchpad_mini.clj
+++ src/afterglow/controllers/launchpad_mini.clj
@@ -43,9 +43,14 @@
   "The color of buttons that are completely off."
   0x0c)

+(def button-dimmed-color
+  "The color of buttons that can be pressed but are in conflict or
+  otherwise backgrounded."
+  0x1d)
+
 (def button-available-color
   "The color of buttons that can be pressed but haven't yet been."
-  0x1d)
+  0x2e)

 (def button-active-color
   "The color of an available button that is currently being pressed."
@@ -79,6 +84,111 @@
   synchronized and a beat is not taking place."
   0x1c)

+(defn set-pad-color
+  "Set one of the 64 grid pads to one of the color values specified
+  above."
+  [controller x y color]
+  (midi/midi-note-on (:port-out controller) (+ x (- 112 (* y 16))) color))
+
+(defn set-control-button-color
+  "Set one of the top row of control buttons to one of the color
+  values specified above."
+  [controller button color]
+  (midi/midi-control (:port-out controller) button color))
+
+(defn- move-origin
+  "Changes the origin of the controller, notifying any registered
+  listeners."
+  [controller origin]
+  (when (not= origin @(:origin controller))
+    (reset! (:origin controller) origin)
+    (doseq [f @(:move-listeners controller)] (f @(:grid-controller-impl controller) :moved))))
+
+
+
+(defn clear-interface
+  "Clears all illuminated buttons and pads."
+  [controller]
+  (midi/midi-control (:port-out controller) 0 0)
+  (midi/midi-control (:port-out controller) 0 1)
+  (reset! (:last-grid-pads controller) nil)
+  (reset! (:last-control-buttons controller) {}))
+
+
+
+
+(defn- midi-received
+  "Called whenever a MIDI message is received while the controller is
+  active; checks if it came in on the right port, and if so, decides
+  what should be done."
+  [controller message]
+  #_(when (amidi/same-device? (:device message) (:port-in controller))
+    ;;(timbre/info message)
+    (when-not (controllers/overlay-handled? (:overlays controller) message)
+      (when (= (:command message) :control-change)
+        (control-change-received controller message))
+      (when (= (:command message) :note-on)
+        (note-on-received controller message))
+      (when (= (:command message) :note-off)
+        (note-off-received controller message)))))
+
+
+
+
+
+(defn deactivate
+  "Deactivates a controller interface, killing its update thread and
+  removing its MIDI listeners. If `:disconnected` is passed with a
+  `true` value, it means that the controller has already been removed
+  from the MIDI environment, so no effort will be made to clear its
+  display or take it out of User mode.
+
+  You can also pass a watcher object created by [[auto-bind]] as
+  `controller`; this will both deactivate the controller being managed
+  by the watcher, if it is currently connected, and cancel the
+  watcher itself. In such cases, `:disconnected` is meaningless."
+  [controller & {:keys [disconnected] :or {disconnected false}}]
+  {:pre [(#{:launchpad-mini :launchpad-mini-watcher} (type controller))]}
+  (if (= (type controller) :launchpad-mini-watcher)
+    (do ((:cancel controller))  ; Shut down the watcher
+        (when-let [watched-controller @(:controller controller)]
+          (deactivate watched-controller)))  ; And deactivate the controller it was watching for
+    (do ;; We were passed an actual controller, not a watcher, so deactivate it.
+      (swap! (:task controller) (fn [task]
+                                  (when task (at-at/kill task))
+                                  nil))
+      (show/unregister-grid-controller @(:grid-controller-impl controller))
+      (doseq [f @(:move-listeners controller)] (f @(:grid-controller-impl controller) :deactivated))
+      (reset! (:move-listeners controller) #{})
+      (amidi/remove-global-handler! @(:midi-handler controller))
+
+      (when-not disconnected
+        (Thread/sleep 35) ; Give the UI update thread time to shut down
+        (clear-interface controller)
+        ;; Leave the User button bright, in case the user has Live
+        ;; running and wants to be able to see how to return to it.
+        (set-control-button-color controller (:user-mode control-buttons) button-available-color))
+
+      ;; Cancel any UI overlays which were in effect
+      (reset! (:overlays controller) (controllers/create-overlay-state))
+
+      ;; And finally, note that we are no longer active.
+      (swap! active-bindings dissoc (:id controller)))))
+
+(defn deactivate-all
+  "Deactivates all controller bindings which are currently active.
+  This will be regustered as a shutdown hook to be called when the
+  Java environment is shutting down, to clean up gracefully."
+  []
+  (doseq [[_ controller] @active-bindings]
+    (deactivate controller)))
+
+(defonce ^{:doc "Deactivates any Launchpad Mini bindings when Java is shutting down."
+           :private true}
+  shutdown-hook
+  (let [hook (Thread. deactivate-all)]
+    (.addShutdownHook (Runtime/getRuntime) hook)
+    hook))

 (defn- valid-identity
   "Checks that the device we are trying to bind to reports the proper
@@ -91,3 +201,166 @@
     (if (= (take 5 (drop 4 (:data ident))) '(0 32 41 54 0))
       (aget (:data ident) 1)
       (timbre/error "Device does not identify as a Launchpad Mini:" port-in))))
+
+(defn bind-to-show
+  "Establish a connection to the Novation Launchpad Mini, for managing
+  the given show.
+
+  Makes sure it identifies as a Launchpad Mini, then initializes the
+  display and starts the UI updater thread. Since SysEx messages are
+  required for communicating with it, if you are on a Mac, you must
+  install [CoreMIDI4J](https://github.com/DerekCook/CoreMidi4J) to
+  provide a working implementation. (If you need to work with Java
+  1.6, you can instead
+  use [mmj](http://www.humatic.de/htools/mmj.htm), but that is no
+  longer developed, and does not support connecting or disconnecting
+  MIDI devices after Java has started.)
+
+  If you have more than one Launchpad Mini connected, or have renamed
+  how it appears in your list of MIDI devices, you need to supply a
+  value after `:device-filter` which identifies the ports to be used
+  to communicate with the Launchpad you want this function to use. The
+  values returned by [[afterglow.midi/open-inputs-if-needed!]]
+  and [[afterglow.midi/open-outputs-if-needed!]] will be searched, and
+  the first port that matches with [[filter-devices]] will be used.
+
+  The controller will be identified in the user interface (for the
+  purposes of linking it to the web cue grid) as \"Launchpad Mini\".
+  If you would like to use a different name (for example, if have more
+  than one Launchpad), you can pass in a custom value after
+  `:display-name`.
+
+  If you want the user interface to be refreshed at a different rate
+  than the default of fifteen times per second, pass your desired
+  number of milliseconds after `:refresh-interval`.
+
+  If you would like to skip the startup animation (for example because
+  the device has just powered on and run its own animation), pass
+  `true` after `:skip-animation`."
+  [show & {:keys [device-filter refresh-interval display-name skip-animation]
+           :or   {device-filter    "Mini"
+                  refresh-interval (/ 1000 15)
+                  display-name     "Launchpad Mini"}}]
+  {:pre [(some? show)]}
+  (let [port-in  (first (amidi/filter-devices device-filter (amidi/open-inputs-if-needed!)))
+        port-out (first (amidi/filter-devices device-filter (amidi/open-outputs-if-needed!)))]
+    (if (and (every? some? [port-in port-out]) (valid-identity port-in port-out))
+      (let [shift-mode (atom false)
+            controller
+            (with-meta
+              {:id                   (swap! controller-counter inc)
+               :display-name         display-name
+               :show                 show
+               :origin               (atom [0 0])
+               :refresh-interval     refresh-interval
+               :port-in              port-in
+               :port-out             port-out
+               :task                 (atom nil)
+               :last-control-buttons (atom {})
+               :next-control-buttons (atom {})
+               :last-grid-pads       (atom nil)
+               :next-grid-pads       (atom nil)
+               :shift-mode           shift-mode
+               :stop-mode            (atom false)
+               :midi-handler         (atom nil)
+               :tempo-tap-handler    (tempo/create-show-tempo-tap-handler show :shift-fn (fn [] @shift-mode))
+               :last-marker          (atom nil)
+               :overlays             (controllers/create-overlay-state)
+               :move-listeners       (atom #{})
+               :grid-controller-impl (atom nil)}
+              {:type :launchpad-mini})]
+        (reset! (:midi-handler controller) (partial midi-received controller))
+        (reset! (:grid-controller-impl controller)
+                (reify controllers/IGridController
+                  (display-name [this] (:display-name controller))
+                  (physical-height [this] 8)
+                  (physical-width [this] 8)
+                  (current-bottom [this] (@(:origin controller) 1))
+                  (current-bottom [this y] (move-origin controller (assoc @(:origin controller) 1 y)))
+                  (current-left [this] (@(:origin controller) 0))
+                  (current-left [this x] (move-origin controller (assoc @(:origin controller) 0 x)))
+                  (add-move-listener [this f] (swap! (:move-listeners controller) conj f))
+                  (remove-move-listener [this f] (swap! (:move-listeners controller) disj f))))
+        (clear-interface controller)
+        #_(if skip-animation
+          (start-interface controller)
+          (welcome-animation controller))
+        (swap! active-bindings assoc (:id controller) controller)
+        (show/register-grid-controller @(:grid-controller-impl controller))
+        (amidi/add-disconnected-device-handler! port-in #(deactivate controller :disconnected true))
+        controller)
+      (timbre/error "Unable to find Launchpad Mini" (amidi/describe-device-filter device-filter)))))
+
+(defn auto-bind
+  "Watches for a Novation Launchpad Mini controller to be connected,
+  and as soon as it is, binds it to the specified show
+  using [[bind-to-show]]. If that controller ever gets disconnected,
+  it will be re-bound once it reappears. Returns a watcher structure
+  which can be passed to [[deactivate]] if you would like to stop it
+  watching for reconnections. The underlying controller mapping, once
+  bound, can be accessed through the watcher's `:controller` key.
+
+  If you have more than one Launchpad Mini that might beconnected, or
+  have renamed how it appears in your list of MIDI devices, you need
+  to supply a value after `:device-filter` which identifies the ports
+  to be used to communicate with the Launchpad you want this function
+  to use. The values returned
+  by [[afterglow.midi/open-inputs-if-needed!]]
+  and [[afterglow.midi/open-outputs-if-needed!]] will be searched, and
+  the first port that matches using [[filter-devices]] will be used.
+
+  Once bound, the controller will be identified in the user
+  interface (for the purposes of linking it to the web cue grid) as
+  \"Launchpad Pro\". If you would like to use a different name (for
+  example, if you have more than one Launchpad), you can pass in a
+  custom value after `:display-name`.
+
+  If you want the user interface to be refreshed at a different rate
+  than the default of fifteen times per second, pass your desired
+  number of milliseconds after `:refresh-interval`."
+  [show & {:keys [device-filter refresh-interval display-name]
+           :or {device-filter "Mini"
+                refresh-interval (/ 1000 15)
+                display-name "Launchpad Mini"}}]
+  {:pre [(some? show)]}
+  (let [idle (atom true)
+        controller (atom nil)]
+    (letfn [(disconnection-handler []
+              (reset! controller nil)
+              (reset! idle true))
+            (connection-handler
+              ([device]
+               (connection-handler device true))
+              ([device wait-for-boot]
+               (when (compare-and-set! idle true false)
+                 (if (and (nil? @controller) (seq (amidi/filter-devices device-filter [device])))
+                   (let [port-in (first (amidi/filter-devices device-filter (amidi/open-inputs-if-needed!)))
+                         port-out (first (amidi/filter-devices device-filter (amidi/open-outputs-if-needed!)))]
+                     (when (every? some? [port-in port-out])  ; We found our Launchpad! Bind to it in the background.
+                       (timbre/info "Auto-binding to Launchpad Mini" device)
+                       (future
+                         (when wait-for-boot (Thread/sleep 3000)) ; Allow for firmware's own welcome animation
+                         (reset! controller (bind-to-show show :device-filter device-filter
+                                                          :refresh-interval refresh-interval
+                                                          :display-name display-name
+                                                          :skip-animation wait-for-boot))
+                         (amidi/add-disconnected-device-handler! (:port-in @controller) disconnection-handler))))
+                   (reset! idle true)))))
+            (cancel-handler []
+              (amidi/remove-new-device-handler! connection-handler)
+              (when-let [device (:port-in @controller)]
+                (amidi/remove-disconnected-device-handler! device disconnection-handler)))]
+
+      ;; See if our Launchpad seems to already be connected, and if so, bind to it right away.
+      (when-let [found (first (amidi/filter-devices device-filter (amidi/open-inputs-if-needed!)))]
+        (connection-handler found false))
+
+      ;; Set up to bind when connected in future.
+      (amidi/add-new-device-handler! connection-handler)
+
+      ;; Return a watcher object which can provide access to the bound controller, and be canceled later.
+      (with-meta
+        {:controller controller
+         :device-filter device-filter
+         :cancel cancel-handler}
+        {:type :launchpad-mini-watcher}))))


after leaving a group, redirect away

after leaving a group, redirect away

--- src/braid/ui/views/pages/group_settings.cljs
+++ src/braid/ui/views/pages/group_settings.cljs
@@ -4,7 +4,8 @@
             [chat.client.dispatcher :refer [dispatch!]]
             [chat.client.reagent-adapter :refer [subscribe]]
             [chat.client.s3 :as s3]
-            [chat.client.store :as store]))
+            [chat.client.store :as store]
+            [chat.client.routes :as routes]))

 (defn leave-group-view
   [group]
@@ -14,7 +15,8 @@
                             (when (js/confirm "Are you sure you want to leave this group?")
                               (dispatch! :remove-from-group
                                          {:group-id (group :id)
-                                          :user-id @user-id})))}
+                                          :user-id @user-id})
+                              (routes/go-to! (routes/index-path))))}
        "Leave this group"])))

 (defn intro-message-view


use deftype

use deftype

--- src/cljx/jamesmacaulay/async_tools/core.cljx
+++ src/cljx/jamesmacaulay/async_tools/core.cljx
@@ -11,7 +11,7 @@
             [cljs.core.async.impl.channels :as channels])
   (:require-macros [cljs.core.async.macros :refer [go]]))

-(defrecord ConstantReadPort [boxed-value]
+(deftype ConstantReadPort [boxed-value]
   impl/ReadPort
   (take! [_ _] boxed-value))

@@ -19,7 +19,7 @@
   [x]
   (ConstantReadPort. (channels/box x)))

-(defrecord AsyncFuture [state-atom]
+(deftype AsyncFuture [state-atom]
   impl/ReadPort
   (take! [_ handler]
     (-> state-atom


(PDB-5022) puppetdb-command->metadata-command: create via map-invert

--- src/puppetlabs/puppetdb/queue.clj
+++ src/puppetlabs/puppetdb/queue.clj
@@ -7,14 +7,15 @@
            [java.nio.file Files LinkOption]
            [java.nio.file.attribute FileAttribute]
            [org.apache.commons.compress.compressors.gzip GzipCompressorInputStream])
-  (:require [clojure.string :as str :refer [re-quote-replacement]]
-            [puppetlabs.stockpile.queue :as stock]
+  (:require [clojure.set :as set]
+            [clojure.string :as str :refer [re-quote-replacement]]
             [clojure.tools.logging :as log]
             [puppetlabs.i18n.core :refer [trs tru]]
             [puppetlabs.puppetdb.cheshire :as json]
             [puppetlabs.puppetdb.command.constants :as command-constants]
             [puppetlabs.puppetdb.constants :as constants]
             [puppetlabs.puppetdb.lint :refer [ignore-value]]
+            [puppetlabs.stockpile.queue :as stock]
             [metrics.timers :refer [timer time!]]
             [metrics.counters :refer [inc!]]
             [puppetlabs.kitchensink.core :as kitchensink]
@@ -45,7 +46,7 @@
    "set-expire" "configure expiration"})

 (def puppetdb-command->metadata-command
-  (into {} (for [[md pdb] metadata-command->puppetdb-command] [pdb md])))
+  (set/map-invert metadata-command->puppetdb-command))

 (defn stream->json [^InputStream stream]
   (try


add-tiles-at

add-tiles-at

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

--- plugins/SlideExplorer2/src/slide_explorer/main.clj
+++ plugins/SlideExplorer2/src/slide_explorer/main.clj
@@ -150,14 +150,22 @@
     (acquire-at (Point2D$Double. x y)))
   ([^Point2D$Double stage-pos]
     (let [xy-stage (core getXYStageDevice)]
-      (time (set-xy-position stage-pos))
-      (time (core waitForDevice xy-stage))
-      (time (processor-sequence)))))
+      (set-xy-position stage-pos)
+      (core waitForDevice xy-stage)
+      (processor-sequence))))

 (defn origin-here-stage-to-pixel-transform []
   (set-destination-origin
     (get-stage-to-pixel-transform)
     (.getXYStagePosition gui)))
+
+(defn add-tiles-at [available-tiles [nx ny] affine-stage-to-pixel]
+  (doseq [image (acquire-at (inverse-transform (Point. (* 512 nx) (* 512 ny)) affine-stage-to-pixel))]
+    (add-to-available-tiles available-tiles
+                            {:nx nx :ny ny :nz (get-in image [:tags "SliceIndex"]) :nt 0
+                             :nc (get-in image [:tags "Channel"])}
+                            (image :proc))))
+

 (defn go []
   (core waitForDevice (core getXYStageDevice))
@@ -173,12 +181,8 @@
                                :nc (get-in image [:tags "Channel"])}
                               (image :proc)))
     (swap! ss assoc :channels (initial-lut-objects first-seq))
-    (doseq [image (time (acquire-at (inverse-transform (Point. 0 -512) affine-stage-to-pixel)))]
-      (add-to-available-tiles available-tiles
-                              {:nx 0 :ny -1 :nz (get-in image [:tags "SliceIndex"]) :nt 0
-                               :nc (get-in image [:tags "Channel"])}
-                              (image :proc)))
-    ))
+    (doseq [tile [[-1 -1] [-1 0] [-1 1] [0 -1] [0 1] [1 -1] [1 0] [1 -1]]]
+      (add-tiles-at available-tiles tile affine-stage-to-pixel))))


Create ES index per team

Create ES index per team

--- webapp/src/org/teamweek/webapp/endpoint/team.clj
+++ webapp/src/org/teamweek/webapp/endpoint/team.clj
@@ -1,6 +1,7 @@
 (ns org.teamweek.webapp.endpoint.team
   (:require [clojure.string :as str]
             [clojure.set :as set]
+            [clojure.java.io :as io]
             [compojure.core :refer :all]
             [ring.util.response :refer :all]
             [ring.middleware.flash :refer [flash-response]]
@@ -112,6 +113,8 @@
              (if (:domain team-data)
                (do
                  (create-team conn token team-data)
+                 ;; TODO remove hardcoded ES_URI
+                 (http/put (str "http://localhost:9200/" (:domain team-data)) {:body (slurp (io/resource "mappings.json"))})
                  (->
                    (redirect "/team")
                    (assoc-in [:session "teamweek-token"] token)))


added minor changes to tests for rubrics, for clarity

--- test/simple_symbolic_regression_clojure/core_test.clj
+++ test/simple_symbolic_regression_clojure/core_test.clj
@@ -172,8 +172,8 @@
                    rubric (->Rubric {:x 17} 5)]
                (score-on script rubric) => 14)
              (let [script [2 :x +]
-                   rubric (->Rubric {:x 7, :y 17} 5)]
-               (score-on script rubric) => 4)
+                   rubric (->Rubric {:x -7, :y 17} 5)]
+               (score-on script rubric) => 10)
              )
        )

@@ -182,12 +182,12 @@
              (let [script [2 4 +]
                    rubrics [(->Rubric {} 0) (->Rubric {} 1)
                             (->Rubric {} -1) (->Rubric {} 4)]]
-               (total-score-on script rubrics) => 20))
+               (total-score-on script rubrics) => (+ 6 5 7 2)))
        (fact "when the script has a single variable"
              (let [script [2 :x *]
                    rubrics [(->Rubric {:x 0} 0) (->Rubric {:x 1} 1)
                             (->Rubric {:x -1} -1) (->Rubric {:x 3} 4)]]
-               (total-score-on script rubrics) => 4))
+               (total-score-on script rubrics) => (+ 0 1 1 2)))
        (fact "when the script has a two variables"
              (let [script [:y :x *]
                    rubrics [(->Rubric {:x 0, :y 0} 0) (->Rubric {:x 1, :y -1} 1)


use assoc-in! and truncate results

use assoc-in! and truncate results

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -7,7 +7,7 @@
    #?(:cljs [babel.logjs :as log])
    [clojure.math.combinatorics :as combo]
    [clojure.string :as string]
-   [dag_unify.core :refer [assoc-in copy fail-path get-in fail? strip-refs unify unify!]]))
+   [dag_unify.core :refer [assoc-in assoc-in! copy fail-path get-in fail? strip-refs unify unify!]]))

 ;; during generation, will not decend deeper than this when creating a tree:
 ;; TODO: should also be possible to override per-language.
@@ -89,16 +89,20 @@

 (declare add-bolt-at)

-
-(defn do-assocs [accum paths val-at-paths]
+(defn do-assocs [accum paths val-at-paths model]
   (if (empty? paths)
     accum
     (do-assocs
-     (assoc-in accum
-               (first paths)
-               (first val-at-paths))
+     (let [result
+           (assoc-in! accum
+                      (first paths)
+                      (first val-at-paths))]
+       (if (not (empty? (first paths)))
+         (dag_unify.core/dissoc-paths result [(first paths)] model)
+         result))
      (rest paths)
-     (rest val-at-paths))))
+     (rest val-at-paths)
+     model)))

 (defn nugents [model spec & [max-depth]]
   (log/debug (str "nugents:" (strip-refs spec)))
@@ -113,9 +117,12 @@
                          trellis)))
                 mapping1)]
     (map (fn [good-one]
-           (do-assocs (get good-one [])
-                      (keys good-one)
-                      (vals good-one)))
+           (do-defaults
+            (do-assocs (get good-one [])
+                       (keys good-one)
+                       (vals good-one)
+                       model)
+            model))
          all-of-them)))

 (defn add-bolts-to-path [path bolts-at bolt top-bolt model depth max-depth truncate? take-n]


Decrease the sleep between server restart.

--- test/catacumba/core_tests.clj
+++ test/catacumba/core_tests.clj
@@ -32,7 +32,7 @@
        ~@body
        (finally
          (.stop server#)
-         (Thread/sleep 200)))))
+         (Thread/sleep 50)))))

 (def base-url "http://localhost:5050")


add tests for defui statics

add tests for defui statics

--- test/cellophane/core_test.clj
+++ test/cellophane/core_test.clj
@@ -10,9 +10,20 @@
   (render [this]
     (dom/div nil "Hello World")))

+(defui ComponentWithStatics
+  static om/Ident
+  (ident [this props]
+    [:by-id 42])
+  static om/IQuery
+  (query [this]
+    [:foo]))
+
 (deftest test-defui
   (testing "defui definition works"
     (is SimpleComponent))
   (testing "defui implements Lifecycle protocols"
-    (is (= (.initLocalState SimpleComponent) {:foo 1}))))
+    (is (= (.initLocalState SimpleComponent) {:foo 1})))
+  (testing "defui implements statics"
+    (is (= (.query ComponentWithStatics) [:foo]))
+    (is (= (.ident ComponentWithStatics {}) [:by-id 42]))))


fixed incorrect binding types

fixed incorrect binding types

--- src/caesium/binding.clj
+++ src/caesium/binding.clj
@@ -137,8 +137,8 @@
       ^bytes ^{Pinned {}} in
       ^long ^{LongLong {}} inlen
       ^bytes ^{Pinned {}} k]]
-    [^void crypto_shorthash_keygen
-     [^bytes ^{Pinned {}} k]]
+    [^int crypto_shorthash_keygen
+     [^long ^{LongLong {}} k]]

     [^long ^{size_t {}} crypto_sign_bytes []]
     [^long ^{size_t {}} crypto_sign_seedbytes []]


reshape `componentWillMount`

reshape `componentWillMount`

--- src/cellophane/next.clj
+++ src/cellophane/next.clj
@@ -318,12 +318,25 @@
                      cellophane.next/*shared*     (cellophane.next/shared this#)
                      cellophane.next/*instrument* (cellophane.next/instrument this#)
                      cellophane.next/*parent*     this#]
-            ~@body))))}
+             (let [ret# (do ~@body)
+                   props# (cellophane.protocols/-props this#)]
+               (when-not @(:cellophaneclj$mounted? props#)
+                     (swap! (:cellophaneclj$mounted? props#) not))
+               ret#)))))
+    'componentWillMount
+    (fn [[name [this :as args] & body]]
+      `(~name [this#]
+         (let [~this    this#
+               indexer# (get-in (cellophane.next/get-reconciler this#) [:config :indexer])]
+           (when-not (nil? indexer#)
+             (om.next.protocols/index-component! indexer# this#))
+           ~@body)))}
    :defaults
    `{~'componentWillMount
-     ([this#])
-     ~'componentDidMount
-     ([this#])
+     ([this#]
+       (let [indexer# (get-in (cellophane.next/get-reconciler this#) [:config :indexer])]
+         (when-not (nil? indexer#)
+           (om.next.protocols/index-component! indexer# this#))))
      ~'render
      ([this#])}})

@@ -347,7 +360,6 @@
               dt))]
     (->> dt (map reshape*) vec add-object-protocol add-defaults)))

-;; TODO: probably need to reshape dt to implement defaults
 (defn defui* [name forms]
   (let [{:keys [dt statics]} (collect-statics forms)
         [other-protocols obj-dt] (split-with (complement '#{Object}) dt)
@@ -376,8 +388,6 @@

                   cellophane.protocols/IReactComponent
                   (~'-render [this#]
-                   (when-not @(:cellophaneclj$mounted? props#)
-                     (swap! (:cellophaneclj$mounted? props#) not))
                    (p/componentWillMount this#)
                    (p/render this#))
                   (~'-props [this]


fix ArrayIter

fix ArrayIter

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -2886,11 +2886,11 @@
 (defn string-iter [x]
   (StringIter. x 0))

-(deftype ArrayIter [s ^:mutable i]
+(deftype ArrayIter [arr ^:mutable i]
   Object
-  (hasNext [_] (< i (alength s)))
+  (hasNext [_] (< i (alength arr)))
   (next [_]
-    (let [ret (.aget s i)]
+    (let [ret (aget arr i)]
       (set! i (inc i))
       ret))
   (remove [_] (js/Error. "Unsupported operation")))