Improve sending user-list implementation.

--- src/tranjlator/chat_room.clj
+++ src/tranjlator/chat_room.clj
@@ -12,6 +12,11 @@
   [user history]
   (go (doseq [h history]
         (>! user h))))
+
+(defn send-user-list
+  [user user-list]
+  (go (doseq [[name _] user-list]
+        (>! user (msg/->user-join name)))))

 (def ^:const +user-default-topics+ #{:original :user-join :user-part})

@@ -60,8 +65,7 @@
                          (log/infof "JOIN: %s" (pr-str msg))
                          (if-not (nil? msg)
                            (do (>! sender msg)
-                               (doseq [[name _] users]
-                                 (>! sender (msg/->user-join name)))
+                               (send-user-list sender users)
                                (send-history sender history)
                                (recur (assoc users user-name (sub-user pub user-name sender +user-default-topics+)) history))
                            (log/warn "ChatRoom shutting down due to \"user-join\" channel closing")))


added back a dependency in the project namespace

--- src-cljs/frontend/models/project.cljs
+++ src-cljs/frontend/models/project.cljs
@@ -1,7 +1,8 @@
 (ns frontend.models.project
   (:require [clojure.string :refer [lower-case split join]]
             [frontend.utils :as utils :include-macros true]
-            [goog.string :as gstring]))
+            [goog.string :as gstring]
+            [frontend.models.plan :as plan-model]))

 (defn project-name [project]
   (->> (split (:vcs_url project) #"/")


CMR-2078: Bumped to use full release due to nexus issues with SNAPSHOTs.

--- common-lib/project.clj
+++ common-lib/project.clj
@@ -18,7 +18,7 @@
     [clj-time "0.14.2"]
     [clojail "1.0.6"]
     [clojurewerkz/quartzite "2.1.0"]
-    [clojusc/ltest "0.3.0-SNAPSHOT"]
+    [clojusc/ltest "0.3.0"]
     [com.dadrox/quiet-slf4j "0.1"]
     [com.gfredericks/test.chuck "0.2.8"]
     [com.github.fge/json-schema-validator "2.2.6"]


Enables heterogenous params in DistributionCreator.

--- src/clojure/uncomplicate/bayadera/internal/impl.clj
+++ src/clojure/uncomplicate/bayadera/internal/impl.clj
@@ -14,7 +14,7 @@
             [uncomplicate.fluokitten.core :refer [op]]
             [uncomplicate.neanderthal
              [vect-math :refer [sqrt!]]
-             [core :refer [transfer dim vspace?]]]
+             [core :refer [transfer transfer! dim vspace? subvector vctr]]]
             [uncomplicate.neanderthal.internal.api :as na]
             [uncomplicate.bayadera.util :refer [srand-int]]
             [uncomplicate.bayadera.internal.protocols :refer :all])
@@ -117,7 +117,7 @@

 (defmacro ^:private with-params-check [model params & body]
   `(if (= (params-size ~model) (if (vspace? ~params) (dim ~params) (count ~params)))
-     ~@body
+     (do ~@body)
      (dragan-says-ex "Dimension of params must match the distribution."
                      {:required (params-size ~model) :supplied (dim ~params)})))

@@ -131,9 +131,11 @@
     (with-params-check (model dist-eng) params
       (->DistributionImpl factory dist-eng sampler-factory (transfer factory params))))
   (invoke [this data hyperparams]
-    (with-release [params (op data hyperparams)]
+    (let-release [params (vctr factory (+ (dim data) (dim hyperparams)))]
       (with-params-check (model dist-eng) hyperparams
-        (->DistributionImpl factory dist-eng sampler-factory (transfer factory params)))))
+        (transfer! data (subvector params 0 (dim data)))
+        (transfer! hyperparams (subvector params (dim data) (dim hyperparams)))
+        (->DistributionImpl factory dist-eng sampler-factory params))))
   ModelProvider
   (model [_]
     (model dist-eng)))


Remove bootstrap.clj :flushed:

Remove bootstrap.clj :flushed:

--- test/metabase/bootstrap.clj
+++ test/metabase/bootstrap.clj
@@ -1,59 +0,0 @@
-(ns metabase.bootstrap
-  "Functions for creating new Orgs/Users from the command-line / REPL."
-  (:require [metabase.db :refer :all]
-            (metabase.models [database :refer [Database]]
-                             [user :refer [User]])
-            [metabase.test.data :refer :all]))
-
-(declare bootstrap-user
-         prompt-read-line
-         prompt-read-line-boolean)
-
-;; # BOOTSTRAPPING
-
-(defn bootstrap
-  "Create a `User` for development purposes.
-   You may optionally load the test data."
-  []
-  (setup-db :auto-migrate true)
-  (let [{:keys [email]} (bootstrap-user)]
-    (println (format "Successfully created User \"%s\"." email))))
-
-
-;; # (INTERNAL)
-
-(defn- bootstrap-user
-  "Create a new User."
-  []
-  (let [email (prompt-read-line "User email" "cam@metabase.com")
-        ;; create User if needed
-        user (or (sel :one User :email email)
-                 (ins User
-                      :email email
-                      :first_name (prompt-read-line "User first name" "Cam")
-                      :last_name (prompt-read-line "User last name" "Saul")
-                      :is_superuser (prompt-read-line-boolean "Make this user a superuser?" "true")
-                      :password (prompt-read-line "User password" "password")))]
-    user))
-
-(defn- prompt-read-line
-  "Prompt for input from stdin with PROMPT, returning DEFAULT if user hits return. Optionally, recurse until the returned value is in set VALID-VALUES."
-  ([prompt default]
-   (println prompt (str "[\"" default "\"]:"))
-   (let [line (read-line)]
-     (if (empty? line) default
-         line)))
-  ([prompt default valid-values]
-   {:pre [(set? valid-values)]}
-   (let [val (prompt-read-line prompt default)]
-     (if (contains? valid-values val) val
-         (do (println "Must be one of:" (map str valid-values))
-             (recur prompt default valid-values))))))
-
-(defn- prompt-read-line-boolean
-  "Prompt user for true/false and return a boolean."
-  [prompt default]
-  {:pre [(contains? #{"true" "false"} default)]}
-  (case (prompt-read-line prompt default #{"true" "false"})
-    "true" true
-    "false" false))


Fix catbytes (a test helper function).

Fix catbytes (a test helper function).

It was written with dependencies on the system's default character encoding,
and wound up working only on OSX.

Only tests were affected; the actual functionality worked all along.

--- test/protobuf/core_test.clj
+++ test/protobuf/core_test.clj
@@ -8,7 +8,14 @@
 (def ErrorMsg (protodef protobuf.test.Core$ErrorMsg))

 (defn catbytes [& args]
-  (.getBytes (apply str (map (fn [#^bytes b] (String. b)) args))))
+  (let [out-buf (byte-array (reduce + (map count args)))]
+    (loop [offset 0, args args]
+      (if-let [[^bytes array & more] (seq args)]
+        (let [size (count array)]
+          (System/arraycopy array 0
+                            out-buf offset size)
+          (recur (+ size offset) more))
+        out-buf))))

 (deftest test-conj
   (let [p (protobuf Foo :id 5 :tags ["little" "yellow"] :doubles [1.2 3.4 5.6] :floats [0.01 0.02 0.03])]


fix tests

fix tests

--- test/protobuf/core_test.clj
+++ test/protobuf/core_test.clj
@@ -207,7 +207,7 @@
                 :long      {:type :float},
                 :deleted   {:type :boolean}}]
     (is (= fields (protofields Foo)))
-    (is (= fields (protofields protobuf.core.Test$Foo)))))
+    (is (= fields (protofields protobuf.test.Core$Foo)))))

 (deftest test-nested-protofields
   (is (= {:year   {:type :int},
@@ -236,7 +236,7 @@
   (is (= {}    (protodefault Foo :groups)))
   (is (= {}    (protodefault Foo :item-map)))
   (is (= false (protodefault Foo :deleted)))
-  (is (= {}    (protodefault protobuf.core.Test$Foo :groups))))
+  (is (= {}    (protodefault protobuf.test.Core$Foo :groups))))

 (deftest test-use-underscores
   (let [p (protobuf Foo {:tag_set ["odd"] :responses [:yes :not-sure :maybe :not-sure :no]})]


Added gameplay/swap-skat tests

Added gameplay/swap-skat tests

--- test/skat/gameplay_test.clj
+++ test/skat/gameplay_test.clj
@@ -3,8 +3,28 @@
             [skat]
             [skat.gameplay :refer :all])
   (:import  [skat Bidding
+                  Player
                   Configuration
                   GameDriver]))
+
+(def c1 (Card. :kreuz :W))
+(def c2 (Card. :kreuz :K))
+(def c3 (Card. :schell :W))
+(def c4 (Card. :kreuz :A))
+(def c5 (Card. :kreuz :10))
+(def c6 (Card. :schell :A))
+(def c7 (Card. :schell :10))
+(def c8 (Card. :schell :K))
+(def deal { :front '(c1 c2), :middle '(c3 c4), :rear '(c5 c6), :skat '(c7 c8) })
+(defn create-player [pid]
+  (reify Player
+         (id [_] pid)
+         (skat-swapping [_ _ cards skat-card] (if (= skat-card c7)
+                                                (first cards)
+                                                (first (rest cards))))))
+(def pl1 (create-player "p1"))
+(def pl2 (create-player "p2"))
+(def pl3 (create-player "p3"))

 (deftest perform-auction-test
   (testing "auction eventually end with bidding"
@@ -20,3 +40,21 @@
     (testing "declaration eventually ends"
       (is (= config-true (declare-game driver-true {})))
       (is (= config-false (declare-game driver-false {}))))))
+
+(deftest swap-skat-test
+  (testing "hand leaves deal intact"
+    (let [config (Configuration. pl1 :grand true false false false false 18)]
+      (is (= deal (swap-skat config deal pl1)))))
+  (testing "no hand swaps at most 2 cards"
+    (let [config (Configuration. pl1 :grand false false false false false 18)]
+      (is (= { :front '(c7 c8)
+               :middle '(c3 c4)
+               :rear '(c5 c6)
+               :skat '(c1 c2) }
+             deal (swap-skat config deal pl1))))))
+
+(deftest play-deal-test)
+
+(deftest deal-end2end-test)
+
+(deftest start-game)


Added reducers, transducers, and pmap examples.

--- src/main/cljc/clojure_club/playground/mbastian.cljc
+++ src/main/cljc/clojure_club/playground/mbastian.cljc
@@ -1,5 +1,9 @@
 (ns clojure-club.playground.mbastian
-  (:require [clojure.core.reducers :as r]))
+  (:require [clojure.core.reducers :as r]
+            [taoensso.tufte :as tufte :refer (defnp p profiled profile)]))
+
+(defn slow-range [n delay] (map (fn [i] (fn [] (Thread/sleep delay) i)) (range n)))
+(defn slow-rangev [n delay] (mapv (fn [i] (fn [] (Thread/sleep delay) i)) (range n)))

 (defn work-proxy [input]  (Thread/sleep input)  1)

@@ -7,6 +11,48 @@

 (defn counter [thunk]
   (thunk))
+
+;Plain old threading
+(defn baseline [limit delay]
+  (->> (slow-range limit delay) (map counter) (map inc) (filter odd?) (reduce +)))
+
+;pmap
+(defn baseline+pmap [limit delay]
+  (->> (slow-range limit delay) (pmap counter) (map inc) (filter odd?) (reduce +)))
+
+;Not reduced since it's not in a vec
+(defn slow-range-reducer [limit delay]
+  (->> (slow-range limit delay) (r/map counter) (r/map inc) (r/filter odd?) (r/fold 8 + +)))
+
+;Reduced since it's in a vec
+(defn slow-rangev-reducer [limit delay]
+  (->> (slow-rangev limit delay) (r/map counter) (r/map inc) (r/filter odd?) (r/fold 8 + +)))
+
+(def rxf #(->> % (r/map counter) (r/map inc) (r/filter odd?)))
+
+(defn slow-rangev-reducer-pipe [limit delay]
+  (->> (slow-rangev limit delay) rxf (r/fold 8 + +)))
+
+;Transducers compose pipelines
+(def xf
+  (comp (map counter) (map inc) (filter odd?)))
+
+;This is not executed in parallel. When would I transduce vs. reduce?
+(defn slow-rangev-transducer [limit delay]
+  (transduce xf + (slow-rangev limit delay)))
+
+(tufte/add-basic-println-handler! {})
+#_(profile
+  {:dynamic? true}
+  (let [samples 40 delay 100]
+    (dotimes [_ 5]
+      (p :baseline (do (baseline samples delay)))
+      (p :baseline+pmap (do (baseline+pmap samples delay)))
+      ;(p :slow-range-reducer (do (slow-range-reducer samples delay)))
+      ;(p :slow-rangev-reducer (do (slow-rangev-reducer samples delay)))
+      (p :slow-rangev-reducer-pipe (do (slow-rangev-reducer-pipe samples delay)))
+      ;(p :slow-rangev-transducer (do (slow-rangev-transducer samples delay)))
+      )))

 ;Think of work proxy as set amount of calculation we want to do.
 ;What I was trying to do was get the reducers to run each thunk in parallel.
@@ -23,6 +69,8 @@
         vec
         ;(r/take limit)
         (r/map counter)
+        (r/map inc)
+        (r/filter odd?)
         (r/fold 8 + +)
         ))

@@ -41,3 +89,11 @@
        (take limit)
        (map counter)
        (reduce +)))
+
+;Transducers - non-parallel?
+(def xf2
+  (comp
+    (take 40)
+    (map counter)
+    (map inc)))
+;(time (transduce xf2 + (repeat work-proxy-thunk)))


Bring back a whole bunch of range tests

Bring back a whole bunch of range tests

--- test/clojure/clojurewerkz/cassaforte/cql_test.clj
+++ test/clojure/clojurewerkz/cassaforte/cql_test.clj
@@ -309,120 +309,103 @@
                  (where {:username "Alex"})
                  (order-by (new-query-api/desc :post_id))))))

-;; (deftest test-select-range-query
-;;   (create-table s :tv_series
-;;                 (column-definitions {:series_title  :varchar
-;;                                      :episode_id    :int
-;;                                      :episode_title :text
-;;                                      :primary-key   [:series_title :episode_id]}))
-;;   (dotimes [i 20]
-;;     (insert s :tv_series {:series_title "Futurama" :episode_id i :episode_title (str "Futurama Title " i)})
-;;     (insert s :tv_series {:series_title "Simpsons" :episode_id i :episode_title (str "Simpsons Title " i)}))
-
-;;   (is (= (set (range 11 20))
-;;          (->> (select s :tv_series
-;;                       (where [[= :series_title "Futurama"]
-;;                               [> :episode_id 10]]))
-;;               (map :episode_id )
-;;               set)))
-
-;;   (is (= (set (range 11 16))
-;;          (->> (select s :tv_series
-;;                       (where [[=  :series_title "Futurama"]
-;;                               [>  :episode_id 10]
-;;                               [<= :episode_id 15]]))
-;;               (map :episode_id)
-;;               set)))
-
-;;   (is (= (set (range 0 15))
-;;          (->> (select s :tv_series
-;;                       (where [[= :series_title "Futurama"]
-;;                               [< :episode_id 15]]))
-;;               (map :episode_id)
-;;               set)))
-
-;;   (drop-table s :tv_series))
-
-;; (deftest test-timeuuid-now-and-unix-timestamp-of
-;;   (create-table s :events
-;;                 (column-definitions {:message      :varchar
-;;                                      :created_at   :timeuuid
-;;                                      :primary-key  [:created_at]}))
-
-;;   (let [dt (-> 2 seconds ago)
-;;         ts (cc/to-long dt)]
-;;     (dotimes [i 20]
-;;       (insert s :events {:created_at (fns/now) :message (format "Message %d" i)}))
-;;     (let [xs  (select s :events
-;;                       (columns (fns/unix-timestamp-of :created_at))
-;;                       (limit 5))
-;;           ts' (get (first xs) (keyword "unixTimestampOf(created_at)"))]
-;;       (is (> ts' ts))))
-
-;;   (drop-table s :events))
-
-;; (deftest test-timeuuid-dateof
-;;   (create-table s :events
-;;                 (column-definitions {:message      :varchar
-;;                                      :created_at   :timeuuid
-;;                                      :primary-key  [:created_at]}))
-
-;;   (let [dt (-> 2 seconds ago)]
-;;     (dotimes [i 20]
-;;       (insert s :events {:created_at (fns/now) :message (format "Message %d" i)}))
-;;     (let [xs  (select s :events
-;;                       (columns (fns/date-of :created_at))
-;;                       (limit 5))
-;;           dt' (cc/from-date (get (first xs) (keyword "dateOf(created_at)")))]
-;;       (is (before? dt dt'))))
-
-;;   (drop-table s :events))
-
-;; (deftest test-timeuuid-min-open-range-query
-;;   (create-table s :events
-;;                 (column-definitions {:message      :varchar
-;;                                      :city         :varchar
-;;                                      :created_at   :timeuuid
-;;                                      :primary-key  [:message :created_at]}))
-;;   (create-index s :events :created_at)
-;;   (dotimes [i 10]
-;;     (let [dt (date-time 2014 11 17 23 i)]
-;;       (insert s :events {:created_at (uuids/start-of (cc/to-long dt))
-;;                          :city       "London, UK"
-;;                          :message    (format "Message %d" i)})))
-;;   (let [xs  (select s :events
-;;                     (where [[:in :message ["Message 7" "Message 8" "Message 9" "Message 10"]]
-;;                             [>= :created_at (-> (date-time 2014 11 17 23 8)
-;;                                                 .toDate
-;;                                                 fns/min-timeuuid)]]))]
-;;     (is (= #{"Message 8" "Message 9"}
-;;            (set (map :message xs)))))
-
-;;   (drop-table s :events))
-
-;; (deftest test-timeuuid-min-max-timeuuid-range-query
-;;   (create-table s :events
-;;                 (column-definitions {:message      :varchar
-;;                                      :created_at   :timeuuid
-;;                                      :primary-key  [:message :created_at]}))
-;;   (create-index s :events :created_at)
-;;   (dotimes [i 10]
-;;     (let [dt (date-time 2014 11 17 23 i)]
-;;       (insert s :events {:created_at (uuids/start-of (cc/to-long dt))
-;;                          :message    (format "Message %d" i)})))
-;;   (let [xs  (select s :events
-;;                     (where [[:in :message ["Message 5" "Message 6" "Message 7"
-;;                                            "Message 8" "Message 9"]]
-;;                             [>= :created_at (-> (date-time 2014 11 17 23 6)
-;;                                                 .toDate
-;;                                                 fns/min-timeuuid)]
-;;                             [<= :created_at (-> (date-time 2014 11 17 23 8)
-;;                                                 .toDate
-;;                                                 fns/max-timeuuid)]]))]
-;;     (is (= #{"Message 6" "Message 7" "Message 8"}
-;;            (set (map :message xs)))))
-
-;;   (drop-table s :events))
+(deftest test-select-range-query
+  (create-table *session* :tv_series
+                (column-definitions {:series_title  :varchar
+                                     :episode_id    :int
+                                     :episode_title :text
+                                     :primary-key   [:series_title :episode_id]}))
+  (dotimes [i 20]
+    (insert *session* :tv_series
+            {:series_title  "Futurama"
+             :episode_id    i
+             :episode_title (str "Futurama Title " i)})
+    (insert *session* :tv_series
+            {:series_title  "Simpsons"
+             :episode_id    i
+             :episode_title (str "Simpsons Title " i)}))
+
+  (is (= (set (range 11 20))
+         (->> (select *session* :tv_series
+                      (where [[= :series_title "Futurama"]
+                              [> :episode_id 10]]))
+              (map :episode_id )
+              set)))
+
+  (is (= (set (range 11 16))
+         (->> (select *session* :tv_series
+                      (where [[=  :series_title "Futurama"]
+                              [>  :episode_id 10]
+                              [<= :episode_id 15]]))
+              (map :episode_id)
+              set)))
+
+  (is (= (set (range 0 15))
+         (->> (select *session* :tv_series
+                      (where [[= :series_title "Futurama"]
+                              [< :episode_id 15]]))
+              (map :episode_id)
+              set)))
+
+  (drop-table *session* :tv_series))
+
+(deftest test-timeuuid-now-and-unix-timestamp-of
+  (let [dt (-> 2 seconds ago)
+        ts (cc/to-long dt)]
+    (dotimes [i 20]
+      (insert *session* :events
+              {:created_at (new-query-api/now)
+               :message    (format "Message %d" i)}))
+    (let [xs  (select *session* :events
+                      (new-query-api/unix-timestamp-of :created_at)
+                      (limit 5))
+          ts' (get (first xs) (keyword "unixTimestampOf(created_at)"))]
+      (is (> ts' ts)))))
+
+(deftest test-timeuuid-dateof
+  (let [dt (-> 2 seconds ago)]
+    (dotimes [i 20]
+      (insert *session* :events
+              {:created_at (new-query-api/now)
+               :message (format "Message %d" i)}))
+    (let [xs  (select *session* :events
+                      (new-query-api/date-of :created_at)
+                      (limit 5))
+          dt' (cc/from-date (get (first xs) (keyword "dateOf(created_at)")))]
+      (is (before? dt dt')))))
+
+(deftest test-timeuuid-min-open-range-query
+  (dotimes [i 10]
+    (let [dt (date-time 2014 11 17 23 i)]
+      (insert *session* :events_for_in_and_range_query
+              {:created_at (uuids/start-of (cc/to-long dt))
+               :city       "London, UK"
+               :message    (format "Message %d" i)})))
+  (let [xs  (select *session* :events_for_in_and_range_query
+                    (where [[:in :message ["Message 7" "Message 8" "Message 9" "Message 10"]]
+                            [>= :created_at (-> (date-time 2014 11 17 23 8)
+                                                .toDate
+                                                new-query-api/min-timeuuid)]]))]
+    (is (= #{"Message 8" "Message 9"}
+           (set (map :message xs))))))
+
+(deftest test-timeuuid-min-max-timeuuid-range-query
+  (dotimes [i 10]
+    (let [dt (date-time 2014 11 17 23 i)]
+      (insert *session* :events_for_in_and_range_query
+              {:created_at (uuids/start-of (cc/to-long dt))
+               :message    (format "Message %d" i)})))
+  (let [xs  (select *session* :events_for_in_and_range_query
+                    (where [[:in :message ["Message 5" "Message 6" "Message 7"
+                                           "Message 8" "Message 9"]]
+                            [>= :created_at (-> (date-time 2014 11 17 23 6)
+                                                .toDate
+                                                new-query-api/min-timeuuid)]
+                            [<= :created_at (-> (date-time 2014 11 17 23 8)
+                                                .toDate
+                                                new-query-api/max-timeuuid)]]))]
+    (is (= #{"Message 6" "Message 7" "Message 8"}
+           (set (map :message xs))))))

 ;; (deftest test-paginate


Add print.

Add print.

--- src/clj/squad_share/interactors/list_links.clj
+++ src/clj/squad_share/interactors/list_links.clj
@@ -7,6 +7,7 @@
 (defn run!
   [context]
   (let [ result (<!! (pg/execute! config/db ["select title, url, description from squadshare.links"])) ]
+    (prn result)
     (result :rows)
   )
 )


Remove debugging code

Remove debugging code

--- src/braid/client/ui/views/thread.cljs
+++ src/braid/client/ui/views/thread.cljs
@@ -244,7 +244,6 @@
               [:button {:on-click (fn [e]
                                     (reset! permalink-open? false))}
                "Done"]])
-           [:div (str (thread :id))]
            (when (not new?)
              [:div.controls
               (if @open?


adding computed user provided values

adding computed user provided values

--- src/celestial/persistency/actions.clj
+++ src/celestial/persistency/actions.clj
@@ -2,14 +2,33 @@
   "Actions persistency"
   (:refer-clojure :exclude  [name type])
   (:require
+    [clojure.string :refer (join escape)]
+    [celestial.model :refer (figure-rem)]
     [slingshot.slingshot :refer  [throw+]]
     [subs.core :as subs :refer (validate!)]
     [clojure.core.strint :refer (<<)]
     [puny.core :refer (entity)]))

-(declare unique-name)
+(declare unique-name with-provided)

-(entity action :indices [operates-on] :intercept {:create [unique-name]})
+(entity action :indices [operates-on] :intercept {:create [unique-name with-provided] :update [with-provided]})
+
+(defn- args-of [s]
+  "grab args from string"
+  (map #(escape % {\~ "" \{ "" \} ""}) (re-seq #"~\{\w+\}" s)))
+
+(defn remoter [action]
+  (get action (figure-rem action)))
+
+(defn add-provided [action]
+  "appends action expected arguments drived from args strings"
+   (assoc action :provided (remove #{"target"} (args-of (join " " ((remoter action) :args))))))
+
+(defn with-provided [f & [a1 a2 & r :as args]]
+  (cond
+    (map? a1) (apply f (add-provided a1) r)
+    (map? a2) (apply f a1 (add-provided a2) r)
+    :else (apply f args)))

 (defn find-action-for [name type]
   (let [ids (get-action-index :operates-on type)
@@ -32,13 +51,3 @@
     (validate! capistrano has-args :error ::invalid-cap-action))
   (validate! action action-base-validation :error ::invalid-action))

-(defn- args-of [s]
-  "grab args from string"
-  (map #(clojure.string/escape % {\~ "" \{ "" \} ""}) (re-seq #"~\{\w+\}" s)))
-
-;; (println (args-of "-S ~{target}"))
-
-(defn action-args [as]
-  "appends action expected arguments drived from args strings"
-
-  )


Fix autofocus on home page. Fixes #150

Fix autofocus on home page. Fixes #150

--- src/cljs/clojuredocs/mods/search.cljs
+++ src/cljs/clojuredocs/mods/search.cljs
@@ -137,7 +137,7 @@
             :placeholder (or placeholder "Looking for? (ctrl-s)")
             :name "q"
             :autoComplete "off"
-            :ref "input"
+            :autoFocus "autofocus"
             :value ac-text
             :on-change (fn [e]
                          (let [text (.. e -target -value)]
@@ -156,12 +156,14 @@
                                (prev-res? act) (do
                                                  (ops/send bus ::move-highlight -1)
                                                  (.preventDefault e)))))}]])
-       :did-mount (fn []
-                    #_(let [$input (om/get-node owner "input")]
-                        (when (and (not (focused? $input))
-                                   search-focused?)
-                          (.focus $input)
-                          (aset $input "value" (.-value $input)))))
+       :component-did-mount
+       (fn [this]
+         (when-let [$form (rea/dom-node this)]
+           (let [$input (dommy/sel1 $form :input.query)]
+             (when (and $input
+                        (not (focused? $input)))
+               (.focus $input)
+               (aset $input "value" (.-value $input))))))
        :did-update (fn [])
        #_(fn []
            (handle-search-active-state ac-text)


[#2437] Fix

[#2437] Fix

--- backend/src/akvo/lumen/lib/transformation/derive.clj
+++ backend/src/akvo/lumen/lib/transformation/derive.clj
@@ -11,6 +11,7 @@
             [clojure.tools.logging :as log]
             [clojure.walk :as walk]))

+(def flow-metadata-questions #{"identifier" "instance_id" "display_name" "submitter" "submitted_at" "surveyal_time" "device_id"})

 (defn row-template-format [s]
   (let [double-quote-template "row[\"%s\"]"
@@ -62,9 +63,16 @@
                                #(conj % {"id" id
                                          "pattern" pattern
                                          "column-name" (if column-ref2
-                                                         (:columnName (first (filter (fn [c]
-                                                                           (and (= column-ref1 (:groupName c))
-                                                                                (= column-ref2 (:title c)))) columns)))
+                                                         (:columnName
+                                                          (first
+                                                           (filter
+                                                            (fn [c]
+                                                              (and (or (= column-ref1 (:groupName c))
+                                                                       (and (engine/is-derivated? (:columnName c))
+                                                                            (= column-ref1 "Transformations"))
+                                                                       (and (contains? flow-metadata-questions (:columnName c))
+                                                                            (= column-ref1 "Metadata")))
+                                                                   (= column-ref2 (:title c)))) columns)))
                                                          (let [results (filter (fn [c] (= column-ref1 (:title c))) columns)]
                                                            (if (> (count results) 1)
                                                              (throw (ex-info (format "There is more than one column with this name: '%s', Js code needs to reference the column with the group. Eg: row['Transformations']['%s']" column-ref1 column-ref1)
@@ -124,15 +132,13 @@
        (map (fn [[i]] (db.tx.derive/delete-row conn (merge {:rnum i} opts))))
        doall))

-
 (defn columns-groups [columns]
   (let [groups (group-by :groupName columns)
         flow-groups (not-empty (dissoc groups nil))
         no-flow-qg (get groups  nil)
         tx-group (when-let [txs (not-empty (filter #(engine/is-derivated? (:columnName %)) no-flow-qg))]
                    {"Transformations" txs })
-        mt-questions #{"identifier" "instance_id" "display_name" "submitter" "submitted_at" "surveyal_time" "device_id"}
-        mt-group (when-let [mts (not-empty (filter #(contains? mt-questions (:columnName %)) no-flow-qg))]
+        mt-group (when-let [mts (not-empty (filter #(contains? flow-metadata-questions (:columnName %)) no-flow-qg))]
                    {"Metadata" mts})]
     (when (or flow-groups tx-group mt-group)
       (->> (merge flow-groups


Issue/361 remove transactions (#378)

Issue/361 remove transactions (#378)

* [#361] Remove transformation transactions

* [#361] Remove run-tests

--- backend/src/org/akvo/lumen/transformation/engine.clj
+++ backend/src/org/akvo/lumen/transformation/engine.clj
@@ -1,6 +1,5 @@
 (ns org.akvo.lumen.transformation.engine
-  (:require [clojure.java.jdbc :as jdbc]
-            [hugsql.core :as hugsql]
+  (:require [hugsql.core :as hugsql]
             [org.akvo.lumen.util :as util])
   (:import java.sql.SQLException))

@@ -205,7 +204,7 @@
   (deliver promise {:status "OK"
                     :jobExecutionId job-execution-id
                     :datasetVersionId dataset-version-id
-                    :datasetId dataset-id}) )
+                    :datasetId dataset-id}))

 (defn- deliver-promise-failure [promise dataset-id job-id message]
   (deliver promise {:status "FAILED"
@@ -220,33 +219,32 @@
 (defn execute-transformation
   [completion-promise tenant-conn job-id dataset-id transformation]
   (try
-    (jdbc/with-db-transaction [tx-conn tenant-conn]
-      (let [dataset-version (latest-dataset-version-by-dataset-id tx-conn {:dataset-id dataset-id})
-            columns (vec (:columns dataset-version))
-            source-table (:table-name dataset-version)]
-        (let [{:keys [success? message columns execution-log]} (apply-operation tx-conn
-                                                                                source-table
-                                                                                columns
-                                                                                transformation)]
-          (if success?
-            (let [new-dataset-version-id (str (util/squuid))]
-              (clear-dataset-version-data-table tx-conn {:id (:id dataset-version)})
-              (new-dataset-version tx-conn
-                                   {:id new-dataset-version-id
-                                    :dataset-id dataset-id
-                                    :job-execution-id job-id
-                                    :table-name source-table
-                                    :imported-table-name (:imported-table-name dataset-version)
-                                    :version (inc (:version dataset-version))
-                                    :transformations (conj (vec (:transformations dataset-version))
-                                                           transformation)
-                                    :columns columns})
-              (update-job-success-execution tenant-conn {:id job-id :exec-log (vec execution-log)})
-              (deliver-promise-success completion-promise dataset-id new-dataset-version-id job-id))
-            (execute-transformation-failed completion-promise
-                                           tenant-conn dataset-id
-                                           job-id
-                                           message)))))
+    (let [dataset-version (latest-dataset-version-by-dataset-id tenant-conn {:dataset-id dataset-id})
+          columns (vec (:columns dataset-version))
+          source-table (:table-name dataset-version)]
+      (let [{:keys [success? message columns execution-log]} (apply-operation tenant-conn
+                                                                              source-table
+                                                                              columns
+                                                                              transformation)]
+        (if success?
+          (let [new-dataset-version-id (str (util/squuid))]
+            (clear-dataset-version-data-table tenant-conn {:id (:id dataset-version)})
+            (new-dataset-version tenant-conn
+                                 {:id new-dataset-version-id
+                                  :dataset-id dataset-id
+                                  :job-execution-id job-id
+                                  :table-name source-table
+                                  :imported-table-name (:imported-table-name dataset-version)
+                                  :version (inc (:version dataset-version))
+                                  :transformations (conj (vec (:transformations dataset-version))
+                                                         transformation)
+                                  :columns columns})
+            (update-job-success-execution tenant-conn {:id job-id :exec-log (vec execution-log)})
+            (deliver-promise-success completion-promise dataset-id new-dataset-version-id job-id))
+          (execute-transformation-failed completion-promise
+                                         tenant-conn dataset-id
+                                         job-id
+                                         message))))
     (catch Exception e
       (execute-transformation-failed completion-promise
                                      tenant-conn
@@ -258,9 +256,9 @@
   (update-job-success-execution tenant-conn {:id job-id :exec-log []})
   (deliver-promise-success completion-promise dataset-id dataset-version-id job-id))

-(defn- apply-undo [completion-promise tenant-conn tx-conn job-id dataset-id current-dataset-version]
+(defn- apply-undo [completion-promise tenant-conn job-id dataset-id current-dataset-version]
   (let [imported-table-name (:imported-table-name current-dataset-version)
-        initial-columns (vec (:columns (dataset-version-by-dataset-id tx-conn
+        initial-columns (vec (:columns (dataset-version-by-dataset-id tenant-conn
                                                                       {:dataset-id dataset-id
                                                                        :version 1})))
         table-name (util/gen-table-name "ds")]
@@ -274,8 +272,8 @@
            full-execution-log []]
       (if (empty? transformations)
         (let [new-dataset-version-id (str (util/squuid))]
-          (clear-dataset-version-data-table tx-conn {:id (:id current-dataset-version)})
-          (new-dataset-version tx-conn
+          (clear-dataset-version-data-table tenant-conn {:id (:id current-dataset-version)})
+          (new-dataset-version tenant-conn
                                {:id new-dataset-version-id
                                 :dataset-id dataset-id
                                 :job-execution-id job-id
@@ -289,7 +287,7 @@
           (update-job-success-execution tenant-conn {:id job-id :exec-log full-execution-log})
           (deliver-promise-success completion-promise dataset-id new-dataset-version-id job-id))
         (let [{:keys [success? message columns execution-log]}
-              (apply-operation tx-conn table-name columns (first transformations))]
+              (apply-operation tenant-conn table-name columns (first transformations))]
           (if success?
             (recur (rest transformations) columns (into full-execution-log execution-log))
             (execute-transformation-failed completion-promise
@@ -300,22 +298,21 @@

 (defn execute-undo [completion-promise tenant-conn job-id dataset-id]
   (try
-    (jdbc/with-db-transaction [tx-conn tenant-conn]
-      (let [current-dataset-version (latest-dataset-version-by-dataset-id tx-conn
-                                                                          {:dataset-id dataset-id})
-            current-version (:version current-dataset-version)]
-        (if (= current-version 1)
-          (nothing-to-undo completion-promise
-                           tenant-conn
-                           dataset-id
-                           (:id current-dataset-version)
-                           job-id)
-          (apply-undo completion-promise
-                      tenant-conn
-                      tx-conn
-                      job-id
-                      dataset-id
-                      current-dataset-version))))
+    (let [current-dataset-version (latest-dataset-version-by-dataset-id tenant-conn
+                                                                        {:dataset-id dataset-id})
+          current-version (:version current-dataset-version)]
+      (if (= current-version 1)
+        (nothing-to-undo completion-promise
+                         tenant-conn
+                         dataset-id
+                         (:id current-dataset-version)
+                         job-id)
+        (apply-undo completion-promise
+                    tenant-conn
+                    job-id
+                    dataset-id
+                    current-dataset-version)))
+
     (catch Exception e
       (execute-transformation-failed completion-promise
                                      tenant-conn


Fix generated runner code

Fix generated runner code

--- src/clj_chrome_devtools/cljs/test.clj
+++ src/clj_chrome_devtools/cljs/test.clj
@@ -42,7 +42,7 @@
    "(defn run-chrome-tests []"
    " (set! *print-fn* (fn [& msg] (swap! PRINTED conj (apply str msg))))\n"
    " (run-tests " (str/join "\n"
-                            (map #(str "'" %) namespaces)) ")"))
+                            (map #(str "'" %) namespaces)) "))"))

 (defn with-test-runner-source [namespaces source-path fun]
   ;; Create a test runner source file in the given source path


more work on querying

more work on querying

--- ketornah-client/src/cljs/ketornah_client/sql.cljs
+++ ketornah-client/src/cljs/ketornah_client/sql.cljs
@@ -63,12 +63,14 @@
           (println result))))

 (def food-query
-  "SELECT * FROM food_summary WHERE name LIKE ")
+  "SELECT * FROM food_summary WHERE name LIKE '%s'")

-(defn search-food [db name]
-  )
+(defn search-food [db search]
+  (let [search (str/replace (str "%" search "%") " " "%")
+        query (str/format food-query search)]
+    (execute-query db query)))

 #_(let [db-channel (open-database default-db-url)]
     (go (let [db (<! db-channel)
-              result (search-food db "peanut")]
+              result (search-food db "peanut oil")]
           (println result))))


select first auto-complete result

select first auto-complete result

--- src/chat/client/views/new_message.cljs
+++ src/chat/client/views/new_message.cljs
@@ -138,7 +138,7 @@
     (init-state [_]
       {:text ""
        :force-close? false
-       :highlighted-result-index -1
+       :highlighted-result-index 0
        :results nil
        :kill-chan (chan)
        :autocomplete-chan (chan)
@@ -151,8 +151,10 @@
         (go (loop []
               (let [[v ch] (alts! [autocomplete kill-chan])]
                 (when (= ch autocomplete)
-                  (om/set-state! owner :results
-                                 (seq (mapcat (fn [e] (e v (config :thread-id))) engines)))
+                  (om/update-state! owner
+                                    #(assoc %
+                                       :results (seq (mapcat (fn [e] (e v (config :thread-id))) engines))
+                                       :highlighted-result-index 0))
                   (recur)))))))

     om/IDidMount
@@ -191,7 +193,7 @@
                                 #(mod (dec %) (count results))))
             highlight-clear!
             (fn []
-              (om/set-state! owner :highlighted-result-index -1))
+              (om/set-state! owner :highlighted-result-index 0))
             close-autocomplete!
             (fn []
               (highlight-clear!))
@@ -202,7 +204,7 @@
                                (merge s
                                       {:text ""
                                        :force-close? false
-                                       :highlighted-result-index -1}))))
+                                       :highlighted-result-index 0}))))
             send-message!
             (fn []
               (store/set-new-thread! (config :thread-id))
@@ -260,9 +262,7 @@
                                    KeyCodes.DOWN (when autocomplete-open?
                                                    (.preventDefault e)
                                                    (highlight-next!))
-                                   (when (KeyCodes.isTextModifyingKeyEvent e)
-                                     ; don't clear if a modifier key alone was pressed
-                                     (highlight-clear!))))})
+                                   nil))})

             (when autocomplete-open?
               (dom/div #js {:className "autocomplete"}


Update store

Update store

--- src/client/clojure_template/store.cljs
+++ src/client/clojure_template/store.cljs
@@ -1,6 +1,6 @@
 (ns clojure-template.store
-  (:require [re-frame.core :refer [reg-event-db debug dispatch]]))
+  (:require [re-frame.core :as rc]))

-(def interceptors [(when ^boolean js/goog.DEBUG debug)])
+(def interceptors [(when ^boolean js/goog.DEBUG rc/debug)])

-(dispatch [:initialize-db])
+(rc/dispatch [:initialize-db])


fix banner timeout again

fix banner timeout again

--- src/clj/collect_earth_online/views.clj
+++ src/clj/collect_earth_online/views.clj
@@ -40,9 +40,7 @@
 (defn js-init [page params]
   (let [js-params (json/write-str params)]
     [:script {:type "text/javascript"}
-     (str "window.onload = function () {
-           setTimeout (function () {document.getElementById ('banner') .style.display='none'}, 10000);
-           " page ".pageInit(" js-params "); };")]))
+     (str "window.onload = function () {" page ".pageInit(" js-params "); };")]))

 (defn find-webpack-files [page]
   (as-> (slurp "target/entry-points.json") wp
@@ -64,6 +62,8 @@
                           :left             "0"
                           :width            "100vw"
                           :z-index          "10000"}}
+     [:script {:type "text/javascript"}
+      "setTimeout (function () {document.getElementById ('banner') .style.display='none'}, 10000);"]
      [:p {:style {:font-size   "18px"
                   :font-weight "bold"
                   :margin      "0 30px 0 0"}}


WIP trying to make a dynamic form

WIP trying to make a dynamic form

--- src/cljs/clj_money/views/accounts.cljs
+++ src/cljs/clj_money/views/accounts.cljs
@@ -380,72 +380,70 @@
                            notify/danger)))

 (defn- item-input-row
-  [index item]
+  [index form-state]
   ^{:key (str "item-form-" index)}
-  [:tr
+  [:tr {:class (when (>= index (:visible-row-count @form-state))  "hidden")}
    [:td "account control goes here"]
    [:td [:input.form-control {:field :numeric
                               :id [:items index :credit-quantity]}]]
    [:td [:input.form-control {:field :numeric
                               :id [:items index :debit-quantity]}]]])

-(defn- items-input
-  [transaction]
-  [:table.table
-   [:thead
-    [:tr
-     [:td "Account"]
-     [:td "Credit Amount"]
-     [:td "Debit Amount"]]]
-   [:tbody
-    (doall
-      (map-indexed item-input-row
-                   (:items @transaction)))]])
-
-(defn- all-items-present?
-  [transaction]
-  (every? #(some % [:credit-quantity :debit-quantity])
-          (:items transaction)))
+(defn- trx-form
+  [form-state]
+  [:form
+   (text-input :transaction-date :required)
+   (text-input :description :required)
+
+   (.log js/console "trx-form " (prn-str @form-state))
+
+   ; full
+   [:table.table
+    [:thead
+     [:tr
+      [:td "Account"]
+      [:td "Credit Amount"]
+      [:td "Debit Amount"]]]
+    [:tbody
+     (->> (range 10)
+          (map #(item-input-row % form-state))
+          doall)]]
+
+   ; simplified
+   #_(number-input :quantity :required)
+   #_(typeahead-input
+       :other-account-id
+       {:data-source accounts-source
+        :input-placeholder "Select the other account"
+        :in-fn (model-in-fn accounts :path)
+        :out-fn (fn [v] (if (iterable? v) (first v) v))
+        :result-fn (fn [[path id]] path)})])

 (defn- transaction-form
   [{:keys [transaction] :as context}]
   (when @transaction
-    (let [form [:form
-                (text-input :transaction-date :required)
-                (text-input :description :required)
-
-                ; full
-                (items-input transaction)
-
-                ; simplified
-                #_(number-input :quantity :required)
-                #_(typeahead-input
-                  :other-account-id
-                  {:data-source accounts-source
-                   :input-placeholder "Select the other account"
-                   :in-fn (model-in-fn accounts :path)
-                   :out-fn (fn [v] (if (iterable? v) (first v) v))
-                   :result-fn (fn [[path id]] path)})]]
+    (let [form-state (r/atom {:visible-row-count 1})]
       [:div.panel.panel-primary
        [:div.panel-heading
         [:h2.panel-title (if (:id @transaction)
                            "Edit Transaction"
                            "New Transaction")]]
        [:div.panel-body
-        [bind-fields form transaction (fn [path value doc]
-
-                                        (.log js/console "doc " (prn-str doc))
-
-                                        (when (all-items-present? doc)
-                                          (swap! transaction
-                                                 update-in
-                                                 [:items]
-                                                 conj
-                                                 {:account-id nil
-                                                  :credit-quantity nil
-                                                  :debit-quantity nil})
-
-                                          (.log js/console "after add " (prn-str @transaction))))]
+        [bind-fields
+         (trx-form form-state)
+         transaction
+         (fn [path value {:keys [items] :as doc}]
+
+           (swap! form-state assoc :last-update (t/now))
+           (.log js/console "updated form state " (prn-str @form-state))
+
+           (let [filled (->> items
+                             (filter #(some % [:debit-quantity :credit-quantity]))
+                             count)
+                 visible (:visible-row-count @form-state)]
+             (when (>= filled visible)
+               (swap! form-state update-in [:visible-row-count] inc))
+             nil))]
         (util/button "Save"
                      #(save-transaction context)
                      {:class "btn btn-primary"


need cider-nrepl

need cider-nrepl

--- lein_profiles.clj
+++ lein_profiles.clj
@@ -1,5 +1,5 @@
 {:user {:plugins [
                   [lein-cljfmt "0.3.0" :exclusions [org.clojure/clojure]]
                   [lein-ancient "0.6.8" :exclusions [org.clojure/clojure]]
-                  [lein-ancient "0.6.8"]
+                  [cider/cider-nrepl "0.10.1"]
                   ]}}


Fixed type in factor-analysis code

Fixed type in factor-analysis code

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/contrib/factor_analysis.clj
+++ src/conexp/contrib/factor_analysis.clj
@@ -201,7 +201,7 @@
   [context U D a j]
   (let [D+ (assoc D j a),
         D+down (fuzzy-attribute-derivation context D+),
-        D+down-up (fuzzy-object-derivation context D+up)]
+        D+down-up (fuzzy-object-derivation context D+down)]
     (set-of [k l] [[k l] U,
                    :when (>= (f-star (D+down k) (D+down-up l))
                              ((incidence context) [k l]))])))


Small tweaks.

Small tweaks.


Update templated cider-nrepl version

Update templated cider-nrepl version

--- src/leiningen/new/figwheel/project.clj
+++ src/leiningen/new/figwheel/project.clj
@@ -109,8 +109,8 @@
                                   [cider/piggieback "0.3.1"]]
                    ;; need to add dev source path here to get user.clj loaded
                    :source-paths ["src" "dev"]
-                   ;; for CIDER
-                   ;; :plugins [[cider/cider-nrepl "0.12.0"]]
+                   ;; for CIDER. Note that you should use the snapshot version, so it matches with the elpa dependency.
+                   ;; :plugins [[cider/cider-nrepl "0.18.0-SNAPSHOT"]]
                    :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}
                    ;; need to add the compliled assets to the :clean-targets
                    :clean-targets ^{:protect false} ["resources/public/js/compiled"


Add commented deletion of temporal files.

--- test/uxbox/tests/helpers.clj
+++ test/uxbox/tests/helpers.clj
@@ -10,6 +10,7 @@
             [uxbox.services.auth :as usa]
             [uxbox.services.users :as usu]
             [uxbox.util.transit :as transit]
+            [uxbox.util.paths :as paths]
             [uxbox.migrations :as umg]
             [uxbox.media :as media]
             [uxbox.persistence :as up]
@@ -38,6 +39,7 @@
   (try
     (next)
     (finally
+      #_(paths/delete (-> +config+ :storage :basedir) {:recursive true})
       (mount/stop-except #'uxbox.config/config
                          #'uxbox.persistence/datasource))))


prettier forms| fs / cb / sg | #3

prettier forms| fs / cb / sg | #3

--- src/cljs/conference_rating/conference.cljs
+++ src/cljs/conference_rating/conference.cljs
@@ -34,6 +34,11 @@

 ;; -------------------------
 ;; Views
+(defn form-input [label input]
+  [:div {:class "form-group"}
+   [:label {:for (:id (second input))} label]
+   input])
+
 (defn display-loading []
   [:div [:h2 "Loading..."]])

@@ -50,12 +55,9 @@

 (def add-rating-template
   [:div
-   [:div {:class "form-group"}
-    [:input {:type "text" :placeholder "author" :class "form-control" :field :text :id :author}]]
-   [:div {:class "form-group"}
-    [:input {:type "number" :placeholder "stars" :class "form-control" :min 1 :max 5 :field :range :id :stars}]]
-   [:div {:class "form-group"}
-    [:textarea {:placeholder "comment" :class "form-control" :rows "5" :field :textarea :id :comment}]]])
+   (form-input "Author" [:input {:type "text" :placeholder "author" :class "form-control" :field :text :id :author}])
+   (form-input "Stars" [:input {:type "number" :placeholder "stars" :class "form-control" :min 1 :max 5 :field :range :id :stars}])
+   (form-input "Comment" [:textarea {:placeholder "comment" :class "form-control" :rows "5" :field :textarea :id :comment}])])

 (defn create-rating [form-data]
   (let [conference @displayed-conference]
@@ -104,15 +106,10 @@
       (display-loading))))

-(defn row [label input]
-  [:div.row
-   [:div.col-md-2 [:label label]]
-   [:div.col-md-5 input]])
-
 (def conference-form-template
   [:div
-   (row "Name" [:input {:field :text :id :name}])
-   (row "Description" [:textarea {:field :textarea :id :description}])])
+   (form-input "Name" [:input {:field :text :id :name :class "form-control" :placeholder "Name of the conference"}])
+   (form-input "Description" [:textarea {:field :textarea :rows 5 :id :description :class "form-control" :placeholder "More information about the conference"}])])

 (defn create-conference [form-data]
   (ajax/POST "/api/conferences/" {:params @form-data
@@ -123,8 +120,9 @@

 (defn add-conference-page []
   (let [doc (atom {})]
-    [:div
-     [:h2 "Add conference"]
-     [:div
-      [forms/bind-fields conference-form-template doc]
-      [:div [:button {:on-click #(create-conference doc)} "Create"]]]]))+    [:div {:class "container"}
+     [:div {:class "panel panel-default"}
+      [:div {:class "panel-heading"} "Add conference"]
+      [:div {:class "panel-body"}
+       [forms/bind-fields conference-form-template doc]
+       [:div [:button {:class "btn btn-primary":on-click #(create-conference doc)} "Create"]]]]]))


Codingame helper

Codingame helper

--- src/clojureplayground/codingame_helper.clj
+++ src/clojureplayground/codingame_helper.clj
@@ -1,26 +1,4 @@
 (ns clojureplayground.codingame-helper)
-
-(defn thor-move1 [adj opp theta]
-  (if (>= adj 0)
-    (if (>= opp 0)
-      (cond
-        (<= theta (/ Math/PI 8)) {:x 1 :y 0 :dir "E"}
-        (and (> theta (/ Math/PI 8)) (<= theta (* Math/PI 0.375))) {:x 1 :y 1 :dir "SE"}
-        (and (> theta (* Math/PI 0.375)) (<= theta (/ Math/PI 2))) {:x 0 :y 1 :dir "S"})
-      (cond
-        (<= theta (/ Math/PI 8)) {:x 1 :y 0 :dir "E"}
-        (and (> theta (/ Math/PI 8)) (<= theta (* Math/PI 0.375))) {:x 1 :y -1 :dir "NE"}
-        (and (> theta (* Math/PI 0.375)) (<= theta (/ Math/PI 2))) {:x 0 :y -1 :dir "N"}))
-    (if (>= opp 0)
-      (cond
-        (<= theta (/ Math/PI 8)) {:x -1 :y 0 :dir "W"}
-        (and (> theta (/ Math/PI 8)) (<= theta (* Math/PI 0.375))) {:x -1 :y 1 :dir "SW"}
-        (and (> theta (* Math/PI 0.375)) (<= theta (/ Math/PI 2))) {:x 0 :y 1 :dir "S"})
-      (cond
-        (<= theta (/ Math/PI 8)) {:x -1 :y 0 :dir "W"}
-        (and (> theta (/ Math/PI 8)) (<= theta (* Math/PI 0.375))) {:x -1 :y -1 :dir "NW"}
-        (and (> theta (* Math/PI 0.375)) (<= theta (/ Math/PI 2))) {:x 0 :y -1 :dir "N"}))
-    ))

 (defn direction [adj opp]
   (if (neg? adj)


Include the action URL with the auth dialog

--- src/com/frereth/server/comms/registrar.clj
+++ src/com/frereth/server/comms/registrar.clj
@@ -86,50 +86,54 @@
   ;; TODO: Set up a web server and go back to doing it this way
   (let [br {:tag :br, :attrs nil, :content nil}]
     (assoc msg
+           :action-url {:port 7841  ; FIXME: Magic Number
+                        ;; TODO: Pull this from a config file/env var instead
+                        :address (util/my-ip)
+                        :protocol :tcp}
            :expires (date/to-java-date (date/plus (date/date-time) (date/days 1)))
            :session-token (util/random-uuid)
            :world '{:data {:type :html
-                          :version 5
-                          ;; TODO: At the very least, use something like enlive/kioo instead
-                          :body {:tag :form
-                                 :attrs {:id "authenticate"}
-                                 :content ["User name:"
-                                           br
-                                           {:tag :input
-                                            :attrs {:name "principal-name" :type "text"}
-                                            :content nil}
-                                           br
-                                           "\nPassword:"
-                                           br
-                                           {:tag :input
-                                            :attrs {:name "auth-token" :type "password"}
-                                            :content nil}
-                                           br
-                                           {:tag :input
-                                            :attrs {:name "submit" :type "submit" :value "Log In"}
-                                            :content nil}]}}
-                   ;; This basic script was taken from
-                   ;; http://swannodette.github.io/2013/11/07/clojurescript-101/
-                   ;; Vital assumptions here:
-                   ;; 1. Basic clojurescript environment
-                   ;; 2. use'ing the core.async ns
-                   ;; 3. require'd goog.dom as dom and goog.events as events
-                   ;; Or, at least, that we're in an interpreter
-                   ;; environment/namespace
-                   ;; that acts as if those assumptions are true
-                   :script [(defn listen [element event-type]
-                              (let [out (chan)]
-                                (events/listen element event-type
-                                               (fn [e]
-                                                 (put! out e)))
-                                out))
-                            (let [clicks (listen (dom/getElement "submit") "click")]
-                              (go (while true
-                                    (raise :start-here)
-                                    (let [clicked (<! clicks)
-                                          ]))))]
-                   ;; TODO: Definitely use garden to build something here
-                   :css []})))
+                           :version 5
+                           ;; TODO: At the very least, use something like enlive/kioo instead
+                           :body {:tag :form
+                                  :attrs {:id "authenticate"}
+                                  :content ["User name:"
+                                            br
+                                            {:tag :input
+                                             :attrs {:name "principal-name" :type "text"}
+                                             :content nil}
+                                            br
+                                            "\nPassword:"
+                                            br
+                                            {:tag :input
+                                             :attrs {:name "auth-token" :type "password"}
+                                             :content nil}
+                                            br
+                                            {:tag :input
+                                             :attrs {:name "submit" :type "submit" :value "Log In"}
+                                             :content nil}]}
+                           ;; This basic script was taken from
+                           ;; http://swannodette.github.io/2013/11/07/clojurescript-101/
+                           ;; Vital assumptions here:
+                           ;; 1. Basic clojurescript environment
+                           ;; 2. use'ing the core.async ns
+                           ;; 3. require'd goog.dom as dom and goog.events as events
+                           ;; Or, at least, that we're in an interpreter
+                           ;; environment/namespace
+                           ;; that acts as if those assumptions are true
+                           :script [(defn listen [element event-type]
+                                      (let [out (chan)]
+                                        (events/listen element event-type
+                                                       (fn [e]
+                                                         (put! out e)))
+                                        out))
+                                    (let [clicks (listen (dom/getElement "submit") "click")]
+                                      (go (while true
+                                            (raise :start-here)
+                                            (let [clicked (<! clicks)
+                                                  ]))))]
+                           ;; TODO: Definitely use garden to build something here
+                           :css []}})))

 (comment
   (require '[clojure.xml :as xml])


Put the construction of the leader into a single form.

--- src/overtunes/songs/canone_alla_quarta.clj
+++ src/overtunes/songs/canone_alla_quarta.clj
@@ -39,22 +39,23 @@
     (range a (inc b))
     (reverse (run b a))))

-(def call
-  {:time (concat (repeat 2 1/4) [1/2] (repeat 14 1/4) [3/2])
-   :pitch (concat [0] (run -1 3) (run 2 0) [4] (run 1 8))})
-
-(def response
-  {:time (concat (repeat 10 1/4) [1/2] (repeat 2 1/4) [9/4])
-   :pitch (concat (run 7 -1) [0] (run 0 -3))})
-
-(def development
-  {:time (concat [3/4] (repeat 12 1/4) [1/2 1 1/2] (repeat 12 1/4) [3])
-   :pitch (concat [4 4] (run 2 -3) [-1 -2 0] (run 3 5) (repeat 3 1) [2] (run -1 1) [0 -1] (run 5 0))})
-
 (defn melody [notes]
   (let [functionalise #(update-all % [:time :pitch] natural-map)
         ground-time (update :time sums)]
     (-> notes ground-time functionalise)))
+
+(def leader
+  (let [call {:time (concat (repeat 2 1/4) [1/2] (repeat 14 1/4) [3/2])
+              :pitch (concat [0] (run -1 3) (run 2 0) [4] (run 1 8))}
+        response
+             {:time (concat (repeat 10 1/4) [1/2] (repeat 2 1/4) [9/4])
+              :pitch (concat (run 7 -1) [0] (run 0 -3))}
+        development
+             {:time (concat [3/4] (repeat 12 1/4) [1/2 1 1/2] (repeat 12 1/4) [3])
+              :pitch (concat [4 4] (run 2 -3) [-1 -2 0] (run 3 5) (repeat 3 1) [2] (run -1 1) [0 -1] (run 5 0))}
+        mainline
+             (merge-with concat call response development)]
+    (melody mainline)))

 (def bassline
   {:time (repeat 24 1)
@@ -65,10 +66,6 @@
        lower-melody (update :pitch #(connect lower-note %))]
    (-> bassline melody lower-melody)))

-(defn subsequent [melody1 melody2]
-  (merge-with concat melody1 melody2))
-
-(def leader (melody (reduce subsequent [call response development])))

 (defn melody# [melody]
   (let [notes (update-all melody [:pitch :time] natural-seq)


refactor several nested gets in terms of get-in

--- src/puppetlabs/cthun/connection_states.clj
+++ src/puppetlabs/cthun/connection_states.clj
@@ -78,18 +78,23 @@
    :user "undefined"
    :created-at (ks/timestamp)})

+ (defn- logged-in?
+  "Determine if host/websocket combination has logged in"
+  [host ws]
+  (= (get-in @connection-map [host ws :status]) "ready"))
+
 (defn- process-login-message
   "Process a login message from a client"
   [host ws message-body]
   (log/info "Processing login message")
   (when (validation/validate-login-data (:data message-body))
     (log/info "Valid login message received")
-    (if (= (:status (get (get @connection-map host) ws)) "ready")
-      ;There has already been a login even on the websocket
+    (if (logged-in? host ws)
       (throw (Exception. (str "Received login attempt from host '" host "' on socket '"
-                         ws "' but already logged in at " (:create-at (get (get @connection-map host) ws))
+                         ws "' but already logged in at "
+                         (get-in @connection-map [host ws :created-at])
                          " as "
-                         (:user (get (get @connection-map host) ws))
+                         (get-in @connection-map [host ws :user])
                          ". Ignoring")))
       (let [data (:data message-body)
             type (:type data)
@@ -120,25 +125,21 @@

 ; Forwards a message to the defined endpoints.
 (defn- process-client-message
-  "Process a message directed at a connected client"
+  "Process a message directed at a connected client(s)"
   [host ws message-body]
   (doseq [websocket (parse-endpoints (:endpoints message-body) @endpoint-map)]
     (try
-      (let [modified-body (assoc message-body :sender (:endpoint (get (get @connection-map host) ws)))]
+      (let [sender (get-in @connection-map [host ws :endpoint])
+            modified-body (assoc message-body :sender sender)]
         (jetty-adapter/send! websocket (cheshire/generate-string modified-body)))
       (catch Exception e (log/warn (str "Exception raised while trying to process a client message: "
                               (.getMessage e)
                               ". Dropping message"))))))

- (defn- logged-in?
-  "Determine if host/websocket combination has logged in"
-  [host ws]
-  (= (:status (get (get @connection-map host) ws)) "ready"))
-
 (defn- login-message?
   "Return true if message is a login type message"
   [message]
-  (and (= (get (:endpoints message) 0) "cth://server")
+  (and (= (first (:endpoints message)) "cth://server")
        (= (:data_schema message) "http://puppetlabs.com/loginschema")))

 (defn add-connection


Project should not be analyzed

Project should not be analyzed

--- src/pathfinder/data/elasticsearch.clj
+++ src/pathfinder/data/elasticsearch.clj
@@ -28,7 +28,8 @@
 (defn- setup-index! [conn]
   (let [mappings {:doc {:properties
                         {:meta {:properties
-                                {:path {:type "string" :index "not_analyzed"}}}}}}]
+                                {:path {:type "string" :index "not_analyzed"}
+                                 :project {:type "string" :index "not_analyzed"}}}}}}]
     (when-not (esi/exists? conn "docs")
       (esi/create conn "docs" :mappings mappings))))


… and the minute was wrong

… and the minute was wrong

--- ws-client/src/main/clojure/ws/client/ws_client.clj
+++ ws-client/src/main/clojure/ws/client/ws_client.clj
@@ -55,7 +55,7 @@
 (comment (run-load-test "http://ec2-50-19-75-61.compute-1.amazonaws.com:8080/ws-java-servlet-blocking/testA" 4 200 "/tmp/testA2.log"))

 ; format dates like "Fri, 15 Feb 2013 15:13:41"
-(def date-format (new java.text.SimpleDateFormat "EEE, dd MMM yyyy HH:MM:ss"))
+(def date-format (new java.text.SimpleDateFormat "EEE, dd MMM yyyy HH:mm:ss"))

 (defn get-formatted-date
   [date]


add placeholders for validation tests

add placeholders for validation tests

--- test/clj_money/models/commodities_test.clj
+++ test/clj_money/models/commodities_test.clj
@@ -33,3 +33,43 @@
              :exchange :nasdaq}]
            (map #(select-keys % [:name :symbol :exchange]) commodities))
         "The commodity can be retrieved after create")))
+
+(deftest entity-id-is-required
+  (is false "need to write the test"))
+
+(deftest name-is-required
+  (is false "need to write the test"))
+
+(deftest name-is-unique-for-an-entity-and-exchange
+  (is false "need to write the test"))
+
+(deftest name-can-be-duplicated-between-exchanges
+  (is false "need to write the test"))
+
+(deftest name-can-be-duplicated-between-entities
+  (is false "need to write the test"))
+
+(deftest symbol-is-required
+  (is false "need to write the test"))
+
+(deftest symbol-is-unique-for-an-entity-and-exchange
+  (is false "need to write the test"))
+
+(deftest symbol-can-be-duplicated-between-exchanges
+  (is false "need to write the test"))
+
+(deftest symbol-can-be-duplicated-between-entities
+  (is false "need to write the test"))
+
+(deftest exchange-is-required
+  (is false "need to write the test"))
+
+(deftest exchange-must-be-a-valid-exchange
+  (testing "it can be :nyse"
+    (is false "need to write the test"))
+  (testing "it can be :nasdaq"
+    (is false "need to write the test"))
+  (testing "it can be :fund"
+    (is false "need to write the test"))
+  (testing "it cannot be anything other than :nyse, :nasdaq, or :fund"
+    (is false "need to write the test")))


Update build_head.cljs

Update build_head.cljs

--- frontend/components/build_head.cljs
+++ frontend/components/build_head.cljs
@@ -267,7 +267,7 @@
         (if (and past-ms
                  (= (:status build) "running")
                  (< duration-ms (* 1.5 past-ms)))
-          (dom/span nil " / " (formatter past-ms))
+          (dom/span nil "/~" (formatter past-ms))
           (dom/span nil ""))))))

 (defn build-head [data owner]


clearing locks during cleanup

clearing locks during cleanup

--- src/taoensso/carmine/message_queue.clj
+++ src/taoensso/carmine/message_queue.clj
@@ -98,6 +98,7 @@
         redis.call('lrem', _:qk-id-circle, 1, msg_id) -- Efficient here
         redis.call('srem', _:qk-recently-done, msg_id)
         redis.call('hdel', _:qk-messages, msg_id)
+        redis.call('hdel', _:qk-locks, msg_id)
         return nil
       else
         local current_time  = tonumber(_:current-time)


[#1077] Parse epoch instad of MS strings

--- backend/src/akvo/lumen/lib/aggregation/filter.clj
+++ backend/src/akvo/lumen/lib/aggregation/filter.clj
@@ -33,7 +33,7 @@

 (defn parse-date [s]
   (try
-    (java.sql.Timestamp. (Long/parseLong s))
+    (java.sql.Timestamp. (/ s 1000))
     (catch NumberFormatException e
       (invalid-filter "Not a timestamp" {:string s}))))


Fix Reagent project template indentation

--- resources/leiningen/new/expo/reagent/project.clj
+++ resources/leiningen/new/expo/reagent/project.clj
@@ -1,45 +1,45 @@
 (defproject {{name}} "0.1.0-SNAPSHOT"
-            :description "FIXME: write description"
-            :url "http://example.com/FIXME"
-            :license {:name "Eclipse Public License"
-                      :url  "http://www.eclipse.org/legal/epl-v10.html"}
-            :dependencies [[org.clojure/clojure "1.10.1"]
-                          [org.clojure/clojurescript "1.10.520"]
-                          [binaryage/oops "0.7.0"]
-                          [reagent "0.8.1" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server cljsjs/create-react-class]]
-                          [re-frame "0.10.8"]]
-            :plugins [[lein-cljsbuild "1.1.4"]
-                      [lein-figwheel "0.5.19"]]
-            :clean-targets ["target/" "main.js"]
-            :aliases {"figwheel"        ["run" "-m" "user" "--figwheel"]
-                      ; TODO: Remove custom extern inference as it's unreliable
-                      ;"externs"         ["do" "clean"
-                      ;                   ["run" "-m" "externs"]]
-                      "rebuild-modules" ["run" "-m" "user" "--rebuild-modules"]
-                      "prod-build"      ^{:doc "Recompile code with prod profile."}
-                                        ["with-profile" "prod" "cljsbuild" "once" "main"]}
-            :profiles {:dev  {:dependencies [[figwheel-sidecar "0.5.18"]
-                                             [cider/piggieback "0.4.1"]]
-                              :source-paths ["src" "env/dev"]
-                              :cljsbuild    {:builds [{:id           "main"
-                                                       :source-paths ["src" "env/dev"]
-                                                       :figwheel     true
-                                                       :compiler     {:output-to     "target/expo/index.js"
-                                                                      :main          "env.expo.main"
-                                                                      :output-dir    "target/expo"
-                                                                      :optimizations :none
-                                                                      :target        :nodejs}}]}
-                              :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}}
-                       :prod {:cljsbuild {:builds [{:id           "main"
-                                                    :source-paths ["src" "env/prod"]
-                                                    :compiler     {:output-to          "main.js"
-                                                                   :main               "env.expo.main"
-                                                                   :output-dir         "target/expo"
-                                                                   :static-fns         true
-                                                                   :externs            ["js/externs.js"]
-                                                                   :infer-externs      true
-                                                                   :parallel-build     true
-                                                                   :optimize-constants true
-                                                                   :optimizations      :advanced
-                                                                   :closure-defines    {"goog.DEBUG" false}
-                                                                   :target             :nodejs}}]}}})
+  :description "FIXME: write description"
+  :url "http://example.com/FIXME"
+  :license {:name "Eclipse Public License"
+            :url  "http://www.eclipse.org/legal/epl-v10.html"}
+  :dependencies [[org.clojure/clojure "1.10.1"]
+                 [org.clojure/clojurescript "1.10.520"]
+                 [binaryage/oops "0.7.0"]
+                 [reagent "0.8.1" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server cljsjs/create-react-class]]
+                 [re-frame "0.10.8"]]
+  :plugins [[lein-cljsbuild "1.1.4"]
+            [lein-figwheel "0.5.19"]]
+  :clean-targets ["target/" "main.js"]
+  :aliases {"figwheel"        ["run" "-m" "user" "--figwheel"]
+            ; TODO: Remove custom extern inference as it's unreliable
+            ;"externs"         ["do" "clean"
+            ;                   ["run" "-m" "externs"]]
+            "rebuild-modules" ["run" "-m" "user" "--rebuild-modules"]
+            "prod-build"      ^{:doc "Recompile code with prod profile."}
+            ["with-profile" "prod" "cljsbuild" "once" "main"]}
+  :profiles {:dev  {:dependencies [[figwheel-sidecar "0.5.18"]
+                                   [cider/piggieback "0.4.1"]]
+                    :source-paths ["src" "env/dev"]
+                    :cljsbuild    {:builds [{:id           "main"
+                                             :source-paths ["src" "env/dev"]
+                                             :figwheel     true
+                                             :compiler     {:output-to     "target/expo/index.js"
+                                                            :main          "env.expo.main"
+                                                            :output-dir    "target/expo"
+                                                            :optimizations :none
+                                                            :target        :nodejs}}]}
+                    :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}}
+             :prod {:cljsbuild {:builds [{:id           "main"
+                                          :source-paths ["src" "env/prod"]
+                                          :compiler     {:output-to          "main.js"
+                                                         :main               "env.expo.main"
+                                                         :output-dir         "target/expo"
+                                                         :static-fns         true
+                                                         :externs            ["js/externs.js"]
+                                                         :infer-externs      true
+                                                         :parallel-build     true
+                                                         :optimize-constants true
+                                                         :optimizations      :advanced
+                                                         :closure-defines    {"goog.DEBUG" false}
+                                                         :target             :nodejs}}]}}})


Merging form into chart component.

Merging form into chart component.

--- src-cljs/kixi/hecuba/web/chart.cljs
+++ src-cljs/kixi/hecuba/web/chart.cljs
@@ -56,10 +56,10 @@
 (defn- fetch-data [device-id]
   (get mock-data device-id))

-;;;;;;;;;; Components ;;;;;;;;;;;;;;;;;
+;;;;;;;;;; Application state ;;;;;;;;;;;;;;;;;

 (def chart-state
-  (atom {:selected []
+  (atom {:selected #{}
          :property "rad003"
          :devices [{:hecuba/name "01"
                     :name "External temperature"}
@@ -67,49 +67,39 @@
                     :name "External humidity"}]
          :data []}))

-;;;;;;;;;;; Component 1:  List of devices for axis plots ;;;;;;;;;;
+;;;;;;;;;; Chart Component ;;;;;;;;;;

-(defn device-list-item
-  [devices]
-  (fn [cursor owner]
-    (om/component
-     (.log js/console "[device-list-item] I render")
-    (let [device-details  (for [device devices] (get cursor device))
-          device-id       (nth device-details 0) ;; TODO Sersiously need to change the way elements are accessed
-          device-name     (str (nth device-details 1))
-          selected        (= device-id (first (:selected cursor)))]
-      (apply dom/input #js {:className (when selected "selected")
-                            :type "checkbox"
-                            :onClick
-                            (fn [e]
-                              (.log js/console "Clicked")
-                              (om/update! cursor update-in [:selected] (fn [selected] (vector device-id))))}
-            device-name)))))
-
-;;;;;;;;;; Component 2: Chart UI ;;;;;;;;;;
-
-(defn chart-item
+(defn chart-component
   [device-details]
   (fn [cursor opts]
     (reify
       om/IWillMount
       (will-mount [this]
-        (.log js/console "[chart-item] I will mount")
+        (.log js/console "I will mount")
         (om/update! cursor update-in [:data] (fn [data] (get mock-data (:selected cursor)))))
       om/IRender
       (render [this]
-        (.log js/console "[chart-item] I render")
-        (dom/div #js {:id "chart"}))
-      om/IDidMount
-      (did-mount [this owner]
-        (.log js/console "[chart-item] I did mount"))
-      om/IWillUpdate
-      (will-update [this next-props next-state]
-        (.log js/console "[chart-item] I will update"))
+        (.log js/console "I render")
+        (dom/div nil
+                 (dom/p nil (apply str (interpose "," (get-in cursor [:selected]))))
+                 (dom/form nil
+                           (for [device (get cursor :devices)]
+                             (let [device-id   (str (:hecuba/name device))
+                                   device-name (str (:name device))]
+                               (.log js/console "I did mount" device-id device-name)
+                               (dom/input #js {:type "checkbox"
+                                               :onClick (fn [e]
+                                                          (.dir js/console e)
+                                                          (om/update! cursor update-in [:selected]
+                                                                      conj device-id))}
+                                          device-name))))
+                 (dom/div #js {:id "chart"})))
       om/IDidUpdate
       (did-update [this prev-props prev-state root-node]
-        (.log js/console "[chart-item] I did update")
-       ; (remove-chart)
+        (.log js/console "I did update")
+        (let [n (.getElementById js/document "chart")]
+             (while (.hasChildNodes n)
+               (.removeChild n (.-lastChild n))))
          (let [Chart        (.-chart dimple)
               svg          (.newSvg dimple "#chart" 400 350)
               measurements []
@@ -122,24 +112,18 @@

 ;;;;;;;;;;; Bootstrap ;;;;;;;;;;;;

-(defn create-form-and-chart [model-path device-item chart-item]
+(defn create-form-and-chart [model-path chart-comp]
   (fn [cursor owner]
     (reify
       om/IRender
       (render [this]
-        (dom/div #js {:className "devices"}
+        (dom/div nil
                  (dom/h3 nil (str "Metering data - " (get-in cursor [:property])))
                  (dom/h4 nil "Select devices to be plotted on the chart:")
-                 (dom/form #js {:className "devices-form"}
-                           (om/build-all device-item
-                                         (get-in cursor model-path)
-                                         {:key :hecuba/name})
-                           (om/build chart-item cursor)))))))
+                 (om/build chart-comp cursor))))))

-(om/root chart-state (create-form-and-chart [:devices]
-                                                   (device-list-item [:hecuba/name :name])
-                                                   (chart-item [:hecuba/name :name :data]))
+(om/root chart-state (create-form-and-chart [:devices] (chart-component [:hecuba/name :name :data]))
                  (.getElementById js/document "app"))


Inbox: Add idx to pages so we can support drop-at-idx.

--- src-cljs/pepa/workflows/inbox2.cljs
+++ src-cljs/pepa/workflows/inbox2.cljs
@@ -27,7 +27,7 @@
   (remove-pages! [_ state page-ids]))

 (defprotocol ColumnDropTarget
-  (accept-drop!  [_ state pages]))
+  (accept-drop!  [_ state pages target-idx]))

 (defrecord InboxColumnSource [id]
   ColumnSource
@@ -48,11 +48,12 @@
                               (remove #(contains? page-ids (:id %)))
                               pages))))))
   ColumnDropTarget
-  ;; TODO: Make immutable?
-  (accept-drop! [_ state new-pages]
-    (go
-      (println "dropping" (pr-str new-pages) "on inbox")
-      (<! (api/add-to-inbox! (map :id new-pages)))
+  (accept-drop! [_ state new-pages target-idx]
+    (go
+      (let [page-ids (map :id new-pages)]
+        (println "dropping" (pr-str page-ids) "on inbox (at index" target-idx ")")
+        ;; TODO: Error-Handling
+        (<! (api/add-to-inbox! page-ids)))
       ;; Return true, indicating successful drop
       true))
   om/IWillMount
@@ -75,9 +76,10 @@
         (js/console.error (str "[DocumentColumnSource] Failed to get document " document-id)
                           {:document-id document-id}))))
   ColumnDropTarget
-  (accept-drop! [_ state new-pages]
-    (go
-      (println "dropping" (pr-str new-pages) "on document" document-id)
+  (accept-drop! [_ state new-pages target-idx]
+    (go
+      (println "dropping" (pr-str (map :id new-pages)) "on document" document-id
+               (str "(at index " target-idx ")"))
       (let [document (om/value (get-in state [:documents document-id]))]
         (<! (api/update-document! (update document :pages
                                           #(into % new-pages))))
@@ -93,14 +95,16 @@
 ;;; `inbox-column-page' (the latter to handle selection-updates when
 ;;; dragging). We bubble it from `inbox-column-page', adding its own
 ;;; `:id' and use that id to update the selection information.
-(ui/defcomponent inbox-column-page [page owner {:keys [page-click!]}]
+(ui/defcomponent inbox-column-page [page owner {:keys [page-click! store-idx!]}]
   (render [_]
     [:li.page {:draggable true
                :class [(when (:selected? page) "selected")]
                :on-drag-start (fn [e]
                                 (println "inbox-column-page")
-                                (doto e.dataTransfer
-                                  (.setData "application/x-pepa-page" (:id page))))
+                                (.setData e.dataTransfer "application/x-pepa-page" (:id page)))
+               :on-drag-enter (fn [e]
+                                (println "[inbox-column-page] drag-enter")
+                                (store-idx! (:idx page)))
                :on-click (fn [e]
                            (page-click!
                             (selection/event->click (:id page) e))
@@ -109,9 +113,10 @@
                {:opts {:enable-rotate? true}})]))

 (defn ^:private get-transfer-data [e key]
-  (some-> e.dataTransfer
-          (.getData (name key))
-          (read-string)))
+  (or (some-> e.dataTransfer
+              (.getData (name key))
+              (read-string))
+      (js/console.warn "Couldn't read transfer-data for key:" (pr-str key))))

 (defn ^:private column-drag-start
   "Called from `inbox-column' when `dragstart' event is fired. Manages
@@ -140,7 +145,7 @@
 (defn ^:private mark-page-selected
   "Assocs {:selected? true} to `page' if `selected-pages'
   contains (:id page). Used in `index-column'."
-  [selected-pages page]
+  [page selected-pages]
   (assoc page :selected? (contains? (set selected-pages) (:id page))))

 (ui/defcomponent inbox-column [[state column] owner opts]
@@ -159,7 +164,7 @@
                   (om/value new-pages))
         (om/set-state! owner :selection
                        (selection/make-selection new-pages)))))
-  (render-state [_ {:keys [selection handle-drop!]}]
+  (render-state [_ {:keys [selection handle-drop! drop-idx]}]
     ;; NOTE: `column' needs to be a value OR we need to extend cursors
     [:.column {:on-drag-over (fn [e]
                                (when (satisfies? ColumnDropTarget (om/value column))
@@ -174,32 +179,44 @@
                             ;; Delegate to `inbox'
                             (handle-drop! (:id column)
                                           source-column
-                                          page-ids)))}
+                                          page-ids
+                                          drop-idx)))}
      [:header (column-title column state)]
      [:ul.pages
-      (om/build-all inbox-column-page (column-pages column state)
-                    {:opts {:page-click! (fn [click]
-                                           (om/update-state! owner :selection
-                                                             #(selection/click % click)))}
-                     :fn (partial mark-page-selected (:selected selection))})]]))
-
-(defn ^:private inbox-handle-drop! [state owner page-cache target source page-ids]
+      (let [pages (map-indexed (fn [idx page] (assoc page :idx idx))
+                               (column-pages column state))]
+        (om/build-all inbox-column-page pages
+                      {:opts {:page-click! (fn [click]
+                                             (om/update-state! owner :selection
+                                                               #(selection/click % click)))
+                              :store-idx! (fn [idx]
+                                            (om/set-state! owner :drop-idx idx))}
+                       :fn (fn [page]
+                             (mark-page-selected page (:selected selection)))}))]]))
+
+(defn ^:private inbox-handle-drop! [state owner page-cache target source page-ids target-idx]
   (let [columns (om/get-state owner :columns)
         target (get columns target)
         source (get columns source)
         ;; Remove page-ids already in `target'
-        target-pages (mapv :id (column-pages target state))
+        existing-pages (mapv :id (column-pages target state))
         pages (into []
-                    (comp (remove (set target-pages))
+                    (comp (remove (set existing-pages))
                           (map page-cache)
                           (map om/value))
                     page-ids)]
+    ;; TODO: Assert?
+    (when-not (<= 0 target-idx (dec (count existing-pages)))
+      (throw (ex-info (str "Got invalid target-idx:" target-idx)
+                      {:idx target-idx
+                       :column-pages existing-pages
+                       :pages pages})))
     (if-not (seq pages)
       ;; TODO: Should we do that in the columns itself?
       (js/console.warn "Ignoring drop consisting only of duplicate pages:"
                        (pr-str page-ids))
       (go
-        (if (<! (accept-drop! target state pages))
+        (if (<! (accept-drop! target state pages target-idx))
           (do
             (println "Target saved. Removing from source...")
             (<! (remove-pages! source state page-ids))


fix custom event dispatch for IE

fix custom event dispatch for IE

--- support/src/figwheel/client/utils.cljs
+++ support/src/figwheel/client/utils.cljs
@@ -1,5 +1,6 @@
 (ns ^:figwheel-no-load figwheel.client.utils
-    (:require [clojure.string :as string])
+  (:require [clojure.string :as string]
+            [goog.userAgent.product :as product])
     (:import [goog]))

 ;; don't auto reload this file it will mess up the debug printing
@@ -14,13 +15,23 @@

 (defn base-url-path [] (string/replace goog/basePath #"(.*)goog/" "$1"))

+;; Custom Event must exist before calling this
+(defn create-custom-event [event-name data]
+  (if-not product/IE
+    (js/CustomEvent. event-name (js-obj "detail" data))
+    ;; in windows world
+    ;; this will probably not work at some point in
+    ;; newer versions of IE
+    (let [event (js/document.createEvent "CustomEvent")]
+      (.. event (initCustomEvent event-name false false data))
+      event)))
+
 ;; actually we should probably lift the event system here off the DOM
 ;; so that we work well in Node and other environments
 (defn dispatch-custom-event [event-name data]
   (when (and (html-env?) (aget js/window "CustomEvent") (js* "typeof document !== 'undefined'"))
     (.dispatchEvent (.-body js/document)
-                    (js/CustomEvent. event-name
-                                     (js-obj "detail" data)))))
+                    (create-custom-event event-name data))))

 (defn debug-prn [o]
   (when *print-debug*


Add tags to malli-example

Add tags to malli-example

--- examples/ring-malli-swagger/src/example/server.clj
+++ examples/ring-malli-swagger/src/example/server.clj
@@ -24,7 +24,9 @@
       [["/swagger.json"
         {:get {:no-doc true
                :swagger {:info {:title "my-api"
-                                :description "with reitit-ring"}}
+                                :description "with [malli](https://github.com/metosin/malli) and reitit-ring"}
+                         :tags [{:name "files", :description "file api"}
+                                {:name "math", :description "math api"}]}
                :handler (swagger/create-swagger-handler)}}]

        ["/files"


Fixed radio buttons on create project

Fixed radio buttons on create project

--- frontend/src/uxbox/main/ui/dashboard/projects.cljs
+++ frontend/src/uxbox/main/ui/dashboard/projects.cljs
@@ -289,7 +289,7 @@
        :id id
        :name "project-layout"
        :value name
-       :checked (= layout-id (:layout @local))
+       :checked (when (= layout-id (:layout @local)) "checked")
        :on-change #(swap! local merge {:layout layout-id
                                        :width width
                                        :height height})}]


Reorganized top level definitions & fixed indentation.

--- src/validation_benchmark/lib/spec.clj
+++ src/validation_benchmark/lib/spec.clj
@@ -4,9 +4,29 @@
   (:import [validation_benchmark.common Person]))

+(s/def ::age integer?)
 (s/def ::name string?)
+(s/def ::keyword-set (s/and set?
+                            (s/coll-of keyword? #{})))
+(s/def ::nilable-saiyan? (s/nilable (s/or :t true? :f false?)))
+(s/def ::nilable-number (s/nilable number?))
+(s/def ::nilable-string (s/nilable string?))
+(s/def ::person (s/keys :req-un [::name ::saiyan? ::age]))
+(s/def ::Person? #(instance? Person %))
+(s/def ::range (s/tuple (partial in-range? 0.0 1.0)
+                        (partial in-range? 1 10)
+                        (partial in-range? 1 100)))
 (s/def ::saiyan? (s/or :t true? :f false?))
-(s/def ::age integer?)
+(s/def ::three-tuple
+  (s/and coll?
+         #(= (count %) 3)
+         #(keyword? (first %))
+         #(string? (second %))
+         #(number? (nth % 2))))
+(s/def ::typed-person (s/and ::Person?
+                             (s/keys :req-un [::name ::saiyan? ::age])))
+(s/def ::vector-of-two-elements (s/and (s/coll-of nil [])
+                                       (s/tuple nil nil)))

 (defn atomic-keyword [v]
@@ -17,29 +37,22 @@
   (s/conform number? v))

-(s/def ::nilable-saiyan? (s/nilable (s/or :t true? :f false?)))
 (defn nil-allowed-bool [v]
   (s/conform ::nilable-saiyan? v))

-(s/def ::nilable-number (s/nilable number?))
 (defn nil-allowed-number [v]
   (s/conform ::nilable-number v))

-(s/def ::nilable-string (s/nilable string?))
 (defn nil-allowed-string [v]
   (s/conform ::nilable-string v))

-(s/def ::person (s/keys :req-un [::name ::saiyan? ::age]))
 (defn person-map [v]
   (s/conform ::person v))

-(s/def ::Person? #(instance? Person %))
-(s/def ::typed-person (s/and ::Person?
-                        (s/keys :req-un [::name ::saiyan? ::age])))
 (defn person-record [v]
   (s/conform ::typed-person
              v))
@@ -49,33 +62,18 @@
   (s/conform prime? v))

-(s/def ::range (s/tuple (partial in-range? 0.0 1.0)
-                 (partial in-range? 1 10)
-                 (partial in-range? 1 100)))
 (defn range-check [v]
   (s/conform ::range v))

-(s/def ::keyword-set (s/and set?
-                       (s/coll-of keyword? #{})))
 (defn set-of-keywords [v]
   (s/conform ::keyword-set v))

-(s/def ::three-tuple
-  (s/and coll?
-    #(= (count %) 3)
-    #(keyword? (first %))
-    #(string? (second %))
-    #(number? (nth % 2))))

 (defn three-tuple [v]
-  ;; (s/conform (s/tuple keyword? string? number?) v)
   (s/conform ::three-tuple v))

-
-(s/def ::vector-of-two-elements (s/and (s/coll-of nil [])
-                                  (s/tuple nil nil)))

 (defn vector-of-two-elements [v]
   (s/conform ::vector-of-two-elements v))


window needs to be resized in tests now that app is actually responsive

--- pedestal-app/test/semtag_web/integration_test.clj
+++ pedestal-app/test/semtag_web/integration_test.clj
@@ -3,6 +3,7 @@
             [clj-webdriver.driver :refer [init-driver]]
             [clj-webdriver.core :as core]
             [clj-webdriver.taxi :as taxi]
+            [clj-webdriver.window :as window]
             [semtag-web.route :as route]
             [clojure.string :as string]
             [io.pedestal.app-tools.dev :as dev])
@@ -45,7 +46,9 @@

 (use-fixtures :each
               (fn [f]
-                (taxi/set-driver! (init-driver {:webdriver (PhantomJSDriver. (DesiredCapabilities. ))}))
+                (-> (init-driver {:webdriver (PhantomJSDriver. (DesiredCapabilities. ))})
+                    (window/resize {:width 1024 :height 768})
+                    (taxi/set-driver!))
                 (binding [ctest/report report] (f))
                 (taxi/quit)))


Extend test for duration parser

Extend test for duration parser

--- test/cider_ci/utils/tests/duration.clj
+++ test/cider_ci/utils/tests/duration.clj
@@ -14,6 +14,10 @@

   (is (= 1.0 (parse-string-to-seconds "1 Second")))

+  (is (= 30.0 (parse-string-to-seconds "0.5 Minutes")))
+
+  (is (= 150.0 (parse-string-to-seconds "2.5 Minutes")))
+
   (is (= 3600.333 (parse-string-to-seconds "1 hour and 333 milliseconds")))

   (is (=


CMR-6217 added additional tests

CMR-6217 added additional tests

--- access-control-app/int-test/cmr/access_control/int_test/access_control_group_crud_test.clj
+++ access-control-app/int-test/cmr/access_control/int_test/access_control_group_crud_test.clj
@@ -464,18 +464,38 @@
               :errors [(format "A system group with name [%s] already exists with concept id [%s]."
                                (:name group2)
                                concept_id2)]}
+             (test-util/update-group token concept_id3 (assoc group3 :name (:name group2))))))
+
+    (testing "Update a group with conflicting name"
+      (is (= {:status 409
+              :errors [(format "A system group with name [%s] already exists with concept id [%s]."
+                               (:name group2)
+                               concept_id2)]}
              (test-util/update-group token concept_id3 (assoc group3 :name (:name group2))))))))

 (deftest update-groups-with-identical-names-but-different-providers
   (let [group1 (test-util/make-group {:name "group1" :provider_id "PROV1"})
+        group1a (test-util/make-group {:name "group2" :provider_id "PROV1"})
         group2 (test-util/make-group {:name "group2" :provider_id "PROV2"})
         token (echo-util/login (test-util/conn-context) "user1")
         {concept_id1 :concept_id} (test-util/create-group token group1)
+        {concept_id1a :concept_id} (test-util/create-group token group1a)
         {concept_id2 :concept_id} (test-util/create-group token group2)]
-    (is (= {:status 200
-            :revision_id 2
-            :concept_id (format "%s" concept_id2)}
-           (test-util/update-group token concept_id2 (assoc group2 :name (:name group1)))))))
+
+    (testing "prevent the same provider from re-using group names"
+      (is (= {:status 409
+              :errors [(format (str "A provider group with name [%s] already exists "
+                                    "with concept id [%s] for provider [%s].")
+                               (:name group1)
+                               concept_id1
+                               (:provider_id group1))]}
+             (test-util/update-group token concept_id1a (assoc group1a :name (:name group1))))))
+
+    (testing "allow different providers to re-use group names"
+      (is (= {:status 200
+              :revision_id 2
+              :concept_id (format "%s" concept_id2)}
+             (test-util/update-group token concept_id2 (assoc group2 :name (:name group1))))))))

 (deftest update-group-legacy-guid-test
   (let [group1 (test-util/make-group {:legacy_guid "legacy_guid_1" :name "group1"})


renames the metric group in test-request-latency-apache-bench to `stress_test` (#209)

--- waiter/integration/waiter/latency_test.clj
+++ waiter/integration/waiter/latency_test.clj
@@ -80,7 +80,7 @@
                          :x-waiter-scale-down-factor 0.001
                          :x-waiter-scale-up-factor 0.999
                          :x-waiter-concurrency-level waiter-concurrency-level
-                         :x-waiter-metric-group "apache_bench"}
+                         :x-waiter-metric-group "stress_test"}
           headers (merge (kitchen-request-headers) extra-headers)
           endpoint "/endpoint"
           _ (log/info (str "Making canary request..."))


Fix health-check-max-consecutive-failures on K8s (#551)

--- waiter/src/waiter/scheduler/kubernetes.clj
+++ waiter/src/waiter/scheduler/kubernetes.clj
@@ -698,7 +698,10 @@
                                               :livenessProbe {:httpGet {:path health-check-url
                                                                         :port port0
                                                                         :scheme backend-protocol-upper}
-                                                              :failureThreshold health-check-max-consecutive-failures
+                                                              ;; We increment the threshold value to match Marathon behavior.
+                                                              ;; Marathon treats this as a retry count,
+                                                              ;; whereas Kubernetes treats it as a run count.
+                                                              :failureThreshold (inc health-check-max-consecutive-failures)
                                                               :initialDelaySeconds grace-period-secs
                                                               :periodSeconds health-check-interval-secs
                                                               :timeoutSeconds 1}