Part 4

Part 4

--- resources/workshop/do-things.clj
+++ resources/workshop/do-things.clj
@@ -1176,3 +1176,438 @@
 "Woohoo!"

 [[:chapter {:tags "mise_en_commun" :title "Mise en commun"}]]
+
+"D'ACCORD! Disons tirer tout cela ensemble et utiliser nos connaissances pour un but noble: la fessée autour hobbits!
+
+Afin de frapper un hobbit, nous allons d'abord modéliser ses parties du corps. Chaque partie du corps comprendra sa taille par rapport à nous aider à déterminer quelle est la probabilité que cette partie sera frappé.
+
+Afin d'éviter les répétitions, ce modèle de hobbit ne inclure des entrées pour "pied gauche", "oreille gauche", etc. Par conséquent, nous aurons besoin d'une fonction pour symétriser complètement le modèle.
+
+Enfin, nous allons créer une fonction qui parcourt nos parties du corps et choisit au hasard l'un hit.
+
+Fun!"
+
+[[:section {:tags "the_shire_s_next_top_model" :title "The Shire's Next Top Model"}]]
+
+"Pour notre modèle de hobbit, nous évitons des caractéristiques telles que «jovialité» et «malice» et se concentrer uniquement sur la petite corps du hobbit. Voici notre modèle de hobbit:"
+
+(comment
+  (  def  asym-hobbit-body-parts  [{  :name  "head"  :size  3  }
+                                   {  :name  "left-eye"  :size  1  }
+                                   {  :name  "left-ear"  :size  1  }
+                                   {  :name  "mouth"  :size  1  }
+                                   {  :name  "nose"  :size  1  }
+                                   {  :name  "neck"  :size  2  }
+                                   {  :name  "left-shoulder"  :size  3  }
+                                   {  :name  "left-upper-arm"  :size  3  }
+                                   {  :name  "chest"  :size  10  }
+                                   {  :name  "back"  :size  10  }
+                                   {  :name  "left-forearm"  :size  3  }
+                                   {  :name  "abdomen"  :size  6  }
+                                   {  :name  "left-kidney"  :size  1  }
+                                   {  :name  "left-hand"  :size  2  }
+                                   {  :name  "left-knee"  :size  2  }
+                                   {  :name  "left-thigh"  :size  4  }
+                                   {  :name  "left-lower-leg"  :size  3  }
+                                   {  :name  "left-achilles"  :size  1  }
+                                   {  :name  "left-foot"  :size  2  }])
+
+  )
+
+"Ce est un vecteur de cartes. Chaque carte a le nom de la partie du corps et la taille relative de la partie du corps. Ecoutez, je sais que seuls personnages de dessins animés ont des yeux 1/3 de la taille de leur tête, mais juste aller avec elle, OK?
+
+Manifestement absent est le côté droit du hobbit. Fixons cela.Le code ci-dessous est le code le plus complexe que nous avons examiné jusqu'ici. Il introduit quelques idées que nous ne avons pas encore couverts. Ne vous inquiétez pas cependant, parce que nous allons examiner en détail:
+
+"
+
+(comment
+  (defn needs-matching-part?
+    [part]
+    (re-find #"^left-" (:name part)))
+
+  (defn make-matching-part
+    [part]
+    {:name (clojure.string/replace (:name part) #"^left-" "right-")
+     :size (:size part)})
+
+  (defn symmetrize-body-parts
+    "Expects a seq of maps which have a :name and :size"
+    [asym-body-parts]
+    (loop [remaining-asym-parts asym-body-parts
+           final-body-parts []]
+      (if (empty? remaining-asym-parts)
+        final-body-parts
+        (let [[part & remaining] remaining-asym-parts
+              final-body-parts (conj final-body-parts part)]
+          (if (needs-matching-part? part)
+            (recur remaining (conj final-body-parts (make-matching-part part)))
+            (recur remaining final-body-parts))))))
+
+  (symmetrize-body-parts asym-hobbit-body-parts)
+  ; => the following is the return value
+  [{:name "head", :size 3}
+   {:name "left-eye", :size 1}
+   {:name "right-eye", :size 1}
+   {:name "left-ear", :size 1}
+   {:name "right-ear", :size 1}
+   {:name "mouth", :size 1}
+   {:name "nose", :size 1}
+   {:name "neck", :size 2}
+   {:name "left-shoulder", :size 3}
+   {:name "right-shoulder", :size 3}
+   {:name "left-upper-arm", :size 3}
+   {:name "right-upper-arm", :size 3}
+   {:name "chest", :size 10}
+   {:name "back", :size 10}
+   {:name "left-forearm", :size 3}
+   {:name "right-forearm", :size 3}
+   {:name "abdomen", :size 6}
+   {:name "left-kidney", :size 1}
+   {:name "right-kidney", :size 1}
+   {:name "left-hand", :size 2}
+   {:name "right-hand", :size 2}
+   {:name "left-knee", :size 2}
+   {:name "right-knee", :size 2}
+   {:name "left-thigh", :size 4}
+   {:name "right-thigh", :size 4}
+   {:name "left-lower-leg", :size 3}
+   {:name "right-lower-leg", :size 3}
+   {:name "left-achilles", :size 1}
+   {:name "right-achilles", :size 1}
+   {:name "left-foot", :size 2}
+   {:name "right-foot", :size 2}]
+  )
+
+"Let's break this down!"
+[[:section {:tags "let" :title "let"}]]
+
+"Dans notre symétriseur ci-dessus, nous avons vu ce qui suit:"
+
+(comment
+
+  (let [[part & remaining] remaining-asym-parts
+        final-body-parts (conj final-body-parts part)]
+    some-stuff)
+  )
+
+
+"Tout cela ne est lier les noms sur la gauche pour les valeurs sur la droite. Vous pouvez penser à \"let\" le plus court pour \"Let it be\", qui est aussi une belle chanson des Beatles (au cas où vous ne saviez pas (dans ce cas, wtf?)). Par exemple, \"Laissez -finale parties de corps soient (conj-finales parties de corps partie) . \""
+
+"Voici quelques exemples simples:"
+
+(comment
+
+  (let [x 3]
+    x)
+  ; => 3
+
+
+  (def dalmatian-list
+    ["Pongo" "Perdita" "Puppy 1" "Puppy 2"]) ; and 97 more...
+  (let [dalmatians (take 2 dalmatian-list)]
+    dalmatians)
+  ; => ("Pongo" "Perdita")
+  )
+
+
+"*let*  introduit également une nouvelle portée:"
+
+(comment
+  (def x 0)
+  (let [x 1] x)
+  ; => 1
+  )
+
+"Cependant, vous pouvez référencer les liaisons existantes dans votre let contraignant:"
+
+(comment
+  (def x 0)
+  (let [x (inc x)] x)
+  ; => 1
+  )
+
+"Vous pouvez également utiliser repos-params de let , tout comme vous pouvez en fonctions:"
+
+(comment
+
+  (let [[pongo & dalmatians] dalmatian-list]
+    [pongo dalmatians])
+  ; => ["Pongo" ("Perdita" "Puppy 1" "Puppy 2")]
+  )
+
+"Notez que la valeur d'un *let* forme est la dernière forme dans son corps qui obtient évaluée.
+
+*let* formes suivent les règles de déstructuration qui nous introduit dans «Appel d'une fonction\" ci-dessus.
+
+Une façon de penser *let* formes, ce est qu'ils fournissent des paramètres et leurs arguments secondaires à côte. *let* formes ont deux utilisations principales:
+
+*Ils fournissent la clarté en vous permettant de nommer les choses
+*Ils vous permettent d'évaluer une expression qu'une seule fois et ré-utiliser le résultat. Ceci est particulièrement important lorsque vous avez besoin de réutiliser le résultat d'un appel de fonction coûteux, comme un appel d'API de réseau. Il est également important lorsque l'expression a des effets secondaires.
+Ayons un autre regard sur  *let* forme dans notre fonction de symétrisation afin que nous puissions comprendre exactement ce qui se passe:"
+
+
+(comment
+  ;; Associate "part" with the first element of "remaining-asym-parts"
+  ;; Associate "remaining" with the rest of the elements in "remaining-asym-parts"
+  ;; Associate "final-body-parts" with the result of (conj final-body-parts part)
+  (let [[part & remaining] remaining-asym-parts
+        final-body-parts (conj final-body-parts part)]
+    (if (needs-matching-part? part)
+      (recur remaining (conj final-body-parts (make-matching-part part)))
+      (recur remaining final-body-parts)))
+  )
+
+"Notez que *part* , *remaining*, et *final-body-parts* de corps sont utilisé plusieurs fois dans le corps du *let* . Si, au lieu d'utiliser les noms *part* , *remaining*, et *final-body-parts* , nous avons utilisé les expressions originales, ce serait un gâchis! Par exemple:"
+
+
+(comment
+
+  (if (needs-matching-part? (first remaining-asym-parts))
+    (recur (rest remaining-asym-parts)
+      (conj (conj final-body-parts (first remaining-asym-parts))
+        (make-matching-part (first remaining-asym-parts))))
+    (recur (rest remaining-asm-parts)
+      (conj (conj final-body-parts (first remaining-asym-parts)))))
+  )
+
+"Alors, let est un moyen pratique d'introduire des noms pour les valeurs."
+
+[[:section {:tags "boucle" :title " boucle"}]]
+
+"Loop fournit une autre façon de faire la récursivité dans Clojure. Regardons un exemple simple:"
+
+(comment
+
+  (loop [iteration 0]
+    (println (str "Iteration " iteration))
+    (if (> iteration 3)
+      (println "Goodbye!")
+      (recur (inc iteration))))
+  ; =>
+  Iteration 0
+  Iteration 1
+  Iteration 2
+  Iteration 3
+  Iteration 4
+  Goodbye!
+  )
+
+"La première ligne, *loop [itération 0]* commence la boucle et présente une liaison avec une valeur initiale. Ce est presque comme appeler une fonction anonyme avec une valeur par défaut. Au premier passage dans la boucle, *iteration* a une valeur de 0.
+
+Ensuite, il imprime un petit message super intéressant.
+
+Ensuite, il vérifie la valeur de *iteration* - si elle est supérieure à 3, alors il est temps de dire au revoir. Sinon, nous bouclons via *recur* . Ce est comme appeler la fonction anonyme créée par *loop* , mais cette fois nous passons un argument, (itération inc) .
+
+Vous pourriez en fait accomplir la même chose tout en utilisant les fonctions:"
+
+(comment
+
+  (defn recursive-printer
+    ([]
+      (recursive-printer 0))
+    ([iteration]
+      (println (str "Iteration " iteration))
+      (if (> iteration 3)
+        (println "Goodbye!")
+        (recursive-printer (inc iteration)))))
+  (recursive-printer)
+  ; =>
+  Iteration 0
+  Iteration 1
+  Iteration 2
+  Iteration 3
+  Iteration 4
+  Goodbye!
+  )
+
+"Comme vous pouvez le voir, ce est un peu plus verbeux. En outre, la boucle a de bien meilleures performances."
+
+
+[[:section {:tags "expressions_regulieres" :title "Expressions régulières"}]]
+
+"Les expressions régulières sont des outils pour effectuer le filtrage sur le texte. Je ne entrerai pas dans la façon dont ils travaillent, mais voici leur notation littérale:"
+(comment
+  ;; pound, open quote, close quote
+  #"regular-expression"
+  )
+
+"Dans notre symétriseur, re-trouver renvoie true ou false selon que le nom de la partie commence par la chaîne \"gauche\":"
+
+(comment
+  (defn needs-matching-part?
+    [part]
+    (re-find #"^left-" (:name part)))
+  (needs-matching-part? {:name "left-eye"})
+  ; => true
+  (needs-matching-part? {:name "neckbeard"})
+  ; => false
+  )
+
+
+"*make-matching-part* utilise une expression régulière pour remplacer \" *left \" par \"* right- \" :"
+
+
+[[:section {:tags "symetriseur" :title "Symétriseur"}]]
+
+"Maintenant, nous allons analyser le symétriseur pleinement. Remarque points de flottent dans l'océan, comme *~~~1~~~* :"
+
+(comment
+  (def asym-hobbit-body-parts [{:name "head" :size 3}
+                               {:name "left-eye" :size 1}
+                               {:name "left-ear" :size 1}
+                               {:name "mouth" :size 1}
+                               {:name "nose" :size 1}
+                               {:name "neck" :size 2}
+                               {:name "left-shoulder" :size 3}
+                               {:name "left-upper-arm" :size 3}
+                               {:name "chest" :size 10}
+                               {:name "back" :size 10}
+                               {:name "left-forearm" :size 3}
+                               {:name "abdomen" :size 6}
+                               {:name "left-kidney" :size 1}
+                               {:name "left-hand" :size 2}
+                               {:name "left-knee" :size 2}
+                               {:name "left-thigh" :size 4}
+                               {:name "left-lower-leg" :size 3}
+                               {:name "left-achilles" :size 1}
+                               {:name "left-foot" :size 2}])
+
+  (defn needs-matching-part?
+    [part]
+    (re-find #"^left-" (:name part)))
+
+  (defn make-matching-part
+    [part]
+    {:name (clojure.string/replace (:name part) #"^left-" "right-")
+     :size (:size part)})
+
+  ; ~~~1~~~
+  (defn symmetrize-body-parts
+    "Expects a seq of maps which have a :name and :size"
+    [asym-body-parts] ;
+    (loop [remaining-asym-parts asym-body-parts ; ~~~2~~~
+           final-body-parts []]
+      (if (empty? remaining-asym-parts) ; ~~~3~~~
+        final-body-parts
+        (let [[part & remaining] remaining-asym-parts ; ~~~4~~~
+              final-body-parts (conj final-body-parts part)]
+          (if (needs-matching-part? part) ; ~~~5~~~
+            (recur remaining (conj final-body-parts (make-matching-part part))) ; ~~~6~~~
+            (recur remaining final-body-parts))))))
+  )
+
+
+"1. Cette fonction utilise une stratégie générale qui est commun dans la programmation fonctionnelle.
+ Compte tenu d'une séquence (dans ce cas, un vecteur de parties du corps et de leurs tailles), divisé en continu la séquence dans une «tête» et une «queue».Traiter la tête, l'ajouter à un certain résultat, et ensuite utiliser la récursivité pour poursuivre le processus avec la queue.
+
+2. Commencez boucle sur les parties du corps. La \"queue\" de la séquence sera lié à *remaining-asym-parts* . Initialement, il est lié à la séquence complète passée à la fonction, *asym-body-parts* . Créer une séquence de résultats, *final-body-parts* ; sa valeur initiale est un vecteur vide.
+
+
+3. Si remaining-asym-parts est vide, cela signifie que nous avons traité la séquence entière et nous pouvons retourner le résultat, *final-body-parts*.
+
+4. Sinon, diviser la liste en tête, partie , et la queue, *remaining* . En outre, ajouter une *part* à *final-body-parts* de corps et re-lier le résultat du nom *final-body-parts* . Cela peut sembler bizarre, et il est intéressant de comprendre pourquoi cela fonctionne.
+
+5. Notre séquence croissante de *final-body-parts* comprend déjà la partie du corps que nous sommes en train d'examiner, partie . Ici, nous décidons si nous devons ajouter la partie du corps correspondant à la liste.
+
+6.Si oui, puis ajouter le résultat de *make-matching-part* à *final-body-parts* de corps et de se reproduire. Sinon, se reproduire.
+
+
+Si vous êtes nouveau à ce genre de programmation, cela pourrait prendre un certain temps de déchiffrer. Rester avec elle! Une fois que vous comprenez ce qui se passe, vous vous sentirez comme un million de dollars!
+"
+
+[[:section {:tags "symetriseur_reduice" :title "Symétriseur et reduice"}]]
+
+"Le modèle de «traiter chaque élément d'une séquence et de construire un résultat\" est si commun qu'il ya une fonction pour cela: réduire .
+
+Voici un exemple simple:"
+
+(comment
+  ;; sum with reduce
+  (reduce + [1 2 3 4])
+  ; => 10
+  )
+
+"C'est comme demander à Clojure de faire ca:"
+
+(comment
+
+  (+ (+ (+ 1 2) 3) 4)
+
+  )
+
+"C'est a dire :"
+
+"1. Appliquer la fonction donnée pour les deux premiers éléments d'une séquence. Ce est là (+ 1 2) vient.
+2. Appliquer la fonction donnée pour le résultat et l'élément suivant de la séquence. Dans ce cas, le résultat de l'étape 1 est 3 , et l'élément suivant de la séquence est 3 aussi. Donc, vous vous retrouvez avec (3 + 3) .
+3. Répétez l'étape 2 pour chaque élément restant dans la séquence.
+Reduce prend également une valeur initiale en option. 15 est la valeur initiale ici:"
+
+(comment
+  (reduce + 15 [1 2 3 4])
+  )
+
+"Si vous fournissez une valeur initiale, puis réduire commence en appliquant la fonction donnée à la valeur initiale et le premier élément de la séquence, plutôt que les deux premiers éléments de la séquence.
+
+Pour mieux comprendre comment réduire œuvres, voici une façon qu'il puisse être mis en œuvre:"
+
+(comment
+  (defn my-reduce
+    ([f initial coll]
+      (loop [result initial
+             remaining coll]
+        (if (empty? remaining)
+          result
+          (recur (f result (first remaining)) (rest remaining)))))
+    ([f [head & tail]]
+      (my-reduce f head tail)))
+  )
+
+"Nous pourrions ré-implémenter Symétriser comme suit:"
+
+(comment
+
+  (defn better-symmetrize-body-parts
+    "Expects a seq of maps which have a :name and :size"
+    [asym-body-parts]
+    (reduce (fn [final-body-parts part]
+              (let [final-body-parts (conj final-body-parts part)]
+                (if (needs-matching-part? part)
+                  (conj final-body-parts (make-matching-part part))
+                  final-body-parts)))
+      []
+      asym-body-parts))
+  )
+
+"Sympa !"
+
+
+[[:chapter {:tags "hobbit_violence" :title "Hobbit violence"}]]
+
+"Ma parole, ce est vraiment Clojure pour les braves et True!
+
+Maintenant, nous allons créer une fonction qui permettra de déterminer quelle partie du hobbit se fait frapper:"
+
+(comment
+
+  (defn hit
+    [asym-body-parts]
+    (let [sym-parts (better-symmetrize-body-parts asym-body-parts)
+          body-part-size-sum (reduce + 0 (map :size sym-parts))
+          target (inc (rand body-part-size-sum))]
+      (loop [[part & rest] sym-parts
+             accumulated-size (:size part)]
+        (if (> accumulated-size target)
+          part
+          (recur rest (+ accumulated-size (:size part)))))))
+
+  (hit asym-hobbit-body-parts)
+  ; => {:name "right-upper-arm", :size 3}
+
+  (hit asym-hobbit-body-parts)
+  ; => {:name "chest", :size 10}
+
+  (hit asym-hobbit-body-parts)
+  ; => {:name "left-eye", :size 1}
+  )
+
+"Oh mon dieu, ce pauvre hobbit! Vous monstre!"


comment about inbound events

comment about inbound events

--- src/launchpad/core.clj
+++ src/launchpad/core.clj
@@ -59,6 +59,11 @@
   "Light right button 0-7"
   [m n col]
   (light m 8 n col))
+
 ;; That should do it. There's more about intensity (wishlist) and about
 ;; double buffering and other tricks for more efficient updates, which I
 ;; may utilize when doing react-style
+
+;; well actually I should do input handling too. but in the context of
+;; the richer api, because we have to at least keep track of the event
+;; handlers.


Add 'remotes

Add 'remotes

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -89,6 +89,18 @@
 (def repos-home (or (System/getenv "REPOS_HOME")
                     (str (System/getProperty "user.home")
                          (str "/.voom-repos"))))
+
+(defn remotes
+  "For a given .git directory, returns a map like:
+  {:origin {:push  \"git@github.com:abrooks/lein-voom.git\",
+            :fetch \"git@github.com:abrooks/lein-voom.git\"}}"
+  [gitdir]
+  (reduce
+   (fn [m line]
+     (let [[_ remote url direction] (re-matches #"(.*)\t(.*)\s+\(([^)]*)\)$" line)]
+       (assoc-in m [(keyword remote) (keyword direction)] url)))
+   {}
+   (:lines (git {:gitdir gitdir} "remote" "-v"))))

 (defn with-log-level [level f]
   (let [handlers (doall (.getHandlers (Logger/getLogger "")))


Add an items fn that returns the items (for saving)

--- src/compound/core.cljc
+++ src/compound/core.cljc
@@ -163,3 +163,7 @@
                                                       {}
                                                       (secondary-indexes-by-id compound))))

+(defn items [compound]
+  (vals (primary-index compound)))
+
+


Make clj-http alias consistent across acceptance & integration

--- src/leiningen/new/cljskel/integration.clj
+++ src/leiningen/new/cljskel/integration.clj
@@ -1,6 +1,6 @@
 (ns {{name}}.integration
   (:require [{{name}}.test-common :refer :all])
-  (:require [clj-http.client :as client]
+  (:require [clj-http.client :as http]
             [midje.sweet :refer :all]
             [environ.core :refer [env]])
   (:import [java.util UUID]))
@@ -9,9 +9,9 @@
  :integration

    (fact "Ping resource returns 200 HTTP response"
-         (let [response (client/get (url+ "/ping")  {:throw-exceptions false})]
+         (let [response (http/get (url+ "/ping")  {:throw-exceptions false})]
            response => (contains {:status 200})))

  (fact "Healthcheck resource returns 200 HTTP response"
-       (let [response (client/get (url+ "/healthcheck") {:throw-exceptions false})]
+       (let [response (http/get (url+ "/healthcheck") {:throw-exceptions false})]
          response => (contains {:status 200}))))


upped chazel to include cluster group creds

--- dash/project.clj
+++ dash/project.clj
@@ -9,7 +9,7 @@
   :jvm-opts ["-Dconf=./resources/conf/hface.conf"]

   :dependencies [[org.clojure/clojure "1.6.0"]
-                 [chazel "0.1.1"]
+                 [chazel "0.1.2-SNAPSHOT"]
                  [cprop "0.1.0"]
                  [com.gitpod/hface-client "0.1.0"]
                  [com.facebook/react "0.11.2"]


fix async code

fix async code

--- examples/pedestal/src/example/server.clj
+++ examples/pedestal/src/example/server.clj
@@ -9,6 +9,16 @@
   {:enter (fn [ctx] (println ">>" x) ctx)
    :leave (fn [ctx] (println "<<" x) ctx)})

+(defn handler [_]
+  (println "handler")
+  {:status 200,
+   :body "pong"})
+
+(def async-handler
+  {:enter (fn [{:keys [request] :as ctx}]
+            (a/go
+              (assoc ctx :response (handler request))))})
+
 (def routing-interceptor
   (pedestal/routing-interceptor
     (http/router
@@ -19,19 +29,11 @@
        ["/sync"
         {:interceptors [[interceptor :sync]]
          :get {:interceptors [[interceptor :get]]
-               :handler (fn [_]
-                          (println "handler")
-                          {:status 200,
-                           :body "pong"})}}]
+               :handler handler}}]

        ["/async"
         {:interceptors [[interceptor :async]]
-         :get {:interceptors [[interceptor :get]]
-               :handler (fn [_]
-                          (a/go
-                            (println "handler")
-                            {:status 200,
-                             :body "pong"}))}}]]
+         :get {:interceptors [[interceptor :get] async-handler]}}]]
       {:data {:interceptors [[interceptor :router]]}})
     (ring/create-default-handler)
     {:interceptors [[interceptor :top]]}))


Make the fleet state table look a little nicer.

--- src-cljs/frontend/components/admin.cljs
+++ src-cljs/frontend/components/admin.cljs
@@ -42,7 +42,11 @@
            [:a {:on-click #(raise! owner [:refresh-admin-fleet-state-clicked])} "Refresh"]]
           (if-not fleet-state
             [:div.loading-spinner common/spinner]
-            [:table
+            ;; FIXME: This table shouldn't really be .recent-builds-table; it's
+            ;; a hack to steal a bit of styling from the builds table until we
+            ;; properly address the styling for this table and admin tools in
+            ;; general.
+            [:table.recent-builds-table
              [:thead
               [:tr
                [:th "Instance ID"]
@@ -55,7 +59,7 @@
                 [:tr
                  [:td (:instance_id instance)]
                  [:td (:ec2_instance_type instance)]
-                 [:td (:boot_time instance)]
+                 [:td (datetime/long-datetime (:boot_time instance))]
                  [:td (:busy instance) " / " (:total instance)]
                  [:td (:state instance)]])]])])))))


LD flag for Team page in nav

LD flag for Team page in nav

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -491,12 +491,20 @@
               [:i.material-icons "library_add"]
               [:div.nav-label "Add Projects"]])

-            [:a.aside-item {:href "/invite-teammates",
-                            :data-placement "right"
-                            :data-trigger "hover"
-                            :title "Add Teammates"}
+           (if (feature/enabled? :team-page)
+             [:a.aside-item {:href "/team",
+                             :data-placement "right"
+                             :data-trigger "hover"
+                             :title "Team"}
+              [:i.material-icons "group"]
+              [:div.nav-label "Team"]]
+
+             [:a.aside-item {:href "/invite-teammates",
+                             :data-placement "right"
+                             :data-trigger "hover"
+                             :title "Add Teammates"}
               [:i.material-icons "group_add"]
-              [:div.nav-label "Team"]]
+              [:div.nav-label "Team"]])

             [:a.aside-item {:data-placement "right"
                                    :data-trigger "hover"


Added measurements row.

Added measurements row.

--- src-cljs/kixi/hecuba/tabs/profiles.cljs
+++ src-cljs/kixi/hecuba/tabs/profiles.cljs
@@ -49,7 +49,6 @@
   (reify
     om/IRenderState
     (render-state [_ state]
-      (println "Number of profiles: " (count profiles))
       (html
        [:div.col-md-12
         (for [profile profiles]
@@ -63,6 +62,29 @@
                [:dt "Occupancy Over 60"] [:dd (display profile_data :occupancy_over_60)]
                [:dt "Occupant Change"] [:dd (display profile_data :occupant_change)]])]))]))))

+(defn measurements-row [profiles ownwer]
+  (reify
+    om/IRenderState
+    (render-state [_ state]
+      (html
+       [:div.col-md-12
+        (for [profile profiles]
+          (let [profile_data (:profile_data profile)]
+            [:div {:class (profile-column-width)}
+             (bs/panel
+              "Measurements"
+              [:dl
+               [:dt "Footprint (internal groundfloor area (m2)"] [:dd (display profile_data :footprint)]
+               [:dt "External Perimeter (m)"] [:dd (display profile_data :external_perimeter)]
+               [:dt "Gross Internal Area (m2)"] [:dd (display profile_data :gross_internal_area)]
+               [:dt "Number Of Storeys"] [:dd (display profile_data :number_of_storeys)]
+               [:dt "Total Volume (m3)"] [:dd (display profile_data :total_volume)]
+               [:dt "Total Rooms"] [:dd (display profile_data :total_rooms)]
+               [:dt "Total Bedrooms"] [:dd (display profile_data :bedroom_count)]
+               [:dt "Habitable Rooms"] [:dd (display profile_data :habitable_rooms)]
+               [:dt "Inadequate Heating?"] [:dd (display profile_data :inadequate_heating)]
+               [:dt "Heated Habitable Rooms"] [:dd (display profile_data :heated_habitable_rooms)]])]))]))))
+
 (defn profile-rows [profiles owner]
   (reify
     om/IRenderState
@@ -71,7 +93,7 @@
        [:div.col-md-12
         (om/build header-row profiles)
         (om/build occupancy-row profiles)
-        ;; (om/build measurements profiles)
+        (om/build measurements-row profiles)
         ;; (om/build energy profiles)
         ;; (om/build efficiency profiles)
         ;; (om/build flats profiles)


Allow any keys in paramters, related to #145

--- modules/reitit-core/src/reitit/spec.cljc
+++ modules/reitit-core/src/reitit/spec.cljc
@@ -74,7 +74,7 @@
 ;; coercion
 ;;

-(s/def :reitit.core.coercion/kw-map (s/or :map (s/map-of keyword? any?) :spec s/spec?))
+(s/def :reitit.core.coercion/kw-map (s/or :map (s/map-of any? any?) :spec s/spec?))

 (s/def :reitit.core.coercion/query :reitit.core.coercion/kw-map)
 (s/def :reitit.core.coercion/body :reitit.core.coercion/kw-map)


read-tagged: add *default-data-reader-fn* support

--- src/main/clojure/clojure/tools/reader.clj
+++ src/main/clojure/clojure/tools/reader.clj
@@ -17,6 +17,14 @@
 (defn- char [x]
   (when x
     (clojure.core/char x)))
+
+;; getColumnNumber and *default-data-reader-fn* are available only since clojure-1.5.0-beta1
+(def ^:private >=clojure-1-5-alpha*?
+  (let [{:keys [minor qualifier]} *clojure-version*]
+    (and (>= minor 5)
+         (not= "alpha"
+               (when qualifier
+                 (subs qualifier 0 (dec (count qualifier))))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; reader protocols
@@ -145,18 +153,10 @@
     (when c
       (.unread ^java.io.PushbackReader rdr (int c)))))

-;; getColumnNumber is available only since clojure-1.5.0-beta1
-(def ^:private getColumnNumber?
-  (let [{:keys [minor qualifier]} *clojure-version*]
-    (and (>= 5 minor)
-         (not= "alpha"
-               (when qualifier
-                 (subs qualifier 0 (dec (count qualifier))))))))
-
 (extend LineNumberingPushbackReader
   IndexingReader
   {:get-line-number (fn [rdr] (.getLineNumber ^LineNumberingPushbackReader rdr))
-   :get-column-number (if getColumnNumber?
+   :get-column-number (if >=clojure-1-5-alpha*?
                         (fn [rdr]
                           (.getColumnNumber ^LineNumberingPushbackReader rdr))
                         (fn [rdr] 0))})
@@ -914,6 +914,10 @@
             (Reflector/invokeStaticMethod class "create" (object-array [vals])))))
       (reader-error rdr "Invalid reader constructor form"))))

+(def default-data-reader-fn
+  (when >=clojure-1-5-alpha*?
+    (resolve '*default-data-reader-fn*)))
+
 (defn read-tagged [rdr initch]
   (let [tag (read rdr true nil false)]
     (if-not (symbol? tag)
@@ -923,7 +927,9 @@
       (read-tagged* rdr tag f)
       (if (.contains (name tag) ".")
         (read-ctor rdr tag)
-        (reader-error rdr "No reader function for tag " (name tag))))))
+        (if-let [f @default-data-reader-fn]
+          (f tag (read rdr true nil true))
+          (reader-error rdr "No reader function for tag " (name tag)))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Public API


more refactoring of metamodel related stuff outof operations

--- src/main/clojure/org/dada/demo/whales.clj
+++ src/main/clojure/org/dada/demo/whales.clj
@@ -221,63 +221,64 @@
 (import org.dada.core.View)
 (import org.dada.core.Update)

-(defn meta-view [#^Model src-metamodel tgt-metamodel f]
+(defn meta-view [#^String suffix #^Model src-metamodel f]
+  (let [tgt-metamodel (model (str (.getName src-metamodel) suffix) nil (.getMetadata src-metamodel))]
   (insert *metamodel* tgt-metamodel)
   (connect
    src-metamodel
    (proxy [View] []
 	  (update [insertions alterations deletions]
-		  (doall (map (fn [#^Update insertion] (apply f (.getNewValue insertion))) insertions))))))
+		  (doall (map (fn [#^Update insertion] (apply f tgt-metamodel (.getNewValue insertion))) insertions)))))
+  tgt-metamodel))

 (defn split [[#^Model src-metamodel #^Metadata src-metadata #^Collection extra-keys] split-key
 	     & [split-key-fn]]
-  (let [tgt-metamodel (model (str (.getName src-metamodel) ".split(" split-key")") nil (.getMetadata src-metamodel))]
-    (meta-view
-     src-metamodel
-     tgt-metamodel
-     (fn [model & extra-values]
-	 (do-split
-	  model
-	  split-key
-	  (or split-key-fn list)
-	  identity
-	  (fn [#^Model model extra-value]
-	      (let [model-entry (list* model (concat extra-values [extra-value]))]
-		(insert tgt-metamodel model-entry)
-		(insert *metamodel* model)
-		)))))
-    [tgt-metamodel src-metadata (concat extra-keys [split-key])]))
+  [(meta-view
+    (str ".split(" split-key")")
+    src-metamodel
+    (fn [tgt-metamodel model & extra-values]
+	(do-split
+	 model
+	 split-key
+	 (or split-key-fn list)
+	 identity
+	 (fn [#^Model model extra-value]
+	     (let [model-entry (list* model (concat extra-values [extra-value]))]
+	       (insert tgt-metamodel model-entry)
+	       (insert *metamodel* model)
+	       )))))
+   src-metadata
+   (concat extra-keys [split-key])])

 ;; extra keys are inserted into attribute list
 ;; extra values are carried in model's row in metamodel
 ;; each split adds an extra key/value downstream that we may need to unwrap upstream
 (defn ccount [[#^Model src-metamodel #^Metadata src-metadata #^Collection extra-keys]
 	      & [count-key]]
-  (let [tgt-metamodel (model (str (.getName src-metamodel) ".count(" (or count-key "") ")") nil (.getMetadata src-metamodel))
-	extra-attributes (map (fn [key] (.getAttribute src-metadata key)) extra-keys)
+  (let [extra-attributes (map (fn [key] (.getAttribute src-metadata key)) extra-keys)
 	tgt-metadata (count-reducer-metadata extra-keys count-key extra-attributes)]
-    (meta-view
-     src-metamodel
-     tgt-metamodel
-     (fn [#^Model src-model & extra-values]
-	 (let [count-model (do-reduce-count
-			    (.getName src-model)
-			    (.getMetadata src-model)
-			    tgt-metadata
-			    count-key
-			    extra-values)]
-	   (insert *metamodel* count-model)
-	   (insert tgt-metamodel (list* count-model extra-values))
-	   (connect src-model count-model))))
-    [tgt-metamodel tgt-metadata extra-keys]))
+    [(meta-view
+      (str "." (count-value-key count-key))
+      src-metamodel
+      (fn [tgt-metamodel #^Model src-model & extra-values]
+	  (let [count-model (do-reduce-count
+			     (.getName src-model)
+			     (.getMetadata src-model)
+			     tgt-metadata
+			     count-key
+			     extra-values)]
+	    (insert *metamodel* count-model)
+	    (insert tgt-metamodel (list* count-model extra-values))
+	    (connect src-model count-model))))
+     tgt-metadata
+     extra-keys]))

 (defn union [[#^Model src-metamodel #^Metadata src-metadata #^Collection extra-keys] #^String prefix]
-  (let [tgt-metamodel (model (str (.getName src-metamodel) ".union()") nil (.getMetadata src-metamodel))
-	tgt-model (model (str prefix ".union()") nil src-metadata)]
+  (let [tgt-model (model (str prefix ".union()") nil src-metadata)
+	tgt-metamodel (meta-view ".union()" src-metamodel (fn [tgt-metamodel src-model & extra-values] (connect src-model tgt-model)))]
     (insert *metamodel* tgt-model)
     (insert tgt-metamodel [tgt-model])
-    (meta-view src-metamodel tgt-metamodel (fn [src-model & extra-values] (connect src-model tgt-model)))
     [tgt-metamodel src-metadata extra-keys]))

 ;;--------------------------------------------------------------------------------


MIDI bindings

MIDI bindings

--- src/lights/my_show.clj
+++ src/lights/my_show.clj
@@ -213,6 +213,8 @@
         "Automap MIDI" 10 21 :sparkle-chance :min 0 :max 0.5)
       (show/add-midi-control-to-var-mapping
         "Automap MIDI" 10 22 :sparkle-fade :min 1 :max 2000)
+      (show/add-midi-control-to-cue-mapping "Automap MIDI" 10 :control 51 0 7)
+      (show/add-midi-control-to-cue-mapping "Automap MIDI" 10 :control 52 1 7)
     )
   )

@@ -391,6 +393,7 @@
       :fade-time :sparkle-fade))
         :held true
         :priority 100
+        :short-name "Sparkle all"
         ))

   (ct/set-cue! (:cue-grid *show*) 1 7
@@ -400,6 +403,7 @@
       :fade-time 400))
         :held true
         :priority 100
+        :short-name "Sparkle scene"
         ))

   (ct/set-cue! (:cue-grid *show*) 0 2
@@ -421,27 +425,33 @@
     ))))

   (ct/set-cue! (:cue-grid *show*) 0 0
-    (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 0))
+    (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 0))
+      :short-name "Red"
       )
     )
   (ct/set-cue! (:cue-grid *show*) 1 0
-    (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 60))
+    (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 60))
+      :short-name "Yellow"
       )
     )
   (ct/set-cue! (:cue-grid *show*) 2 0
-    (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 120))
+    (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 120))
+      :short-name "Green"
       )
     )
   (ct/set-cue! (:cue-grid *show*) 3 0
     (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 180))
+      :short-name "Blue"
       )
     )
   (ct/set-cue! (:cue-grid *show*) 4 0
     (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 240))
+      :short-name "Dark blue"
       )
     )
   (ct/set-cue! (:cue-grid *show*) 5 0
     (cues/cue :set-main-hue (fn [_] (var-fx/variable-effect @var-binder :main-hue 300))
+      :short-name "Purple"
       )
     )
 )


[base] Add cqrs/dispatch!

[base] Add cqrs/dispatch!

--- src/braid/base/server/cqrs_fx.clj
+++ src/braid/base/server/cqrs_fx.clj
@@ -3,10 +3,13 @@
   (:require
     [braid.base.server.socket :as socket]
     [braid.core.server.sync-helpers :as helpers]
-    [braid.core.server.db :as db]))
+    [braid.core.server.db :as db]
+    [braid.base.server.cqrs :as cqrs]))

 (def run-txns! db/run-txns!)

 (def chsk-send! socket/chsk-send!)

 (def group-broadcast! helpers/broadcast-group-change)
+
+(def dispatch! cqrs/dispatch)


Removed bullshitty test datasets.

Removed bullshitty test datasets.


lazy eval in the frame

lazy eval in the frame

--- src/cljs/triboard/view/frame.cljs
+++ src/cljs/triboard/view/frame.cljs
@@ -10,5 +10,5 @@
   [turn interactions]
   [:div.game-panel
    [panel/show-top-panel (turn/get-scores turn) (turn/current-player turn) interactions]
-   (board/render-board (turn/get-board turn) interactions)
+   [board/render-board (turn/get-board turn) interactions]
    ])


Remove unused format-number-short method

--- src/metabase/pulse.clj
+++ src/metabase/pulse.clj
@@ -54,14 +54,6 @@
 (defn- format-number
   [n]
   (if (integer? n) (cl-format nil "~:d" n) (cl-format nil "~,2f" n)))
-
-(defn- format-number-short
-  [n]
-  (cond
-    (>= n 1000000000) (str (cl-format nil "~,1f" (/ n 1000000000.0)) "B")
-    (>= n 1000000) (str (cl-format nil "~,1f" (/ n 1000000.0)) "M")
-    (>= n 1000) (str (cl-format nil "~,1f" (/ n 1000.0)) "K")
-    :else (str (cl-format nil "~,1f" n))))

 (defn- format-timestamp
   "Formats timestamps with human friendly absolute dates based on the column :unit"


Fixes Inbox counter

Fixes Inbox counter

--- src/front/ui/menu.cljs
+++ src/front/ui/menu.cljs
@@ -169,7 +169,11 @@
               :id "Inbox"
               :route "/inbox"
               :icon "inbox"
-              :badge #(:tasks (state/inbox))}]]
+              :badge #(filter (fn [t]
+                                (and (= "Inbox"
+                                        (:id (:project t)))
+                                     (not (:done t))))
+                              (state/all-tasks))}]]
     [menu-section-component
      :project-id project-id
      :title "Focus"


removed unnecessary print

removed unnecessary print

--- src/frontend/core.cljs
+++ src/frontend/core.cljs
@@ -72,10 +72,9 @@
 (.change (js/$ "#file-upload")
   (fn [e]
     (let [file (aget (.-files (.-target e)) 0)]
-      (println "SHIT " (:num-of-uploads @app-state))
-        (if (> (:upload-slots @app-state) (:num-of-uploads @app-state))
-          (upload-file file)
-          (swap! app-state assoc :upload-queue (vec (cons file (:upload-queue @app-state))))))))
+      (if (> (:upload-slots @app-state) (:num-of-uploads @app-state))
+        (upload-file file)
+        (swap! app-state assoc :upload-queue (vec (cons file (:upload-queue @app-state))))))))

 (.click (js/$ "#clear-songs-button")
   (fn [e]


fix dialog width

fix dialog width

--- src/cljs/swarmpit/component/dialog.cljs
+++ src/cljs/swarmpit/component/dialog.cljs
@@ -13,7 +13,7 @@
     (comp/dialog
       {:disableBackdropClick true
        :disableEscapeKeyDown true
-       :maxWidth             "400px"
+       :maxWidth             "xs"
        :open                 open
        :onEntering           #()
        :aria-labelledby      "confirmation-dialog-title"}


Fixed botched refactoring: leftover hello param

In the call to do-polling-loop. The raw-packet needs to be rebuilt
every time.

--- src/clojure/frereth_cp/client/hello.clj
+++ src/clojure/frereth_cp/client/hello.clj
@@ -258,7 +258,6 @@
          (assoc this
                 ::log-state log-state
                 ::state/server-ips remaining-ips)
-         raw-packet
          cookie-waiter
          (System/nanoTime)
          timeout-ms))


Use statement batching when inserting resources

We would previously do several SQL statements for insertion of a resource:

* insert its metadata
* N inserts for all of its parameters
* N inserts for all of its tags
* an insert to associate it with a catalog

...and we'd do that for all N resources in a catalog. That's a lot of queries.
Now, we use statement batching to queue up all the pending inserts on a
per-table basis. We then execute them in foreign-key-satisfying order:

* insert metadata for all resources in the catalog
* insert all resource parameters for all resources
* insert all resources tags for all resources
* associated all of the resources with the catalog

We do this all in a single round-trip to the database, saving a ton of wasted
time doing back-and-forth communication.

Note: this patch does not remove the query-per-resource penalty we pay when
determining if a resource exists. Even though that penalty remains, batched
inserts are still a pretty massive performance boost.

Signed-off-by: Deepak Giridharagopal <d11186354d1ef01ca06ae37d7e23e827da13e85f@puppetlabs.com>

--- src/com/puppetlabs/cmdb/scf/storage.clj
+++ src/com/puppetlabs/cmdb/scf/storage.clj
@@ -217,35 +217,54 @@
   (-> (resource-identity-string resource)
       (digest/sha-1)))

-(defn add-resource!
-  "Given a certname and a single resource, persist that resource and its parameters"
+(defn- resource->values
+  "Given a catalog-hash and a resource, return a map representing the
+  set of database rows pending insertion.
+
+  The result map has the following format:
+
+    {:hashes [[<catalog hash> <resource hash>] ...]
+     :metadata [[<resouce hash> <type> <title> <exported?> <sourcefile> <sourceline>] ...]
+     :parameters [[<resource hash> <name> <value>] ...]
+     :tags [[<resource hash> <tag>] ...]}
+
+  The result map format may seem arbitrary and confusing, but its best
+  to think about it in 2 ways:
+
+  1. Each key corresponds to a table, and each value is a list of rows
+  2. The mapping of keys and values to table names and columns is done
+     by `add-resources!`"
   [catalog-hash {:keys [type title exported parameters tags file line] :as resource}]
-  {:pre [(every? string? #{type title})]}
+  {:pre  [(every? string? #{catalog-hash type title})]
+   :post [(= (set (keys %)) #{:hashes :metadata :parameters :tags})]}

   (let [resource-hash (resource-identity-hash resource)
-        persisted?    (resource-exists? resource-hash)
-        connection    (sql/find-connection)]
-
-    (when-not persisted?
-      ; Add to resources table
-      (sql/insert-record :resources {:hash resource-hash :type type :title title :exported exported :sourcefile file :sourceline line})
-
-      ; Build up a list of records for insertion
-      (let [records (for [[name value] parameters]
-                      ; Parameter values are represented as serialized strings,
-                      ; for ease of comparison.
-                      (let [value (db-serialize value)]
-                        {:resource resource-hash :name name :value value}))]
-
-        ; ...and insert them
-        (apply sql/insert-records :resource_params records))
-
-      ; Add rows for each of the resource's tags
-      (let [records (for [tag tags] {:resource resource-hash :name tag})]
-        (apply sql/insert-records :resource_tags records)))
-
-    ;; Insert pointer into certname => resource map
-    (sql/insert-record :catalog_resources {:catalog catalog-hash :resource resource-hash})))
+        persisted?    (resource-exists? resource-hash)]
+
+    (if persisted?
+      {:hashes [[catalog-hash resource-hash]]
+       :metadata []
+       :parameters []
+       :tags []}
+      {:hashes [[catalog-hash resource-hash]]
+       :metadata [[resource-hash type title exported file line]]
+       :parameters (for [[name value] parameters] [resource-hash name (db-serialize value)])
+       :tags (for [tag tags] [resource-hash tag])})))
+
+(defn add-resources!
+  "Persist the given resource and associate it with the given catalog."
+  [catalog-hash resources]
+  (let [resource-values   (map #(resource->values catalog-hash %) resources)
+        lookup-table      [[:metadata "INSERT INTO resources (hash,type,title,exported,sourcefile,sourceline) VALUES (?,?,?,?,?,?)"]
+                           [:parameters "INSERT INTO resource_params (resource,name,value) VALUES (?,?,?)"]
+                           [:tags "INSERT INTO resource_tags (resource,name) VALUES (?,?)"]
+                           [:hashes "INSERT INTO catalog_resources (catalog,resource) VALUES (?,?)"]]]
+    (sql/transaction
+     (doseq [[lookup the-sql] lookup-table
+             :let [param-sets (remove empty? (mapcat lookup resource-values))]
+             :when (not (empty? param-sets))]
+       (apply sql/do-prepared the-sql param-sets)))
+))

 (defn edge-identity-string
   "Compute a stably-sorted string for the given edge that will
@@ -342,8 +361,7 @@
           (time! (:add-tags *metrics*)
            (add-tags! hash tags))
           (time! (:add-resources *metrics*)
-           (doseq [resource (vals resources)]
-             (add-resource! hash resource)))
+           (add-resources! hash (vals resources)))
           (time! (:add-edges *metrics*)
            (add-edges! hash edges resources)))))


Use bulk query to determine resource existence

Previously, we used a SELECT for each resource we wanted to store to determine
if it already exists in the database. If a catalog has 1000 resources, this
results in 1000 queries. It's much more efficient to use a single query to
determine the existence of a set of resources in one shot.

Signed-off-by: Deepak Giridharagopal <d11186354d1ef01ca06ae37d7e23e827da13e85f@puppetlabs.com>

--- src/com/puppetlabs/cmdb/scf/storage.clj
+++ src/com/puppetlabs/cmdb/scf/storage.clj
@@ -288,13 +288,18 @@
         tags        (map #(assoc default-row :name %) tags)]
     (apply sql/insert-records :tags tags)))

-(defn resource-exists?
-  "Returns a boolean indicating whether or not the given resource exists in the db"
-  [resource-hash]
-  {:pre [(string? resource-hash)]}
-  (sql/with-query-results result-set
-    ["SELECT 1 FROM resource_params WHERE resource=? LIMIT 1" resource-hash]
-    (pos? (count result-set))))
+(defn resources-exist?
+  "Given a collection of resource-hashes, return the subset that
+  already exist in the database."
+  [resource-hashes]
+  {:pre  [(coll? resource-hashes)]
+   :post [(set? resource-hashes)]}
+  (let [qmarks     (apply str (interpose "," (repeat (count resource-hashes) "?")))
+        query      (format "SELECT DISTINCT resource FROM resource_params WHERE resource IN (%s)" qmarks)
+        sql-params (vec (cons query resource-hashes))]
+    (sql/with-query-results result-set
+      sql-params
+      (into #{} (map :resource result-set)))))

 (defn resource-identity-string
   "Compute a stably-sorted, string representation of the given
@@ -337,8 +342,10 @@
   (pr-str [type title (sort tags) exported file line (sort parameters)]))

 (defn- resource->values
-  "Given a catalog-hash and a resource, return a map representing the
-  set of database rows pending insertion.
+  "Given a catalog-hash, a resource, and a truthy value indicating
+  whether or not the indicated resource already exists somewhere in
+  the database, return a map representing the set of database rows
+  pending insertion.

   The result map has the following format:

@@ -353,12 +360,11 @@
   1. Each key corresponds to a table, and each value is a list of rows
   2. The mapping of keys and values to table names and columns is done
      by `add-resources!`"
-  [catalog-hash {:keys [type title exported parameters tags file line] :as resource} resource-hash]
+  [catalog-hash {:keys [type title exported parameters tags file line] :as resource} resource-hash persisted?]
   {:pre  [(every? string? #{catalog-hash type title})]
    :post [(= (set (keys %)) #{:resource :parameters})]}
-  (let [persisted?    (resource-exists? resource-hash)
-        values        {:resource [[catalog-hash resource-hash type title (to-jdbc-varchar-array tags) exported file line]]
-                       :parameters []}]
+  (let [values {:resource [[catalog-hash resource-hash type title (to-jdbc-varchar-array tags) exported file line]]
+                :parameters []}]

     (if persisted?
       values
@@ -368,8 +374,12 @@
 (defn add-resources!
   "Persist the given resource and associate it with the given catalog."
   [catalog-hash refs-to-resources refs-to-hashes]
-  (let [resource-values   (for [[ref resource] refs-to-resources]
-                            (resource->values catalog-hash resource (refs-to-hashes ref)))
+  (let [hashes-to-refs    (into {} (for [[ref hash] refs-to-hashes] [hash ref]))
+        resource-hashes   (set (keys hashes-to-refs))
+        persisted?        (resources-exist? resource-hashes)
+        resource-values   (for [[ref resource] refs-to-resources
+                                :let [hash (refs-to-hashes ref)]]
+                            (resource->values catalog-hash resource hash (persisted? hash)))
         lookup-table      [[:resource "INSERT INTO catalog_resources (catalog,resource,type,title,tags,exported,sourcefile,sourceline) VALUES (?,?,?,?,?,?,?,?)"]
                            [:parameters "INSERT INTO resource_params (resource,name,value) VALUES (?,?,?)"]]]
     (sql/transaction


render an image when people don't have access

--- src/pc/http/routes.clj
+++ src/pc/http/routes.clj
@@ -131,6 +131,8 @@
                                                                         (urls/from-doc doc)]])
                  "Document not found")}))))

+(def private-layers [{:layer/opacity 1.0, :layer/stroke-width 1.0, :layer/end-x 389.5996, :entity/type :layer, :layer/start-y 120.0, :layer/text "Please log in or request access to view it.", :layer/stroke-color "black", :layer/start-x 100.0, :layer/fill "none", :layer/type :layer.type/text, :layer/end-y 100.0} {:layer/opacity 1.0, :layer/stroke-width 1.0, :layer/end-x 373.5547, :entity/type :layer, :layer/start-y 90.0, :layer/text "Sorry, this document is private.", :layer/stroke-color "black", :layer/start-x 100.0, :layer/fill "none", :layer/type :layer.type/text, :layer/end-y 70.0}])
+
 (defn image-cache-headers [db doc]
   (let [last-modified-instant (or (doc-http/last-modified-instant db doc)
                                   (java.util.Date.))]
@@ -173,13 +175,15 @@

           (auth/logged-in? req)
           {:status 403
-           ;; TODO: use an image here
-           :body "Please request permission to access this document"}
+           :headers {"Content-Type" "image/svg+xml"
+                     "Cache-Control" "no-cache; private"}
+           :body (render/render-layers private-layers :invert-colors? (-> req :params :printer-friendly (= "false")))}

           :else
           {:status 401
-           ;; TODO: use an image here
-           :body "Please log in so that we can check if you have permission to access this document"})))
+           :headers {"Content-Type" "image/svg+xml"
+                     "Cache-Control" "no-cache; private"}
+           :body (render/render-layers private-layers :invert-colors? (-> req :params :printer-friendly (= "false")))})))

 (defpage doc-png "/document/:document-id.png" [req]
   (let [document-id (-> req :params :document-id)
@@ -216,13 +220,19 @@

           (auth/logged-in? req)
           {:status 403
-           ;; TODO: use an image here
-           :body "Please request permission to access this document"}
+           :headers {"Content-Type" "image/png"
+                     "Cache-Control" "no-cache; private"}
+           :body (convert/svg->png (render/render-layers private-layers
+                                                         :invert-colors? (-> req :params :printer-friendly (= "false"))
+                                                         :size-limit 800))}

           :else
           {:status 401
-           ;; TODO: use an image here
-           :body "Please log in so that we can check if you have permission to access this document"})))
+           :headers {"Content-Type" "image/png"
+                     "Cache-Control" "no-cache; private"}
+           :body (convert/svg->png (render/render-layers private-layers
+                                                         :invert-colors? (-> req :params :printer-friendly (= "false"))
+                                                         :size-limit 800))})))

 (defpage doc-pdf "/document/:document-id.pdf" [req]
   (let [document-id (-> req :params :document-id)
@@ -253,13 +263,17 @@

           (auth/logged-in? req)
           {:status 403
-           ;; TODO: use an image here
-           :body "Please request permission to access this document"}
+           :headers {"Content-Type" "application/pdf"
+                     "Cache-Control" "no-cache; private"}
+           :body (convert/svg->pdf (render/render-layers private-layers :invert-colors? (-> req :params :printer-friendly (= "false")))
+                                   (render/svg-props private-layers))}

           :else
           {:status 401
-           ;; TODO: use an image here
-           :body "Please log in so that we can check if you have permission to access this document"})))
+           :headers {"Content-Type" "application/pdf"
+                     "Cache-Control" "no-cache; private"}
+           :body (convert/svg->pdf (render/render-layers private-layers :invert-colors? (-> req :params :printer-friendly (= "false")))
+                                   (render/svg-props private-layers))})))

 (defn frontend-response
   "Response to send for requests that the frontend will route"


Use print-cause-trace instead of print-stack-trace.

--- src/incise/watcher.clj
+++ src/incise/watcher.clj
@@ -1,6 +1,6 @@
 (ns incise.watcher
   (:require [taoensso.timbre :refer [error]]
-            [clojure.stacktrace :refer [print-stack-trace]]
+            [clojure.stacktrace :refer [print-cause-trace]]
             [watchtower.core :refer [watcher rate file-filter extensions
                                      on-change]]))

@@ -14,7 +14,7 @@
         (try
           (apply func args)
           (catch Exception e
-            (error (with-out-str (print-stack-trace e)))))))))
+            (error (with-out-str (print-cause-trace e)))))))))

 (defn per-change [change-fn]
   (fn [files]


fix version number

fix version number

--- ingestion-api/src/ingestion_api/main.clj
+++ ingestion-api/src/ingestion_api/main.clj
@@ -47,12 +47,10 @@
   which is typically boundled with jar file"
   []
   (try
-    (->> "project.clj"
-         ((fn [f] (if (.exists (io/file f)) (io/file f) (io/resource f))))
+    (->> (if (.exists (io/file "../samsara.version"))
+           (io/file "../samsara.version")
+           (io/resource "samsara.version"))
          slurp
-         read-string
-         nnext
-         first
          (str "v"))
     (catch Exception x "")))

@@ -70,7 +68,7 @@
 /____/\\__,_/_/ /_/ /_/____/\\__,_/_/   \\__,_/

   Samsara Ingestion API
------------------------------| %7.7s |-------
+--------------------------| %10.10s |-------

 " (version)))


Wub function - complete!

Wub function - complete!

--- src/leap_step/example/popular.clj
+++ src/leap_step/example/popular.clj
@@ -1,62 +1,29 @@
 (ns leap-step.example.popular
   (:use [overtone.core]))

+
 (defsynth dubstep [rootNote 34 bpm 120 wobble 8 note 34 snare-vol 1 kick-vol 1 hihat-vol 1 v 1 chord-vol 0 wob-vol 0 wob4-vol 0 out-bus 0]
- (let [trig (impulse:kr (/ bpm 120))
-       freq (midicps note)

-       cf1 (midicps (- note 5))
-       cf2 (midicps (+ note 2))
-       cf3 (midicps (- note 24))
-
-       freq4 (midicps (+ note 19))
-       freq5 (midicps (+ note 12))
-       freq6 (midicps (+ note 7))
-
-       swr (demand trig 0 (dseq [wobble] INF))
-       sweep (lin-exp (lf-tri swr) -1 1 40 3000)
-       wob (apply + (saw (* freq [0.99 1.01])))
-       wob (lpf wob sweep)
-       wob (* (+ (* wobble 0.02) 0.4) (normalizer wob))
-       wob (+ wob (bpf wob 9000 2))
-       wob (+ wob (* 0.3 (g-verb wob 8 0.7 0.7)))
+  (defn wub [offset b-freq roomsize]
+    (let [trig-i (impulse:kr (/ bpm 120))
+          freq (midicps (+ note offset))
+          swr (demand trig-i 0 (dseq [wobble] INF))
+          sweep (lin-exp (lf-tri swr) -1 1 40 3000)
+          wob (apply + (saw (* freq [0.99 1.01])))
+          wob (lpf wob sweep)
+          wob (* (+ (* wobble 0.02) 0.4) (normalizer wob))
+          wob (+ wob (bpf wob b-freq 2))
+          wob (+ wob (* 0.3 (g-verb wob roomsize 0.7 0.7)))]
+      wob))
+
+ (let [wob (wub 0 9000 8)
        ; 2,3,4,6,8,9, (10) 12,14,16
-       crd1 (apply + (saw (* cf1 [0.99 1.01])))
-       crd1 (lpf crd1 sweep)
-       crd1 (* (+ (* wobble 0.02) 0.4) (normalizer crd1))
-       crd1 (+ crd1 (bpf crd1 2000 2))
-       crd1 (+ crd1 (* 0.3 (g-verb crd1 13 0.7 0.7)))
-
-       crd2 (apply + (saw (* cf2 [0.99 1.01])))
-       crd2 (lpf crd2 sweep)
-       crd2 (* (+ (* wobble 0.02) 0.4) (normalizer crd2))
-       crd2 (+ crd2 (bpf crd2 2000 2))
-       crd2 (+ crd2 (* 0.3 (g-verb crd2 13 0.7 0.7)))
-
-       crd3 (apply + (saw (* cf3 [0.99 1.01])))
-       crd3 (lpf crd3 sweep)
-       crd3 (* (+ (* wobble 0.02) 0.4) (normalizer crd3))
-       crd3 (+ crd3 (bpf crd3 2000 2))
-       crd3 (+ crd3 (* 0.3 (g-verb crd3 13 0.7 0.7)))
-
-       wob4 (apply + (saw (* freq4 [0.99 1.01])))
-       wob4 (lpf wob4 sweep)
-       wob4 (* (+ (* wobble 0.02) 0.4) (normalizer wob4))
-       wob4 (+ wob4 (bpf wob4 2000 2))
-       wob4 (+ wob4 (* 0.3 (g-verb wob4 13 0.7 0.7)))
-
-       wob5 (apply + (saw (* freq5 [0.99 1.01])))
-       wob5 (lpf wob5 sweep)
-       wob5 (* (+ (* wobble 0.02) 0.4) (normalizer wob5))
-       wob5 (+ wob5 (bpf wob5 2000 2))
-       wob5 (+ wob5 (* 0.3 (g-verb wob5 13 0.7 0.7)))
-
-       wob6 (apply + (saw (* freq6 [0.99 1.01])))
-       wob6 (lpf wob6 sweep)
-       wob6 (* (+ (* wobble 0.02) 0.4) (normalizer wob6))
-       wob6 (+ wob6 (bpf wob6 2000 2))
-       wob6 (+ wob6 (* 0.3 (g-verb wob6 13 0.7 0.7)))
-
+       crd1 (wub -5 2000 13)
+       crd2 (wub 2 2000 13)
+       crd3 (wub -24 2000 13)
+       wob4 (wub 19 2000 13)
+       wob5 (wub 12 2000 13)
+       wob6 (wub 7 2000 13)
        kickenv (decay (t2a (demand (impulse:kr (/ bpm 30)) 0 (dseq [1 0 0 1 0 0 1 0 1 0 0 1 0 1 0 0] INF))) 0.7)
        kick (* (* kickenv 7) (sin-osc (+ 20 (* kickenv kickenv kickenv 150))))
        kick (clip2 kick 1)


Require formatting and update middleware stack

--- src/leiningen/new/cljskel/web.clj
+++ src/leiningen/new/cljskel/web.clj
@@ -1,13 +1,17 @@
 (ns {{name}}.web
-    (:require [compojure.core :refer [defroutes context GET PUT POST DELETE]]
-              [compojure.route :as route]
-              [metrics.ring.expose :refer [expose-metrics-as-json]]
-              [metrics.ring.instrument :refer [instrument]]
-              [nokia.ring-utils.error :refer [wrap-error-handling error-response]]
-              [nokia.ring-utils.ignore-trailing-slash :refer [wrap-ignore-trailing-slash]]
-              [ring.middleware.format-response :refer [wrap-json-response]]
-              [ring.middleware.keyword-params :refer [wrap-keyword-params]]
-              [ring.middleware.params :refer [wrap-params]]))
+  (:require [compojure
+             [core :refer [defroutes context GET PUT POST DELETE]]
+             [route :as route]]
+            [metrics.ring
+             [expose :refer [expose-metrics-as-json]]
+             [instrument :refer [instrument]]]
+            [nokia.ring-utils
+             [error :refer [wrap-error-handling error-response]]
+             [ignore-trailing-slash :refer [wrap-ignore-trailing-slash]]]
+            [ring.middleware
+             [format-params :refer [wrap-json-kw-params]]
+             [format-response :refer [wrap-json-response]]
+             [params :refer [wrap-params]]]))

 (def ^:dynamic *version* "none")
 (defn set-version! [version]
@@ -38,7 +42,7 @@
       (instrument)
       (wrap-error-handling)
       (wrap-ignore-trailing-slash)
-      (wrap-keyword-params)
+      (wrap-json-response)
+      (wrap-json-kw-params)
       (wrap-params)
-      (wrap-json-response)
       (expose-metrics-as-json)))


Allow task functions to be defined in project.clj.

--- src/leiningen/core.clj
+++ src/leiningen/core.clj
@@ -61,7 +61,8 @@
                     (format "%s is not a task. Use \"help\" to list all tasks."
                              task)))]
     (try
-     (require task-ns)
+     (when-not (find-ns task-ns)
+       (require task-ns))
      (or (ns-resolve task-ns task)
          error-fn)
      (catch java.io.FileNotFoundException e


Add support for meshes

Add support for meshes

--- src/main/cljs/ohpengull/core.cljs
+++ src/main/cljs/ohpengull/core.cljs
@@ -53,6 +53,10 @@
                                      :byteOffset 0
                                      :byteLength 6
                                      :target buffer-object/element-array-buffer}}
+   :meshes {"my-mesh" {:primitives [{:attributes {"vertex_position" "my-position-accessor"}
+                                     :indices "my-index-accessor"
+                                     :material nil
+                                     :primitive draw-mode/triangles}]}}
    :programs {"my-program" {:attributes ["vertex_position"]
                             :fragment-shader "my-fragment-shader"
                             :vertex-shader "my-vertex-shader"}}
@@ -125,12 +129,15 @@
        :buffer-views buffer-views})))

 (defn- make-draw-calls [gl render-state]
-  (let [program (get-in render-state [:programs "my-program"])]
-    [{:shader program
-      :draw-mode draw-mode/triangles
-      :count 3
-      :attributes [(assoc-attribute gl render-state program "vertex_position" "my-position-accessor")]
-      :element-array (assoc-element-array render-state "my-index-accessor")}]))
+  (for [mesh (vals (get-in render-state [:last-input :meshes]))
+        prim (:primitives mesh)
+        :let [program (get-in render-state [:programs "my-program"])]]
+    {:shader program
+     :draw-mode (:primitive prim)
+     :count (get-in render-state [:last-input :accessors (:indices prim) :count])
+     :attributes (for [[attribute-name accessor-name] (:attributes prim)]
+                   (assoc-attribute gl render-state program attribute-name accessor-name))
+     :element-array (assoc-element-array render-state (:indices prim))}))

 (let [gl (context/get-context (sel1 :#glcanvas))]
   (swap! render-state update-render-state! gl input)        ;TODO swap! function must not have side-effects


ensure that a package.json exists in the project

--- src/main/shadow/cljs/npm/cli.cljs
+++ src/main/shadow/cljs/npm/cli.cljs
@@ -369,6 +369,10 @@

                 (println (str "Running: " pkg-cmd " " (str/join " " pkg-args)))

+                ;; npm installs into wrong location if no package.json is present
+                (when-not (fs/existsSync package-json-file)
+                  (fs/writeFileSync package-json-file "{}"))
+
                 (cp/spawnSync pkg-cmd (into-array pkg-args) #js {:cwd project-root
                                                                  :stdio "inherit"})
                 true))))))


Story ID: develop Summary: Fixing crashes related to sorting a diff output and having mismatched types

--- src/untangled_spec/reporters/terminal.clj
+++ src/untangled_spec/reporters/terminal.clj
@@ -69,7 +69,7 @@
             num-diffs (if (number? num-diffs)
                         num-diffs (count diff))]
         (println (color-str :diff "diffs:"))
-        (doseq [d (->> (sort diff) (take num-diffs))]
+        (doseq [d (take num-diffs diff)]
           (let [{:keys [exp got path]} (diff/extract d)]
             (when (seq path)
               (println (str "-  at: " path)))


added docstrings to just, contains, has-prefix, and has-suffix

--- src/midje/checkers/collection.clj
+++ src/midje/checkers/collection.clj
@@ -123,39 +123,103 @@
                                   "A collection with ~R element~:P cannot match a ~A of size ~R."
                                   (count actual) x-name (count expected))))))))]

-  (def ^{:midje/checker true} has-prefix
+  (def ^{:midje/checker true
+         :doc "Checks that the actual result starts with the expected result:
+
+  [1 2 3] => (has-prefix   [1 2]) ; true
+  [1 2 3] => (has-prefix   [2 1]) ; false - order matters
+  [1 2 3] => (has-prefix   [2 1] :in-any-order) ; true
+  [1 2 3] => (has-prefix  #{2 1}) ; true "}
+    has-prefix
     (container-checker-maker 'has-prefix
       (has-xfix "prefix" #(re-pattern (str "^" %)) take)))

-  (def ^{:midje/checker true} has-suffix
+  (def ^{:midje/checker true
+         :doc "Checks that the actual result ends with the expected result:
+
+  [1 2 3] => (has-suffix   [2 3]) ; true
+  [1 2 3] => (has-suffix   [3 2]) ; false - order matters
+  [1 2 3] => (has-suffix   [3 2] :in-any-order) ; true
+  [1 2 3] => (has-suffix  #{3 2}) ; true "}
+    has-suffix
     (container-checker-maker 'has-suffix
       (has-xfix "suffix" #(re-pattern (str % "$")) take-last)))

-  (def ^{:midje/checker true} contains (container-checker-maker 'contains
-                                         (fn [actual expected looseness]
-                                           (let [ [actual expected looseness] (standardized-arguments actual expected looseness)]
-                                             (cond (regex? expected)
-                                               (try-re expected actual re-find)
-
-                                               :else
-                                               (match? actual expected looseness))))))
-
-  (def ^{:midje/checker true} just (container-checker-maker 'just
-                                     (fn [actual expected looseness]
-                                       (let [ [actual expected looseness] (standardized-arguments actual expected looseness)]
-                                         (cond (regex? expected)
-                                           (try-re expected actual re-matches)
-
-                                           (same-lengths? actual expected)
-                                           (match? actual expected looseness)
-
-                                           :else
-                                           (noted-falsehood
-                                             (cl-format nil "Expected ~R element~:P. There ~[were~;was~:;were~]~:* ~R."
-                                               (count expected)
-                                               (count actual)))))))))
-
+  (def ^{:midje/checker true
+         :doc "Checks that the expected result is a subsequence of the actual result:
+
+To succeed, f's result must be (1) contiguous and (2) in the
+same order as in the contains clause. Here are examples:
+
+   [3 4 5 700]   => (contains [4 5 700]) ; true
+   [4 700 5]     => (contains [4 5 700]) ; false
+   [4 5 'hi 700] => (contains [4 5 700]) ; false
+
+The :in-any-order modifier loosens the second requirement:
+
+   ['hi 700 5 4] => (contains [4 5 700] :in-any-order) ; true
+   [4 5 'hi 700] => (contains [4 5 700] :in-any-order) ; false b/c 'hi is in middle
+
+The :gaps-ok modifier loosens the first:
+
+   [4 5 'hi 700]  => (contains [4 5 700] :gaps-ok) ; true
+   [4 700 'hi' 5] => (contains [4 5 700] :gaps-ok) ; false b/c of bad order
+
+The two modifiers can be used at the same time:
+
+   [4 700 5]         => (contains [4 5 700] :gaps-ok :in-any-order) ; true
+   [4 5 'hi 700]     => (contains [4 5 700] :in-any-order :gaps-ok) ; true
+   [700 'hi 4 5 'hi] => (contains [4 5 700] :in-any-order :gaps-ok) ; true
+
+Another way to indicate :in-any-order is to describe
+what's contained by a set. The following two are equivalent:
+
+   [700 4 5] => (contains [4 5 700] :in-any-order)
+   [700 4 5] => (contains #{4 5 700})
+
+:gaps-ok can be used with a set. (So can :in-any-order, but it has no effect.)"}
+    contains (container-checker-maker 'contains
+               (fn [actual expected looseness]
+                 (let [[actual expected looseness] (standardized-arguments actual expected looseness)]
+                   (cond (regex? expected)
+                     (try-re expected actual re-find)
+
+                     :else (match? actual expected looseness))))))
+
+  (def ^{:midje/checker true
+         :doc "A variant of contains, just, will fail if the
+left-hand-side contains any extra values:
+   [1 2 3] => (just [1 2 3])  ; true
+   [1 2 3] => (just [1 2 3 4]) ; false
+
+The first of those seems senseless, since you could just use this:
+
+   [1 2 3] => [1 2 3]
+
+However, it's required if you want to use checkers in the expected result:
+
+   [1 2 3] => [odd? even? odd?]  ; false b/c 2nd-level fns aren't normally treated as checkers.
+   [1 2 3] => (just [odd? even? odd?]) ; true
+
+just is also useful if you don't care about order:
+
+  [1 3 2] => (just   [1 2 3] :in-any-order)
+  [1 3 2] => (just  #{1 2 3})"}
+    just (container-checker-maker 'just
+           (fn [actual expected looseness]
+             (let [[actual expected looseness] (standardized-arguments actual expected looseness)]
+               (cond (regex? expected)
+                 (try-re expected actual re-matches)
+
+                 (same-lengths? actual expected)
+                 (match? actual expected looseness)
+
+                 :else (noted-falsehood
+                         (cl-format nil "Expected ~R element~:P. There ~[were~;was~:;were~]~:* ~R."
+                           (count expected)
+                           (count actual)))))))))
+
 (defchecker has
   "You can apply Clojure's quantification functions (every?, some, and so on)
    to all the values of sequence.


Some utilities used in midje tests

Some utilities used in midje tests

--- src/midje/clojure_test_facade.clj
+++ src/midje/clojure_test_facade.clj
@@ -15,11 +15,25 @@
 ;; Midje is really useful any more. The only reason for it that I can
 ;; think of is so that `lein test` works with Midje.

+(defn set-counters [map]
+  (alter-var-root #'ct/*report-counters*
+                  (constantly (ref map))))
+
 (defn zero-counters []
-  (alter-var-root (var ct/*report-counters*)
-                  (fn [_#] (ref ct/*initial-report-counters*))))
+  (set-counters ct/*initial-report-counters*))

 (defn counters []  @ct/*report-counters*)
+
+(defmacro ignoring-counter-changes [& forms]
+  `(let [stashed-counters# (counters)]
+    (try
+      ~@forms
+    (finally
+       (set-counters stashed-counters#)))))
+
+(defn reset-counters [counters]
+  (alter-var-root (var ct/*report-counters*)
+                  (constantly counters)))

 (defmacro with-isolated-counters [& body]
   `(let [original-value# ct/*report-counters*]


definitions for London

definitions for London

--- src/lights/my_show.clj
+++ src/lights/my_show.clj
@@ -92,18 +92,11 @@
 (defn use-my-show
   "Set up the show on the OLA universes it actually needs."
   []
-
-  ;; Create, or re-create the show. Make it the default show so we don't
-  ;; need to wrap everything below in a (with-show sample-show ...) binding.
   (set-default-show!
     (swap! my-show (fn [s]
       (when s
         (show/unregister-show s)
         (with-show s (show/stop!)))
-      ;; TODO: Edit this to list the actual OLA universe(s) that
-      ;;       your show needs to use if they are different than
-      ;;       just universe 1, as below, and change the description
-      ;;       to something descriptive and in your own style:
       (show/show :universes [1] :description "Accuraten"))))

   (show/patch-fixture! :back-1 (simple-rgbd) 1 1 :x 1)
@@ -123,10 +116,7 @@
       (when s
         (show/unregister-show s)
         (with-show s (show/stop!)))
-      ;; TODO: Edit this to list the actual OLA universe(s) that
-      ;;       your show needs to use if they are different than
-      ;;       just universe 1, as below, and change the description
-      ;;       to something descriptive and in your own style:
+
       (show/show :universes [1] :description "London"))))

   (show/patch-fixture! :front-1 (rgbd-simple) 1 1   :x 1.6  :y 3.5 :z 2.6)
@@ -134,14 +124,10 @@

   (show/patch-fixture! :scene-side-1 (rgbw-simple) 1 33  :x 0 :y 1.7 :z 1.5)

-  (show/patch-fixture! :head-1 (jb-systems-sirius-8ch) 1 49 :x 3.5  :y 7  :z 2.8
-     :x-rotation (tf/degrees -135))
-  (show/patch-fixture! :head-2 (jb-systems-sirius-8ch) 1 65 :x 3.5  :y 7  :z 2.8
-     :x-rotation (tf/degrees -135))
-  (show/patch-fixture! :head-3 (jb-systems-sirius-8ch) 1 81 :x 3.5  :y 7  :z 2.8
-     :x-rotation (tf/degrees -135))
-  (show/patch-fixture! :head-4 (jb-systems-sirius-8ch) 1 97 :x 3.5  :y 7  :z 2.8
-     :x-rotation (tf/degrees -135))
+  (show/patch-fixture! :head-1 (jb-systems-sirius-8ch) 1 49 :x 3.5  :y 7  :z 2.8)
+  (show/patch-fixture! :head-2 (jb-systems-sirius-8ch) 1 65 :x 3.5  :y 7  :z 2.8)
+  (show/patch-fixture! :head-3 (jb-systems-sirius-8ch) 1 81 :x 3.5  :y 7  :z 2.8)
+  (show/patch-fixture! :head-4 (jb-systems-sirius-8ch) 1 97 :x 3.5  :y 7  :z 2.8)

   (show/patch-fixture! :back-1 (simple-rgbd) 1 113 :x -1.757 :y 0.325 :z 0.3)
   (show/patch-fixture! :back-2 (simple-rgbd) 1 117 :x -1.057 :y 0.325 :z 0.3)
@@ -154,7 +140,7 @@
   ;; all the expanded, patched fixtures in it.
   '*show*)

-(use-my-show)  ; Set up my show as the default show, using the function above.
+(use-my-show)

 ;(use-london-show)


Relaxing the test constraint a small bit.

--- suite/test/cortex/suite/logistic_test.clj
+++ suite/test/cortex/suite/logistic_test.clj
@@ -43,5 +43,5 @@
         trained-network (train/load-network "trained-network.nippy" description)
         [[should-def] [shouldnt-def]] (inference/infer-n-observations trained-network [[5000.0 10.0] [5.0 100000.0]]
                                                                       2 :batch-size 2)]
-    (is (> should-def 0.99))
-    (is (< shouldnt-def 0.01))))
+    (is (> should-def 0.98))
+    (is (< shouldnt-def 0.02))))


s/map/pmap/

s/map/pmap/

--- src/babel/parse.cljc
+++ src/babel/parse.cljc
@@ -17,8 +17,8 @@
         tokens2 (toks2 tokens (count tokens))]
     (log/debug (str "tokens: " tokens))
     (log/debug (str "tokens2 size: " (count tokens2)))
-    (map (fn [token-vector]
-           (map lookup token-vector))
+    (pmap (fn [token-vector]
+            (pmap lookup token-vector))
          tokens2)))

 (defn toks2 [tokens n]
@@ -34,13 +34,13 @@

     (> (count tokens) n) ;; ([a b c]; n = 2) => [["a b" "c"] ["a" "b c"]]
     (concat (let [first-token (string/join " " (subvec tokens 0 n))]
-              (map #(vec (cons first-token %))
-                   (toks2 (subvec tokens n (count tokens))
-                          n)))
+              (pmap #(vec (cons first-token %))
+                    (toks2 (subvec tokens n (count tokens))
+                           n)))
             (let [last-token (string/join " " (subvec tokens (- (count tokens) n) (count tokens)))]
-              (map #(vec (concat % (list last-token)))
-                   (toks2 (subvec tokens 0 (- (count tokens) n))
-                          n)))
+              (pmap #(vec (concat % (list last-token)))
+                    (toks2 (subvec tokens 0 (- (count tokens) n))
+                           n)))
             (toks2 tokens (- n 1)))
     true
     tokens))


+TODO

+TODO

--- src/babel/parse.cljc
+++ src/babel/parse.cljc
@@ -26,6 +26,7 @@
                           y)))
           x))

+;; TODO: make a static lookup table, at least for n < (e.g.) 5.
 (defn spanpairs [n]
   (mapcat (fn [x]
             (pmap (fn [y]


is-workday cljs tests

is-workday cljs tests

--- test-cljs/cljs_workcalendar/api_test.cljs
+++ test-cljs/cljs_workcalendar/api_test.cljs
@@ -1,7 +1,20 @@
 (ns cljs-workcalendar.api-test
-  (:require [cljs.test :refer-macros [deftest testing is]]
+  (:require [cljs.test :refer-macros [deftest testing is are]]
             [cljs-workcalendar.api :as cs]))

-(deftest simple
+(defn- is-workday? [service year month day]
+  (.is-workday service (js/Date. year (dec month) day)))
+
+(deftest is-workday-test
   (let [service (cs/createWorkCalendarService)]
-    (is (not (.is-workday service (js/Date 2012 (dec 1) 2))))))
+
+    (are [year month day workday?]
+      (= workday? (.is-workday service (js/Date. year (dec month) day)))
+      2012 1 1 false
+      2012 1 2 false
+      2012 1 3 false
+      2012 1 10 true
+      2012 1 13 true
+      2012 2 23 false
+      2013 3 11 true
+      2012 6 9 true)))


Fix Issue

Fix Issue

Fixing issues stated by @l5t in the pull-request #189.

--- resources/languages/tr/rules/numbers.clj
+++ resources/languages/tr/rules/numbers.clj
@@ -20,10 +20,6 @@
   "ten"
   #"(?i)on"
   {:dim :number :integer true :value 10 :grain 1}
-
-  "single"
-  #"(?i)single"
-  {:dim :number :integer true :value 1 :grain 1}

   "a couple (of)"
   #"(?i)(bir )?çift"
@@ -156,7 +152,7 @@
    :grain (:grain %2)}

   "number millions"
-  [(integer 1 999) (integer 1000000 1000000)]
+  [(integer 2 999) (integer 1000000 1000000)]
   {:dim :number
    :integer true
    :value (* (:value %1) (:value %2))
@@ -272,7 +268,7 @@

   "decimal thousand | million"
-  [(dim :number #(< (:value %) 999.9)) (integer 1000 1000000 #(#{1000 1000000} (:value %)))]
+  [(dim :number #(< (:value %) 999.9) #(not (:integer %))) (integer 1000 1000000 #(#{1000 1000000} (:value %)))]
   (let [value (* (:value %1) (long (:value %2)))
   	    int?  (zero? (mod value 1))
 		value (if int? (long value) value)]


Add docstring

Add docstring

--- scheduler/src/cook/mesos/constraints.clj
+++ scheduler/src/cook/mesos/constraints.clj
@@ -187,6 +187,8 @@
 ;; Group host placement constraints

 (defn- get-running-cotasks-from-cache
+  "Looks up the currently running tasks in group from group-uuid->running-cotask-cache
+   and loads them from db if missing."
   [db group-uuid->running-cotask-cache group]
   (let [group-uuid (:group/uuid group)]
     (cache/lookup (swap! group-uuid->running-cotask-cache


Better output for one-click-deploy.

Better output for one-click-deploy.

--- src/circle/tasks.clj
+++ src/circle/tasks.clj
@@ -2,6 +2,7 @@
   "Like rake tasks, for the repl"
   (:require [circle.backend.build.run :as run])
   (:require [circle.util.mongo :as mongo])
+  (:require [clojure.pprint :as pprint])
   (:require [circle.backend.build.config :as config]))

 (defn one-click-deploy [& args]
@@ -11,4 +12,9 @@
                :job-name
                :deploy)]
     (mongo/ensure-object-id-ref :builds build)
-    (apply run/run-build build args)))+    (let [result (apply run/run-build build args)]
+      (pprint/pprint result)
+      (println
+       (if (-> @result :failed)
+         "Failed"
+         "Success")))))


missing lib

missing lib

--- src/clj/hsm/ring.clj
+++ src/clj/hsm/ring.clj
@@ -1,5 +1,6 @@
 (ns hsm.ring
 	(:require
+		[clojure.tools.logging :as log]
 		[ring.util.response :as resp]
 		[cheshire.core :refer :all]))


(dom/text $el) should return text value, not element.

--- src/cljs/c2/dom.cljs
+++ src/cljs/c2/dom.cljs
@@ -148,8 +148,7 @@
   "Get or set element text, returning element"
   ([el]
      (let [el (->dom el)]
-       (gdom/getTextContent el)
-       el))
+       (gdom/getTextContent el)))
   ([el v]
      (let [el (->dom el)]
        (gdom/setTextContent el v)


needs more guitar

needs more guitar


(PDB-1254) Fix naming conventions for indexes for latest migration

Fix the index naming conventions for the latest migration to be
<table>_<column>_idx.

Signed-off-by: Ken Barber <470bc578162732ac7f9d387d34c4af4ca6e1b6f7@bob.sh>

--- src/puppetlabs/puppetdb/scf/migrate.clj
+++ src/puppetlabs/puppetdb/scf/migrate.clj
@@ -982,28 +982,28 @@

     (sql/do-commands
      "ALTER TABLE reports ADD CONSTRAINT reports_pkey PRIMARY KEY (id)"
-     "CREATE INDEX idx_reports_certname ON reports(certname)"
-     "CREATE INDEX idx_reports_end_time ON reports(end_time)"
-     "CREATE INDEX idx_reports_environment_id ON reports(environment_id)"
-     "CREATE INDEX idx_reports_status_id ON reports(status_id)"
-     "CREATE INDEX idx_reports_transaction_uuid ON reports(transaction_uuid)"
+     "CREATE INDEX reports_certname_idx ON reports(certname)"
+     "CREATE INDEX reports_end_time_idx ON reports(end_time)"
+     "CREATE INDEX reports_environment_id_idx ON reports(environment_id)"
+     "CREATE INDEX reports_status_id_idx ON reports(status_id)"
+     "CREATE INDEX reports_transaction_uuid_idx ON reports(transaction_uuid)"
      "ALTER TABLE reports ADD CONSTRAINT reports_env_fkey FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE"
      "ALTER TABLE reports ADD CONSTRAINT reports_status_fkey FOREIGN KEY (status_id) REFERENCES report_statuses(id) ON DELETE CASCADE")

     (sql/do-commands
      "ALTER TABLE resource_events ADD CONSTRAINT resource_events_unique UNIQUE (report_id, resource_type, resource_title, property)"
-     "CREATE INDEX idx_resource_events_containing_class ON resource_events(containing_class)"
-     "CREATE INDEX idx_resource_events_property ON resource_events(property)"
-     "CREATE INDEX idx_resource_events_reports_id ON resource_events(report_id)"
-     "CREATE INDEX idx_resource_events_resource_type ON resource_events(resource_type)"
-     "CREATE INDEX idx_resource_events_resource_title ON resource_events(resource_title)"
-     "CREATE INDEX idx_resource_events_status ON resource_events(status)"
-     "CREATE INDEX idx_resource_events_timestamp ON resource_events(timestamp)"
+     "CREATE INDEX resource_events_containing_class_idx ON resource_events(containing_class)"
+     "CREATE INDEX resource_events_property_idx ON resource_events(property)"
+     "CREATE INDEX resource_events_reports_id_idx ON resource_events(report_id)"
+     "CREATE INDEX resource_events_resource_type_idx ON resource_events(resource_type)"
+     "CREATE INDEX resource_events_resource_title_idx ON resource_events(resource_title)"
+     "CREATE INDEX resource_events_status_idx ON resource_events(status)"
+     "CREATE INDEX resource_events_timestamp_idx ON resource_events(timestamp)"
      "ALTER TABLE resource_events ADD CONSTRAINT resource_events_report_id_fkey FOREIGN KEY (report_id) REFERENCES reports(id) ON DELETE CASCADE")

     (sql/do-commands
       "ALTER TABLE certnames ADD CONSTRAINT certnames_pkey PRIMARY KEY (name)"
-      "CREATE INDEX idx_certnames_latest_report_id ON certnames(latest_report_id)"
+      "CREATE INDEX certnames_latest_report_id_idx ON certnames(latest_report_id)"
       "ALTER TABLE edges ADD CONSTRAINT edges_certname_fkey FOREIGN KEY (certname) REFERENCES certnames(name) ON UPDATE NO ACTION ON DELETE CASCADE"
       "ALTER TABLE catalogs ADD CONSTRAINT catalogs_certname_fkey FOREIGN KEY (certname) REFERENCES certnames(name) ON UPDATE NO ACTION ON DELETE CASCADE"
       "ALTER TABLE factsets ADD CONSTRAINT factsets_certname_fk FOREIGN KEY (certname) REFERENCES certnames(name) ON UPDATE CASCADE ON DELETE CASCADE"


small improvements to the early-access stuff

--- src/pc/views/admin.clj
+++ src/pc/views/admin.clj
@@ -39,28 +39,31 @@
         requested (d/q '{:find [[?t ...]]
                          :where [[?t :flags :flags/requested-early-access]]}
                        db)
-        granted (d/q '{:find [[?t ...]]
-                       :where [[?t :flags :flags/private-docs]]}
-                     db)
-        not-granted (remove #(contains? (set granted) %) requested)]
+        granted (set (d/q '{:find [[?t ...]]
+                            :where [[?t :flags :flags/private-docs]]}
+                          db))
+        not-granted (remove #(contains? granted %) requested)]
     (list
      [:style "td, th { padding: 5px; text-align: left }"]
      (if-not (seq not-granted)
        [:h4 "No users that requested early access, but don't have it."]
        (list
-        [:p "Pending:"
+        [:p (str (count not-granted) " pending:")
          [:table {:border 1}
           [:tr
-           [:th "User"]
+           [:th "Email"]
+           [:th "Name"]
            [:th "Company"]
            [:th "Employee Count"]
            [:th "Use Case"]
            [:th "Grant Access (can't be undone without a repl!)"]]
-          (for [cust-id not-granted
+          (for [cust-id (sort not-granted)
                 :let [cust (cust-model/find-by-id db cust-id)
                       req (first (pc.early-access/find-by-cust db cust))]]
             [:tr
              [:td (:cust/email cust)]
+             [:td (or (:cust/name cust)
+                      (:cust/first-name cust))]
              [:td (:early-access-request/company-name req)]
              [:td (:early-access-request/employee-count req)]
              [:td (:early-access-request/use-case req)]
@@ -68,18 +71,21 @@
                    (anti-forgery/anti-forgery-field)
                    [:input {:type "hidden" :name "cust-uuid" :value (str (:cust/uuid cust))}]
                    [:input {:type "submit" :value "Grant early access"}]]]])]]))
-     [:p "Granted:"
+     [:p (str (count granted) " granted:")
       [:table {:border 1}
        [:tr
-        [:th "User"]
+        [:th "Email"]
+        [:th "Name"]
         [:th "Company"]
         [:th "Employee Count"]
         [:th "Use Case"]]
-       (for [cust-id granted
+       (for [cust-id (sort granted)
              :let [cust (cust-model/find-by-id db cust-id)
                    req (first (pc.early-access/find-by-cust db cust))]]
          [:tr
           [:td (:cust/email cust)]
+          [:td (or (:cust/name cust)
+                   (:cust/first-name cust))]
           [:td (:early-access-request/company-name req)]
           [:td (:early-access-request/employee-count req)]
           [:td (:early-access-request/use-case req)]])]])))


Adds a new global option :user

Adds a new global option :user

--- src/control/core.clj
+++ src/control/core.clj
@@ -1,6 +1,6 @@
 (ns control.core
   #^{ :doc "Clojure control core"
-         :author " Dennis Zhuang <killme2008@gmail.com>"}
+     :author " Dennis Zhuang <killme2008@gmail.com>"}
   (:use [clojure.java.io :only [reader]]
         [clojure.java.shell :only [sh]]
         [clojure.string :only [join blank?]]
@@ -55,7 +55,10 @@
     execp))

 (defn ssh-client [host user]
-  (str user "@" host))
+  (let [user (or user (:user *global-options*))]
+    (if (not user)
+      (throw (IllegalArgumentException. "user is nil")))
+    (str user "@" host)) )

 (defn-  user-at-host? [host user]
   (fn [m]
@@ -80,6 +83,7 @@
   :ssh-options        a ssh options string,for example \"-o ConnectTimeout=3000\"
   :scp-options       a scp options string
   :rsync-options    a rsync options string.
+  :user                    global user for cluster,if cluster do not have :user ,it will use this by default.

   Example:
         (set-options! :ssh-options \"-o ConnectTimeout=3000\")
@@ -233,11 +237,11 @@
 (defn- unquote-cluster [args]
   (walk (fn [item]
           (cond (and (seq? item) (= `unquote (first item)))
-                ,(second item)
+                (second item)
                 (or (seq? item) (symbol? item))
-                ,(list 'quote item)
+                (list 'quote item)
                 :else
-                ,(unquote-cluster item)))
+                (unquote-cluster item)))
         identity
         args))


Don't log request body.

Don't log request body.

--- src/rsvp_backend/middleware/logging.clj
+++ src/rsvp_backend/middleware/logging.clj
@@ -6,7 +6,7 @@

 (def standard-ring-request-keys
   [:server-port :server-name :remote-addr :uri :query-string :scheme
-   :headers :request-method :body :params :form-params :query-params])
+   :headers :request-method :params :form-params :query-params])

 (defn wrap-log-request-response
  "Logs requests to the server and responses with INFO level."


Fix refactor error

Fix refactor error

--- src/braid/server/routes/bots.clj
+++ src/braid/server/routes/bots.clj
@@ -75,7 +75,7 @@
         (if (bot-can-message? bot-id msg)
           (do
             (timbre/debugf "Creating message from bot: %s %s" bot-id msg)
-            (db/run-txns! (message/create-message! msg))
+            (message/create-message! msg)
             (sync/broadcast-thread (msg :thread-id) [])
             {:status 201
              :headers {"Content-Type" "text/plain"}
@@ -115,7 +115,7 @@
                            (catch IllegalArgumentException _ nil))]
         (if (= (bot :group-id) (thread/thread-group-id thread-id))
           (do
-            (db/run-txns! (bot/bot-watch-thread! bot-id thread-id))
+            (db/run-txns! (bot/bot-watch-thread-txn bot-id thread-id))
             {:status 201
              :headers {"Content-Type" "text/plain"}
              :body "ok"})


sampling and response handling code removed since it needs an overhaul

--- src/crawler/core.clj
+++ src/crawler/core.clj
@@ -18,57 +18,6 @@
 (def lemurproject-header
   {"User-Agent" lemurproject-ua-string})

-(defn handle-response
-  "Response is a value returned by our wrapper around
-clj-http's get call. We have a couple of statuses that we use"
-  [response doc-writer]
-  (when (not (= :download-failed (:status response)))
-    (do
-      (->> (:body response)
-         (.write doc-writer))
-      (page-utils/get-links-out (:body response)))))
-
-(defn write-response
-  [response doc-writer link]
-  (binding [*out* doc-writer]
-    (pprint {:link link
-             :body (-> response :body)})
-    (flush)))
-
-(defn random-sample
-  "Randomly sample a website. This is done by
-dequeuing from the front or the end (picked at random)
-of the to-visit queue.
-Args:
- site       : the seed in question
- to-visit   : queue of unvisited URLs
- num-docs   : number of documents to obtain
- doc-writer : a file-descriptor of your choice"
-  [to-visit num-docs visited doc-writer]
-  (let [[next-link remaining] (utils/random-dequeue to-visit)
-
-        next-link-response    (utils/download-page
-                               next-link
-                               {"User-Agent"
-                                lemurproject-ua-string})
-
-        out-links             (filter
-                               #(not (some #{%} visited))
-                               (map
-                                #(if (utils/relative? %)
-                                   (uri/resolve-uri next-link %)
-                                   %)
-                                (filter
-                                 #(utils/in-domain? next-link %)
-                                 (page-utils/get-links-out
-                                  (:body next-link-response)))))]
-    (do
-      (write-response next-link-response doc-writer next-link)
-      (when (not (= 1 num-docs))
-        (recur
-         (concat remaining out-links)
-         (dec num-docs)
-         (cons next-link visited)
-         doc-writer)))))

+


abortive attempt to add email out

abortive attempt to add email out

--- src/prais2/logger.cljs
+++ src/prais2/logger.cljs
@@ -1,6 +1,7 @@
 (ns ^:figwheel-always prais2.logger
     (:require [rum.core :as rum]
               [prais2.core :as core]
+
               ))

 (rum/defc icon-control [icon event-key tooltip]
@@ -29,6 +30,20 @@
 (rum/defc load-control []
   (icon-control "sign-in fa-rotate-90" :load-session "read in session"))

+#_(rum/defcc my-component [comp arg1 arg2]
+  (let [node (.findDOMNode comp)]
+    [:div "fails with: Uncaught TypeError: comp.findDOMNode is not a function"]))
+
+(rum/defcc my-component [comp arg1 arg2]
+  (let [node (.findDOMNode js/React comp)]
+    [:div "fails with: Invariant Violation: findComponentRoot(...): Unable to find element.  This probably means the DOM was unexpectedly mutated ..."]))
+
+#_(rum/defcc div [comp to-address session-log]
+  (let [element (.findDOMNode js/React comp)]
+
+    (.log js/console element)
+    [:div#lookatme "Hi there"]
+))

 (rum/defc playback-controls []
   [:div
@@ -42,4 +57,18 @@
     (share-control)
     (load-control)]

+   (my-component 1 2)
+
+   #_(email-form "gmp26@cam.ac.uk" "hello there")
    ])
+
+
+(comment
+  #_[:form {:action (str "mailto:" to-address
+                         "?subject=" "prais2-session-start " (new js/Date.))
+            :method "post"
+            :enctype "text/plain"}
+     [:input {:type "text"
+              :name "session log"
+              :value session-log
+              }]])


add description param to form

add description param to form

--- src/push_ups/forms.clj
+++ src/push_ups/forms.clj
@@ -1,5 +1,6 @@
 (ns push-ups.forms
-  (:use hiccup.form))
+  (:use hiccup.form
+        hiccup.element))

 (defn- start-week
   "dropdown for selecting start date"
@@ -57,18 +58,26 @@

 (defn exercise-time-choice-set
   ([legend]
-   (exercise-time-choice-set legend "next-week" "1-3-5" 20))
-  ([legend week-choice day-choice time-choice]
+   (exercise-time-choice-set legend nil))
+  ([legend description]
+   (exercise-time-choice-set legend "next-week" "1-3-5" 20 description))
+  ([legend week-choice day-choice time-choice description]
    [:fieldset.time-choice-set [:legend legend]
+    (when-not (or (nil? description) (false? description))
+      (into [:p]description))
     (start-week week-choice)
     (day-in-week day-choice)
     (time-in-day time-choice)]))

 (defn test-result-set
   ([legend]
-   (test-result-set legend 0))
-  ([legend checked-idx]
+   (test-result-set legend nil))
+  ([legend description]
+   (test-result-set legend 0 description))
+  ([legend checked-idx description]
    [:fieldset.result-set [:legend legend]
+    (when-not (or (nil? description) (false? description))
+      (into [:p] description))
     (into [:table [:tr [:th ""] [:th "Your Age"] [:th {:width "60%"} "How many push-ups did you do?"]]]
           (map-indexed (fn [idx [label sep]]
                          (test-input-row label idx (= idx checked-idx) sep))
@@ -78,8 +87,16 @@
   "generate initial form for creating a new calendar"
   [action]
   (form-to [:post action]
-           (exercise-time-choice-set "Arrange exercise time")
-           (test-result-set "Input initial test result")
+           (exercise-time-choice-set "Arrange exercise time"
+                                     "Chose the date and time you'd like to arrange your push-ups exercise at.
+                                     You will be able to change the settings after taken the first periodic test
+                                     two weeks later.")
+           (test-result-set "Input initial test result"
+                            [nil
+                             "Before your begin your exercise, try to execute as many good-form push ups as you can
+                            and count the number. Please click "
+                            (link-to "http://www.hundredpushups.com/test.html" "here")
+                            " for more infomation."])
            [:p.form-controllers
             (submit-button "Submit")
             (reset-button "Reset")]))


start using reg exp to make routes more specific

--- src/clj/clj_money/web/server.clj
+++ src/clj/clj_money/web/server.clj
@@ -56,6 +56,8 @@
                            wrap-models
                            wrap-integer-id-params)))

+(def ^:private id-pattern #"^[0-9]+$")
+
 (defroutes all-routes
   ; Entities
   (model-route GET "/entities" entities/index)
@@ -77,7 +79,7 @@
   (model-route GET "/entities/:entity-id/accounts" accounts/index)
   (model-route GET "/entities/:entity-id/accounts/new" accounts/new-account)
   (model-route POST "/entities/:entity-id/accounts" accounts/create)
-  (model-route GET "/accounts/:id" accounts/show)
+  (model-route GET ["/accounts/:id" :id id-pattern] accounts/show)
   (model-route GET "/accounts/:id/edit" accounts/edit)
   (model-route POST "/accounts/:id" accounts/update)
   (model-route POST "/accounts/:id/delete" accounts/delete)


feature: Add delete-datastore-raw to datastore features (#62)

--- src/clj/datasplash/datastore.clj
+++ src/clj/datasplash/datastore.clj
@@ -28,6 +28,15 @@
                    (cond-> query (.withQuery query))
                    (cond-> namespace (.withNamespace namespace))
                    (cond-> num-query-split (.withNumQuerySplits num-query-split)))]
+    (apply-transform pcoll ptrans named-schema opts)))
+
+(defn delete-datastore-raw
+  "delete a pcoll of already generated datastore entity from datastore"
+  [{:keys [project-id] :as options} pcoll]
+  (let [opts (assoc options :label :delete-datastore-raw)
+        ptrans (-> (DatastoreIO/v1)
+                   (.deleteEntity)
+                   (.withProjectId project-id))]
     (apply-transform pcoll ptrans named-schema opts)))

 (declare value->clj)


Check on common db exception msg

Check on common db exception msg

--- src/clj_crud/system/database.clj
+++ src/clj_crud/system/database.clj
@@ -45,8 +45,7 @@
        ;; might fail with the latest down migration that drops :migration_version
        (catch Exception e
          (let [msg (string/lower-case (.getMessage e))]
-           (when-not (and (.contains msg "migration_version")
-                          (.contains msg "does not exist"))
+           (when-not (.contains msg "migration_version")
              (throw e))))))

 (defn migrate!


add selectable list

add selectable list

--- src/cljs/material/component.cljs
+++ src/cljs/material/component.cljs
@@ -504,6 +504,55 @@
                          render-item-fn
                          render-items-key)))))

+;; List selectable component
+
+(defn list-selecttable-header
+  [headers]
+  (table-header
+    {:key               "th"
+     :displaySelectAll  true
+     :adjustForCheckbox true
+     :enableSelectAll   true
+     :style             {:border "none"}}
+    (table-row
+      {:key           "tr"
+       :displayBorder true}
+      (map-indexed
+        (fn [index header]
+          (table-header-column
+            {:key (str "thc-" index)}
+            header)) headers))))
+
+(defn list-selecttable-body
+  [items render-item-fn render-items-key]
+  (table-body
+    {:key                 "tb"
+     :showRowHover        true
+     :deselectOnClickaway true
+     :displayRowCheckbox  true}
+    (map-indexed
+      (fn [index item]
+        (table-row
+          {:key       (str "tr-" (:id item))
+           :style     {:cursor "pointer"}
+           :rowNumber index}
+          (->> (select-keys* item render-items-key)
+               (map #(table-row-column
+                       {:key (str "trc-" (:id item))}
+                       (render-item-fn % item)))))) items)))
+
+(defn list-selectable
+  [headers items render-item-fn render-items-key]
+  (mui
+    (table
+      {:key            "tbl"
+       :selectable     true
+       :onRowSelection nil}
+      (list-selecttable-header headers)
+      (list-selecttable-body items
+                             render-item-fn
+                             render-items-key))))
+
 ;; Form table component

 (defn form-table-header


Add form toggle btn to defn-form

Add form toggle btn to defn-form

--- src/cljs/whatishistory/core.cljs
+++ src/cljs/whatishistory/core.cljs
@@ -52,6 +52,7 @@
     [:input {:type "text"
              :class "authorInput"
              :placeholder "Your Name (Optional)"}]
+    [:a {:class "button formToggle"} "Add Another Author's Definition"]
     [:br]
     [:input {:type "email"
              :class "emailInput"