[#1104] Fix typo in format string

[#1104] Fix typo in format string

--- backend/src/akvo/lumen/admin/util.clj
+++ backend/src/akvo/lumen/admin/util.clj
@@ -18,9 +18,9 @@
           database (env :pg-database)
           user (env :pg-user)
           password (env :pg-password)}}]
-   (format "jdbc:postgresql://%s/%s?ssl=true&user=%s%s%s"
+   (format "jdbc:postgresql://%s/%s?ssl=true&user=%s%s"
            host database user
-           (if (or (= host "localhost") (= host "postgres") )
+           (if (or (= host "localhost") (= host "postgres"))
              ""
              (format "&password=%s" password)))))


proper error boxes

proper error boxes

--- frontend/src/leftover/ui.cljs
+++ frontend/src/leftover/ui.cljs
@@ -8,7 +8,8 @@
     [goog.string :as gstring]
     [om-bootstrap.button :as obb]
     [om-bootstrap.input :as obi]
-    [om-bootstrap.table :as obt]))
+    [om-bootstrap.table :as obt]
+    [om-bootstrap.random :as obr]))

 (def money-format "%.02f")

@@ -59,6 +60,13 @@
       (put! actions {:type :add-payment :args state})
       (om/set-state! owner :errors errors))))

+(defn show-error
+  [name error]
+  (if error
+    (obr/alert {:bs-style "danger"}
+               (dom/strong "Error: ")
+               (str name " " error))))
+
 (defn enter-payment [app owner]
   (reify
     om/IInitState
@@ -71,9 +79,9 @@
         (dom/div {:class "col-sm-6 component"}
                  (dom/form
                    (obi/input {:type "text" :placeholder "Location" :value location :on-change #(handle-change % owner :location)})
-                   (dom/div (get-in state [:errors :location]))
+                   (show-error "Location" (get-in state [:errors :location]))
                    (obi/input {:type "text" :placeholder "Amount" :value amount :on-change #(handle-change % owner :amount)})
-                   (dom/div (get-in state [:errors :amount]))
+                   (show-error "Amount" (get-in state [:errors :amount]))
                    (obb/button-group {:justified? true}
                                      (obb/button-group {} (obb/button { :bs-style "success" :on-click (fn [e] (.preventDefault e) (add-payment actions owner state) nil) } "Add")))))))))


Do not edit app name if move away from edit mode

Do this by resetting the submode

--- idecode/myappshare/mainapp.cljs
+++ idecode/myappshare/mainapp.cljs
@@ -232,7 +232,10 @@

             (button {:className    (if (small-screen) "btn btn-default" "btn-lg btn-default")
                      :style       {:display "inline-block" :marginLeft (if (small-screen) "2px"  "30px") :fontFamily "Ubuntu" :fontSize "1em" :marginTop "0.3em"}
-                     :onClick     #(write-ui app [:mode] "browse")} "Home")
+                     :onClick     #(do
+                                     (write-ui app [:mode] "browse")
+                                     (write-ui app [:submode] "")
+                                     )} "Home")

             (button {:className    (if (small-screen) "btn btn-default" "btn-lg btn-default")
                      :style       {:display "inline-block" :marginLeft (if (small-screen) "2px"  "30px") :fontFamily "Ubuntu" :fontSize "1em" :marginTop "0.3em"


url and title tests added

url and title tests added

--- test/webdriver/core_test.clj
+++ test/webdriver/core_test.clj
@@ -227,31 +227,27 @@
             (is (= bar nil))
             (is (= dunno nil))))))))

-
-
-;; (deftest test-url-title
-;;   (with-server host port
-;;     (wait-running :message "The server did not start.")
-;;     (with-session {} {}
-;;       (go-url "http://ya.ru")
-;;       (let [url (get-url)]
-;;         (is (= url "https://ya.ru/")))
-;;       (with-url url
-;;         (is (= url "https://ya.ru/")))
-;;       (let [title (get-title)]
-;;         (is (= title "Яндекс")))
-;;       (with-title title
-;;         (is (= title "Яндекс"))))))
-
-;; (deftest test-navigation
-;;   (with-server host port
-;;     (wait-running :message "The server did not start.")
-;;     (with-session {} {}
-;;       (go-url "http://ya.ru")
-;;       (go-url "http://mail.ru")
-;;       (back)
-;;       (refresh)
-;;       (forward)
-;;       (refresh)
-;;       (let [url (get-url)]
-;;         (is (= url "https://mail.ru/"))))))
+(deftest test-title
+  (let [url (-> "html/test.html" io/resource str)]
+    (wait-running :message "The server did not start.")
+    (with-session {} {}
+      (testing "empty page"
+        (with-title title
+          (is (= title ""))))
+      (testing "go URL"
+        (go-url url)
+        (with-title title
+          (is (= title "Webdriver Test Document")))))))
+
+(deftest test-url
+  (let [url (-> "html/test.html" io/resource str)]
+    (wait-running :message "The server did not start.")
+    (with-session {} {}
+      (testing "empry page"
+        (with-url url
+          (is (or (= url "about:blank")
+                  (= url "data:,")))))
+      (testing "go URL"
+        (go-url url)
+        (with-url url
+          (is (str/ends-with? url "/resources/html/test.html")))))))


Исправлена ошибка

Исправлена ошибка

--- radiolamp-6P3/src/ixinfestor/core.clj
+++ radiolamp-6P3/src/ixinfestor/core.clj
@@ -879,7 +879,7 @@
   (reduce
    (fn [{:keys [files images] :as  row}
         {content_type :content_type :as file-row}]
-     (if (contains? images-mime-types content_type)
+     (if (contains? images-content-types content_type)
        (assoc row :images (conj images file-row))
        (assoc row :files  (conj files  file-row))))
    (assoc row :images [] :files [])


Fix typo.

Fix typo.

--- src/apio/cli.clj
+++ src/apio/cli.clj
@@ -42,7 +42,7 @@
           thr     (thr/thread #(task-dispatcher queue))
           mq-conn (mq/initialize-connection (messages-dispatcher queue))]

-      ;; Add hook for key board interruption (sigint) and
+      ;; Add hook for keyboard interruption (sigint) and
       ;; properly close RabbitMQ connection.
       (let [hook (proxy [Thread] [] (run [] (mq/finish-connection mq-conn)))]
         (.addShutdownHook (Runtime/getRuntime) hook))


more logs

more logs

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -142,14 +142,16 @@
    as the first argument to render functions."
   [n filename NAME str "filename to read global metadata from"]
   (boot/with-pre-wrap fileset
-    (let [global-meta
+    (let [meta-file (or filename "perun.base.edn")
+          global-meta
             (some->> fileset
                      boot/user-files
-                     (boot/by-name [(or filename "perun.base.edn")])
+                     (boot/by-name [meta-file])
                      first
                      boot/tmp-file
                      slurp
                      read-string)]
+             (perun/report-info "global-metadata" "read global metadata from %s" meta-file)
              (perun/set-global-meta fileset global-meta))))

 (def ^:private ttr-deps


batch size

batch size

--- Clojure-Websockets/MainApp/src/cljs/birdwatch/state/search.cljs
+++ Clojure-Websockets/MainApp/src/cljs/birdwatch/state/search.cljs
@@ -11,8 +11,8 @@
   "Loads previous tweets matching the current search. Search is contructed
    by calling the util/query-string function with dereferenced app state."
   [app put-fn]
-  (let [chunks-to-load 10
-        chunk-size 500
+  (let [chunks-to-load 20
+        chunk-size 250
         prev-chunks-loaded (:prev-chunks-loaded @app)]
     (when (< prev-chunks-loaded chunks-to-load)
       (put-fn [:cmd/query {:query (util/query-string @app)


add 'aot' option for main

add 'aot' option for main

--- ch06-assembler/clj-hackasm/hackasm/project.clj
+++ ch06-assembler/clj-hackasm/hackasm/project.clj
@@ -3,4 +3,6 @@
   :url "http://example.com/FIXME"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[org.clojure/clojure "1.5.1"]])
+  :dependencies [[org.clojure/clojure "1.5.1"]]
+  :aot [hackasm.main])
+


Minor cosmetics for DL exploration code

Minor cosmetics for DL exploration code

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

--- src/conexp/contrib/dl/languages/EL_gfp_exploration.clj
+++ src/conexp/contrib/dl/languages/EL_gfp_exploration.clj
@@ -90,8 +90,8 @@
                    all-P_k-closure
                                 (model-closure next-model all-P_k),

-                   new-concepts (if (forall [[_ Q-closure] (vals P-map)]
-                                      (not (equivalent? all-P_k-closure Q-closure))),
+                   new-concepts (when (forall [[_ Q-closure] (vals P-map)]
+                                        (not (equivalent? all-P_k-closure Q-closure))),
                                   (for [r (role-names language)]
                                     (dl-expression language (exists r all-P_k-closure)))),
 		   next-M_k     (apply add-concepts! M_k new-concepts),
@@ -117,7 +117,8 @@
                                                                 :when (not-empty (conclusion impl))))]
                                   (if (not-empty (conclusion new-impl))
                                     (conj impls new-impl)
-                                    impls))
+                                    impls)),
+
 		   background-knowledge
                                 (minimal-implication-set next-M_k),


Change namespace reload order in wrap-reload

Fixes #376.

--- ring-devel/src/ring/middleware/reload.clj
+++ ring-devel/src/ring/middleware/reload.clj
@@ -6,11 +6,11 @@

 (defn- reloader [dirs retry?]
   (let [modified-namespaces (ns-tracker dirs)
-        load-queue (java.util.concurrent.LinkedBlockingQueue.)]
+        load-queue (java.util.concurrent.LinkedBlockingDeque.)]
     (fn []
       (locking load-queue
-        (doseq [ns-sym (modified-namespaces)]
-          (.offer load-queue ns-sym))
+        (doseq [ns-sym (reverse (modified-namespaces))]
+          (.push load-queue ns-sym))
         (loop []
           (when-let [ns-sym (.peek load-queue)]
             (if retry?


Function singleton-client now uses decorate-with

--- lib/compojure/cometd/cometd.clj
+++ lib/compojure/cometd/cometd.clj
@@ -135,12 +135,13 @@

 ;;;; Sending and receiving ;;;;

-(defvar- singleton-client
-  (memoize
-    (fn [bayeux]
-      (.newClient bayeux "publisher")))
-  "Creates a new client the first time its called, then returns the same
-  client for each subsequent call.")
+(defn singleton-client
+  "Creates a new client the first time its called, and returns the same
+  client for each subsequent call."
+  [bayeux]
+  (.newClient bayeux "publisher"))
+
+(decorate-with memoize singleton-client)

 (defn- clj->java
   "Convert a clojure data structure into Java-compatible types."


cosets.clj: coset table computation seems to work.

--- clojure/org/gavrog/clojure/cosets.clj
+++ clojure/org/gavrog/clojure/cosets.clj
@@ -1,28 +1,59 @@
 (ns org.gavrog.clojure.cosets
   (:use (org.gavrog.clojure
           free-word
-          partition)))
+          partition
+          util)))
+
+(defn- merge-rows [table equiv q a b]
+  (let [merge (fn [ra rb]
+                (reduce (fn [r g] (if (ra g) r (assoc r g (rb g))))
+                        ra (keys rb)))
+        row-a (merge (table a) (table b))
+        row-b (merge (table b) (table a))
+        q (into q (for [g (keys row-a)
+                        :when (not= (pfind equiv (row-a g))
+                                    (pfind equiv (row-b g)))]
+                    [(row-a g) (row-b g)]))
+        table (conj table [a row-a] [b row-a])]
+    [table q]))
+
+(defn- identify [table equiv i j]
+  (loop [q (conj empty-queue [i j])
+         table table
+         equiv equiv]
+    (if-let [[i j] (first q)]
+      (let [q (pop q)
+            a (pfind equiv i)
+            b (pfind equiv j)]
+        (if (= a b)
+          (recur q table equiv)
+          (let [equiv (punion equiv a b)
+                [table q] (merge-rows table equiv q a b)]
+            (recur q table equiv))))
+      [table equiv])))

 (defn- scan [table equiv w start]
-  (let [n (dec (count w))
+  (let [n (count w)
         [head a] (loop [row start, i 0]
-                   (let [next ((table row) (get w i))]
-                     (if (and next (< i n))
+                   (if (>= i n)
+                     [row i]
+                     (if-let [next ((table row) (get w i))]
                        (recur next (inc i))
                        [row i])))
         [tail b] (loop [row start, i n]
-                   (let [next ((table row) (inverse (get w i)))]
-                     (if (and next (>= i a))
+                   (if (<= i a)
+                     [row i]
+                     (if-let [next ((table row) (- (get w (dec i))))]
                        (recur next (dec i))
                        [row i])))]
-    (cond (= a b)
+    (cond (= (inc a) b)
           [(-> table
-             (assoc-in head (get w a) tail)
-             (assoc-in tail (inverse (get w a)) head))
+             (assoc-in [head (get w a)] tail)
+             (assoc-in [tail (- (get w a))] head))
            equiv]

-          (and (< b a) (not= head tail))
-          [table (punion equiv head tail)]
+          (and (= a b) (not= head tail))
+          (identify table equiv head tail)

           :else
           [table equiv])))
@@ -30,30 +61,38 @@
 (defn- scan-relations [rels subgens table equiv n]
   (let [[table equiv]
         (reduce (fn [[t p] w] (scan t p w n)) [table equiv] rels)]
-    (reduce (fn [[t p] w] (scan t p w 0)) [table equiv] subgens)))
+    (reduce (fn [[t p] w] (scan t p w (pfind equiv 0))) [table equiv] subgens)))

 (defn- compressed-table [table equiv]
-  table)
+  (let [canon (into {} (for [i (keys table)] [i (pfind equiv i)]))]
+    (into {} (for [[i row] table :when (= i (canon i))]
+               [i (into {} (map (fn [[j v]] [j (canon v)]) row))]))))

 (defn coset-table [nr-gens relators subgroup-gens]
-  (let [with-inverses (fn [ws] (vec (concat ws (map inverse ws))))
-        gens (with-inverses (map vector (range 1 (inc nr-gens))))
+  (let [with-inverses (fn [ws] (vec (into #{} (concat ws (map inverse ws)))))
+        gens (vec (concat (range 1 (inc nr-gens))
+                          (range -1 (- (inc nr-gens)) -1)))
         rels (with-inverses (for [w relators, i (range (count w))]
                               (into (subvec w i) (subvec w 0 i))))
         subgens (with-inverses subgroup-gens)]
-
     (loop [table {0 {}}
            equiv pempty
            i 0
            j 0]
-      (cond (>= i (count table))     (compressed-table table equiv)
-            (>= j (count gens))      (recur table equiv (inc i) 0)
-            ((table i) (get gens j)) (recur table equiv i (inc j))
+      (assert (< (count table) 500))
+      (cond (>= i (count table))
+            (compressed-table table equiv)
+
+            (or (>= j (count gens)) (not= i (pfind equiv i)))
+            (recur table equiv (inc i) 0)
+
+            ((table i) (get gens j))
+            (recur table equiv i (inc j))

             :else
             (let [g (get gens j)
-                  g* (inverse g)
+                  g* (- g)
                   n (count table)
-                  table (-> table (assoc-in i g n) (assoc-in n g* i))
+                  table (-> table (assoc-in [i g] n) (assoc-in [n g*] i))
                   [table equiv] (scan-relations rels subgens table equiv n)]
               (recur table equiv i (inc j)))))))


update comment

update comment

--- logcabin/src/jepsen/logcabin.clj
+++ logcabin/src/jepsen/logcabin.clj
@@ -21,9 +21,9 @@
             [cheshire.core :as json]))

 (defn install!
-  "Install logcabin"
-  [node]
-  (info node "installing logcabin")
+  "Install LogCabin"
+  [node]
+  (info node "installing LogCabin")
   (debian/install [:git-core
                    :protobuf-compiler
                    :libprotobuf-dev
@@ -43,7 +43,7 @@
     (c/exec :cp :-f "/logcabin/build/LogCabin" "/root")
     (c/exec :cp :-f "/logcabin/build/Examples/Reconfigure" "/root")
     (c/exec :cp :-f "/logcabin/build/Examples/TreeOps" "/root")
-    (info node "install logcabin ok")))
+    (info node "install LogCabin ok")))

 (defn server-id
   [node]
@@ -63,9 +63,9 @@
 (def treeops-bin "/root/TreeOps")

 (defn configure!
-  "Configure logcabin"
-  [node]
-  (info node "configuring logcabin")
+  "Configure LogCabin"
+  [node]
+  (info node "configuring LogCabin")
   (c/su
     (c/exec :echo (str
                     "serverId = "
@@ -76,33 +76,33 @@
             :> config-file)))

 (defn bootstrap!
-  "bootstrap logcabin"
-  [node]
-  (info node "bootstrapping logcabin")
+  "bootstrap LogCabin"
+  [node]
+  (info node "bootstrapping LogCabin")
   (c/su
     (c/cd "/root"
           (c/exec logcabin-bin :-c config-file :-l log-file :--bootstrap))))

 (defn start!
-  "Start logcabin"
-  [node]
-  (info node "starting logcabin")
+  "Start LogCabin"
+  [node]
+  (info node "starting LogCabin")
   (c/su
     (c/cd "/root"
           (c/exec logcabin-bin :-c config-file :-d :-l log-file :-p pid-file))))

 (defn stop!
-  "Stop logcabin"
-  [node]
-  (info node "stopping logcabin")
+  "Stop LogCabin"
+  [node]
+  (info node "stopping LogCabin")
   (c/su
     (cu/grepkill! :LogCabin)
     (c/exec :rm :-rf pid-file)))

 (defn reconfigure!
-  "Reconfigure logcabin servers"
-  [node]
-  (info node "reconfiguring logcabin servers")
+  "Reconfigure LogCabin servers"
+  [node]
+  (info node "reconfiguring LogCabin servers")
   (c/su
     (c/cd "/root"
           (c/exec reconfigure-bin
@@ -126,6 +126,7 @@
             ; Remove log file first.
             (c/exec :rm :-rf log-file)

+            ; Bootstrap in n1.
             (when (= node :n1)
               (bootstrap! node))

@@ -133,6 +134,7 @@
             (start! node)

             (jepsen/synchronize test)
+            ; Use Reconfigure tool to set up the LogCabin cluster in n1.
             (when (= node :n1)
               (reconfigure! node))

@@ -148,15 +150,18 @@
                (info node "tore down"))))

 (def cas-msg-pattern
+  "LogCabin returns following error for CAS failed"
   (re-pattern "Exiting due to LogCabin::Client::Exception: Path '.*' has value '.*', not '.*' as required"))

 (def timeout-msg-pattern
   (re-pattern "Exiting due to LogCabin::Client::Exception: Client-specified timeout elapsed"))

-(def op-timeout 3)
+(def op-timeout
+  "Use 3s for LogCabin operation timeout"
+  3)

 (defn logcabin-get!
-  "get a value for path"
+  "Get a value for path"
   [node path]
   (c/on node
         (c/su
@@ -198,6 +203,7 @@
                           :write
                           (c/lit path)))))
     (catch Exception e
+      ; For CAS failed, we return false, otherwise, re-raise the error.
       (if (re-matches cas-msg-pattern (str/trim (.getMessage e)))
         false
         (throw e)))))
@@ -236,6 +242,6 @@
   (teardown! [_ test]))

 (defn cas-client
-  "A compare and set register built around a single logcabin node."
+  "A compare and set register built around a single LogCabin node."
   []
   (CASClient. "/jepsen" nil))


Add Textmorph locking

Add Textmorph locking

--- src-cljs/cljs_workspace/om_morph.cljs
+++ src-cljs/cljs_workspace/om_morph.cljs
@@ -188,7 +188,7 @@

 (defn create-text-node [app owner]
     (dom/div #js {:className "visible Selection"
-                  :contentEditable true
+                  :contentEditable (nil? (get-in app [:morph :AllowInput]))
                   :onMouseDown #(swap! clicked-morph (fn [_] @app :id))
                   :onInput #(handle-input % owner app)
                   ; :onKeyDown #(when (.-metaKey %) (save-input % owner app))} (dom/span #js {
@@ -250,9 +250,10 @@

 (defmethod shape "Text" [app owner]
   (prn "Rendering Text Shape")
-  (let [style (dict->js (extract-style (:shape app)))]
-    (dom/div #js {:style style
-                  :className "Morph Text"} (create-text-node app owner))))
+  (let [style (extract-style (:shape app))]
+    (let [text-style (assoc style "cursor" "default")]
+      (dom/div #js {:style (dict->js text-style)
+                    :className "Morph Text"} (create-text-node app owner)))))

 (defmethod shape :default [app owner]
   (let [style (extract-style (:shape app))]


Improve example README

Improve example README

--- examples/todomvc/project.clj
+++ examples/todomvc/project.clj
@@ -2,7 +2,7 @@
   :dependencies [[org.clojure/clojure "1.6.0"]
                  [org.clojure/clojurescript "0.0-3208"]
                  [reagent "0.5.0"]
-                 [re-frame "0.4.0"]
+                 [re-frame "0.4.1"]
                  [figwheel "0.2.6"]
                  [secretary "1.2.3"]]


Updates from last month

Updates from last month

--- scrape-n-mail/src/scrape_n_mail/core.cljs
+++ scrape-n-mail/src/scrape_n_mail/core.cljs
@@ -186,8 +186,7 @@
                [:br]
                [:p "Dear " (::submitter-name (first name-records)) ","]

-               [:p "You should have recently recieved the monthly announcement for the renewal of "
-                   "names for wellbeing. That email goes into more detail than this one and includes a photo of the altar. "]
+               [:p "Our call for names for Wellbeing for August 2018 is out: http://center.transformativechange.org/?p=1883"]

                [:p "Currently, the community is holding the following names on the altar "
                    "in support of their wellbeing at your request. You can click "


express initial ideas for authorization and a dynamic menu

--- src/aspire/security.clj
+++ src/aspire/security.clj
@@ -1,5 +1,6 @@
 (ns aspire.security
   (:require [digest :refer [md5]]
+            [clojure.string :as str]
             [aspire.data.user :refer [get-valid-user]]
             [aspire.util :refer [keywords->ns]]
             [cemerick.friend :as friend]
@@ -62,3 +63,34 @@
   [ring-route]
   nil
   )
+
+(defn authorized?
+  "low-granularity, page-level authorization checker
+   Returns a fn that takes in a ring request and checks that the
+   currently authenticated user has at least one of the specified
+   roles."
+  [& roles]
+  (fn authorized?* [request]
+    (let [ca (friend/current-authentication request)
+          privilege (-> ca :privilege str/lower-case keyword)]
+      (some #{privilege} roles))))
+
+;; This menu stuff is a total hack, and probably doesn't even belong
+;; in this file. (Putting it in util.clj causes circular deps...)
+;; TODO: Somehow combine this with our actual routes.
+;; TODO: How to combine this page-level access with more granular
+;; access based on parameters in the route (e.g., you can update
+;; *your* profile, but not just any profile)?
+(def menu-items
+  {:admin {:route "/admin" :name "Admin" :weight 100 :authorized? (authorized? :admin)}
+   :home {:route "/" :name "Home" :weight 0 :authorized? (constantly true)}
+   :onboarding {:route "/welcome" :name "Competency Map" :weight 10 :authorized? (constantly true)}})
+
+(defn menu [request]
+  (let [ca (friend/current-authentication request)]
+    (->> menu-items
+         (filter (fn menu-f* [[k v]]
+                   (let [f (:authorized? v)]
+                     (f request))))
+         (sort (fn menu-s* [& _] true)))))
+


Back out a change that prevented tests from loading

--- dev-resources/user.clj
+++ dev-resources/user.clj
@@ -7,7 +7,7 @@
     [io.aviso.twixt :only [get-asset-uris default-options]]
     io.aviso.twixt.startup
     ring.adapter.jetty)
-  #_ (:require
+  (:require
     ;; See https://github.com/slagyr/speclj/issues/79
     speclj.run.standard))


comments and logging improvements

comments and logging improvements

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -196,9 +196,9 @@
                                 (if (empty? (get-in spec [:synsem :subcat]))
                                   "(empty)"
                                   (get-in spec [:synsem :subcat :1 :sem :pred] :no-pred))]
-                            (log/warn (str "could generate neither phrasal nor lexical complements for parent: "
-                                           (get-in bolt (concat (butlast path) [:rule]) :norule-wtf) " "
-                                           "with complement having: "
+                            (log/warn (str "add-complement-to-bolt: could generate neither phrasal nor lexical complements for parent: "
+                                           (get-in bolt (concat (butlast path) [:rule]) :norule) " "
+                                           "while trying to create a complement with:"
                                            "cat: " cat "; "
                                            "pred: " pred "; "
                                            "subcat1 cat: " subcat1-cat "; "
@@ -209,6 +209,17 @@

                           true
                           (lazy-cat phrasal-complements (lazy-shuffle filtered-lexical-complements))))))))
+
+(defn spec-info [spec]
+  "give a human-readable summary of _spec_."
+  (merge
+   (if-let [cat (get-in spec [:synsem :cat] :top)]
+     {:cat cat})
+   (if-let [pred (get-in spec [:synsem :sem :pred] :top)]
+     {:pred pred})
+   (if-let [subcat1 (if (not (empty? (get-in spec [:synsem :subcat])))
+                      (get-in spec [:synsem :subcat :1 :cat]))]
+     {:subcat1 subcat1})))

 (defn lightning-bolts [language-model spec depth total-depth
                        & {:keys [max-total-depth]
@@ -217,12 +228,18 @@
 there is only one child for each parent, and that single child is the
 head of its parent. generate (above) 'decorates' each returned lightning bolt
 of this function with complements."
-  (log/trace (str "lightning-bolts(depth=" depth "; total-depth=" total-depth "; cat=" (get-in spec [:synsem :cat]) "; spec=" (strip-refs spec) ")"))
+  (log/info (str "lightning-bolts(depth=" depth
+                 "; total-depth=" total-depth
+                 "; max-total-depth=" max-total-depth
+                 "; spec info:" (spec-info spec)))
   (let [morph (:morph language-model)
         grammar (:grammar language-model)
         index (:index language-model)
         morph (if morph morph (fn [input] (get-in input [:rule] :default-morph-no-rule)))
-        depth (if depth depth 0)
+        depth (if depth depth 0)
+        ;; this is the relative depth; that is, the depth from the top of the current lightning bolt.
+        ;; total-depth, on the other hand, is the depth all the way to the top of the entire
+        ;; expression, which might involve several parent lightning bolts.
         parents (shuffle (candidate-parents grammar spec))]
     (let [lexical ;; 1. generate list of all phrases where the head child of each parent is a lexeme.
           (lazy-mapcat (fn [parent]


Add links to graphs in API docs.

Add links to graphs in API docs.

Also converted to Markdown to enable this, added formatting, clarified
slightly, and fixed some incorrect values which were left over from
before the waves had their current characteristics.

--- src/afterglow/effects/oscillators.clj
+++ src/afterglow/effects/oscillators.clj
@@ -10,12 +10,16 @@
     (- sum (long sum))))

 (defn sawtooth-beat
-  "Returns an oscillator which generates a sawtooth wave relative to the phase
-  of the current beat. Passing true for down? creates an inverse sawtooth wave
-  (ramps downward rather than upward), supplying a beat ratio will run the
-  oscillator at the specified fraction or multiple of a beat, and supplying a
-  phase will offset the oscillator from the underlying metronome phase by that
-  amount."
+  "Returns an oscillator which generates a sawtooth wave relative to
+  the phase of the current beat. Passing `true` with `:down?` creates
+  an inverse sawtooth wave (ramps downward rather than upward),
+  supplying a value with `:beat-ratio` will run the oscillator at the
+  specified fraction or multiple of a beat, and supplying a `:phase`
+  will offset the oscillator from the underlying metronome phase by
+  that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#sawtooth-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [down? beat-ratio phase] :or {down? false beat-ratio 1 phase 0.0}}]
   (cond (and (= beat-ratio 1) (= phase 0.0)) ; Simplest case; maybe no calculation
         (if down?
@@ -40,11 +44,14 @@

 (defn sawtooth-bar
   "Returns an oscillator which generates a sawtooth wave relative to the phase
-  of the current bar. Passing true for down? creates an inverse sawtooth wave
-  (ramps downward rather than upward), supplying a bar ratio will run the
-  oscillator at the specified fraction or multiple of a bar, and supplying a
-  phase will offset the oscillator from the underlying metronome phase by that
-  amount."
+  of the current bar. Passing `true` with `:down?` creates an inverse sawtooth
+  wave (ramps downward rather than upward), supplying a value with
+  `:bar-ratio` will run the oscillator at the specified fraction or
+  multiple of a bar, and supplying a `:phase` will offset the oscillator
+  from the underlying metronome phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#sawtooth-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [down? bar-ratio phase] :or {down? false bar-ratio 1 phase 0.0}}]
   (cond (and (= bar-ratio 1) (= phase 0.0))  ; Simplest case, maybe no calculation
         (if down?
@@ -69,11 +76,14 @@

 (defn sawtooth-phrase
   "Returns an oscillator which generates a sawtooth wave relative to the phase
-  of the current phrase. Passing true for down? creates an inverse sawtooth wave
-  (ramps downward rather than upward), supplying a phrase ratio will run the
-  oscillator at the specified fraction or multiple of a phrase, and supplying a
-  phase will offset the oscillator from the underlying metronome phase by that
-  amount."
+  of the current phrase. Passing `true` with `:down?` creates an inverse sawtooth wave
+  (ramps downward rather than upward), supplying a value with
+  `:phrase-ratio` will run the oscillator at the specified fraction or
+  multiple of a phrase, and supplying a `:phase` will offset the
+  oscillator from the underlying metronome phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#sawtooth-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [down? phrase-ratio phase] :or {down? false phrase-ratio 1 phase 0.0}}]
   (cond (and (= phrase-ratio 1) (= phase 0.0))  ; Simplest case, maybe no calculation
         (if down?
@@ -97,11 +107,14 @@
             (adjust-phase (rhythm/snapshot-phrase-phase snapshot phrase-ratio) phase)))))

 (defn triangle-beat
-  "Returns an oscillator which generates a triangle wave relative to the phase
-  of the current beat. Supplying a beat ratio will run the oscillator at
-  the specified fraction or multiple of a beat, and supplying a phase
-  will offset the oscillator from the underlying metronome phase by that
-  amount."
+  "Returns an oscillator which generates a triangle wave relative to
+  the phase of the current beat. Supplying a value with `:beat-ratio`
+  will run the oscillator at the specified fraction or multiple of a
+  beat, and supplying a `:phase` will offset the oscillator from the
+  underlying metronome phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#triangle-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [beat-ratio phase] :or {beat-ratio 1 phase 0.0}}]
   (fn [^afterglow.rhythm.MetronomeSnapshot snapshot]
     (let [reached (adjust-phase (rhythm/snapshot-beat-phase snapshot beat-ratio) phase)]
@@ -110,11 +123,14 @@
         (- 2.0 (* reached 2.0))))))

 (defn triangle-bar
-  "Returns an oscillator which generates a triangle wave relative to the phase
-  of the current bar. Supplying a bar ratio will run the oscillator at
-  the specified fraction or multiple of a bar, and supplying a phase
-  will offset the oscillator from the underlying metronome phase by that
-  amount."
+  "Returns an oscillator which generates a triangle wave relative to
+  the phase of the current bar. Supplying a value with `:bar-ratio`
+  will run the oscillator at the specified fraction or multiple of a
+  bar, and supplying a `:phase` will offset the oscillator from the
+  underlying metronome phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#triangle-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [bar-ratio phase] :or {bar-ratio 1 phase 0.0}}]
   (fn [^afterglow.rhythm.MetronomeSnapshot snapshot]
     (let [reached (adjust-phase (rhythm/snapshot-bar-phase snapshot bar-ratio) phase)]
@@ -123,11 +139,14 @@
         (- 2.0 (* reached 2.0))))))

 (defn triangle-phrase
-  "Returns an oscillator which generates a triangle wave relative to the phase
-  of the current phrase. Supplying a phrase ratio will run the oscillator at
-  the specified fraction or multiple of a phrase, and supplying a phase
-  will offset the oscillator from the underlying metronome phase by that
-  amount."
+  "Returns an oscillator which generates a triangle wave relative to
+  the phase of the current phrase. Supplying a value with
+  `:phrase-ratio` will run the oscillator at the specified fraction or
+  multiple of a phrase, and supplying a `:phase` will offset the
+  oscillator from the underlying metronome phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#triangle-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [phrase-ratio phase] :or {phrase-ratio 1 phase 0.0}}]
   (fn [^afterglow.rhythm.MetronomeSnapshot snapshot]
     (let [reached (adjust-phase (rhythm/snapshot-phrase-phase snapshot phrase-ratio) phase)]
@@ -136,14 +155,18 @@
         (- 2.0 (* reached 2.0))))))

 (defn square-beat
-  "Returns an oscillator which generates a square wave relative to the phase
-  of the current beat. Specifying a width adjusts how much of the time the
-  wave is on (high); the default is 0.5, lower values cause it to turn off
-  sooner, larger values later. In any case the width must be greater than
-  0.0 and less than 1.0. Supplying a beat ratio will run the oscillator at
-  the specified fraction or multiple of a beat, and supplying a phase
-  will offset the oscillator from the underlying metronome phase by that
-  amount. "
+  "Returns an oscillator which generates a square wave relative to the
+  phase of the current beat. Specifying a value with `:width` adjusts
+  how much of the time the wave is _on_ (high); the default is `0.5`,
+  lower values cause it to turn off sooner, larger values later. In
+  any case the width must be greater than `0.0` and less than `1.0`.
+  Supplying a value with `:beat-ratio` will run the oscillator at the
+  specified fraction or multiple of a beat, and supplying a `:phase`
+  will offset the oscillator from the underlying metronome phase by
+  that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#square-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [width beat-ratio phase] :or {width 0.5 beat-ratio 1 phase 0.0}}]
   (when-not (and (> width 0.0) (< width 1.0))
     (throw (IllegalArgumentException. "width must fall between 0.0 and 1.0")))
@@ -154,14 +177,18 @@
         0.0))))

 (defn square-bar
-  "Returns an oscillator which generates a square wave relative to the phase
-  of the current bar. Specifying a width adjusts how much of the time the
-  wave is on (high); the default is 0.5, lower values cause it to turn on
-  sooner, larger values later. In any case the width must be greater than
-  0.0 and less than 1.0. Supplying a bar ratio will run the oscillator at
-  the specified fraction or multiple of a bar, and supplying a phase
-  will offset the oscillator from the underlying metronome phase by that
-  amount. "
+  "Returns an oscillator which generates a square wave relative to the
+  phase of the current bar. Specifying a value with `:width` adjusts
+  how much of the time the wave is _on_ (high); the default is `0.5`,
+  lower values cause it to turn off sooner, larger values later. In
+  any case the width must be greater than `0.0` and less than `1.0`.
+  Supplying a value with `:bar-ratio` will run the oscillator at the
+  specified fraction or multiple of a bar, and supplying a `:phase`
+  will offset the oscillator from the underlying metronome phase by
+  that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#square-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [width bar-ratio phase] :or {width 0.5 bar-ratio 1 phase 0.0}}]
   (when-not (and (> width 0.0) (< width 1.0))
     (throw (IllegalArgumentException. "width must fall between 0.0 and 1.0")))
@@ -172,14 +199,18 @@
         0.0))))

 (defn square-phrase
-  "Returns an oscillator which generates a square wave relative to the phase
-  of the current phrase. Specifying a width adjusts how much of the time the
-  wave is on (high); the default is 0.5, lower values cause it to turn on
-  sooner, larger values later. In any case the width must be greater than
-  0.0 and less than 1.0. Supplying a phrase ratio will run the oscillator at
-  the specified fraction or multiple of a phrase, and supplying a phase
-  will offset the oscillator from the underlying metronome phase by that
-  amount. "
+  "Returns an oscillator which generates a square wave relative to the
+  phase of the current phrase. Specifying a value with `:width`
+  adjusts how much of the time the wave is _on_ (high); the default is
+  `0.5`, lower values cause it to turn off sooner, larger values
+  later. In any case the width must be greater than `0.0` and less
+  than `1.0`. Supplying a value with `:phrase-ratio` will run the
+  oscillator at the specified fraction or multiple of a phrase, and
+  supplying a `:phase` will offset the oscillator from the underlying
+  metronome phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#square-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [width phrase-ratio phase] :or {width 0.5 phrase-ratio 1 phase 0.0}}]
   (when-not (and (> width 0.0) (< width 1.0))
     (throw (IllegalArgumentException. "width must fall between 0.0 and 1.0")))
@@ -190,12 +221,16 @@
         0.0))))

 (defn sine-beat
-  "Returns an oscillator which generates a sine wave relative to the phase
-  of the current beat. The wave has value 0.0 at phase 0.0, rising to 1.0
-  at phase 0.5, and returning to 0.0. Supplying a beat ratio will run the
-  oscillator at the specified fraction or multiple of a beat, and supplying
-  a phase will offset the oscillator from the underlying metronome phase by
-  that amount. "
+  "Returns an oscillator which generates a sine wave relative to the
+  phase of the current beat. The wave has value `0.0` at phase `0.0`,
+  rising to `1.0` at phase `0.5`, and returning to `0.0`. Supplying a
+  value with `:beat-ratio` will run the oscillator at the specified
+  fraction or multiple of a beat, and supplying a `:phase` will offset
+  the oscillator from the underlying metronome phase by that amount.
+  (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#sine-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [beat-ratio phase] :or {beat-ratio 1 phase 0.0}}]
   (let [adjusted-phase (- phase 0.25)
         two-pi (* 2.0 Math/PI)]
@@ -203,12 +238,16 @@
       (+ 0.5 (Math/sin (* two-pi (adjust-phase (rhythm/snapshot-beat-phase snapshot beat-ratio) adjusted-phase)))))))

 (defn sine-bar
-  "Returns an oscillator which generates a sine wave relative to the phase
-  of the current bar. The wave has value 1.0 at phase 0.0, dropping to 0.0
-  at phase 0.5, and returning to 1.0. Supplying a bar ratio will run the
-  oscillator at the specified fraction or multiple of a bar, and supplying
-  a phase will offset the oscillator from the underlying metronome phase by
-  that amount. "
+  "Returns an oscillator which generates a sine wave relative to the
+  phase of the current bar. The wave has value `0.0` at phase `0.0`,
+  rising to `1.0` at phase `0.5`, and returning to `0.0`. Supplying a
+  value with `:bar-ratio` will run the oscillator at the specified
+  fraction or multiple of a bar, and supplying a `:phase` will offset
+  the oscillator from the underlying metronome phase by that
+  amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#sine-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [bar-ratio phase] :or {bar-ratio 1 phase 0.0}}]
   (let [adjusted-phase (- phase 0.25)
         two-pi (* 2.0 Math/PI)]
@@ -216,12 +255,16 @@
       (+ 0.5 (* 0.5 (Math/sin (* two-pi (adjust-phase (rhythm/snapshot-bar-phase snapshot bar-ratio) adjusted-phase))))))))

 (defn sine-phrase
-  "Returns an oscillator which generates a sine wave relative to the phase
-  of the current phrase. The wave has value 1.0 at phase 0.0, dropping to 0.0
-  at phase 0.5, and returning to 1.0. Supplying a phrase ratio will run the
-  oscillator at the specified fraction or multiple of a phrase, and supplying
-  a phase will offset the oscillator from the underlying metronome phase by
-  that amount. "
+  "Returns an oscillator which generates a sine wave relative to the
+  phase of the current phrase. The wave has value `0.0` at phase
+  `0.0`, rising to `1.0` at phase `0.5`, and returning to `0.0`.
+  Supplying a value with `:phrase-ratio` will run the oscillator at
+  the specified fraction or multiple of a phrase, and supplying a
+  `:phase` will offset the oscillator from the underlying metronome
+  phase by that amount. (See the
+  [documentation](https://github.com/brunchboy/afterglow/blob/master/doc/oscillators.adoc#sine-oscillators)
+  for an expanded explanation illustrated with graphs.)"
+  {:doc/format :markdown}
   [& {:keys [phrase-ratio phase] :or {phrase-ratio 1 phase 0.0}}]
   (let [adjusted-phase (- phase 0.25)
         two-pi (* 2.0 Math/PI)]


let them eat cake

let them eat cake

--- src/cake/tasks/help.clj
+++ src/cake/tasks/help.clj
@@ -44,4 +44,9 @@
     (apply task-doc (map symbol names))
     (list-all-tasks)))

-(deftask default #{help})+(deftask default #{help})
+
+(deftask eat
+  (while (not (.ready *in*))
+    (println "the cake is a lie.")
+    (Thread/sleep 300)))


[#154] More readable cache logic

[#154] More readable cache logic

--- api/src/clojure/org/akvo/flow_api/boundary/user.clj
+++ api/src/clojure/org/akvo/flow_api/boundary/user.clj
@@ -16,8 +16,8 @@
   (cache/has? @cache [instance-id email]))

 (defn id-by-email [{:keys [user-cache unknown-user-cache] :as this} instance-id email]
-  (if-let [id (get-id user-cache instance-id email)]
-    id
+  (or
+    (get-id user-cache instance-id email)
     (when-not (has? unknown-user-cache instance-id email)
       (ds/with-remote-api this instance-id
         (let [id (user/id email)


maximum -> max

maximum -> max

--- docs/sc-book/sc-one.clj
+++ docs/sc-book/sc-one.clj
@@ -37,7 +37,7 @@
                speed 1000]
            (* (mix
                (map #(pan2 (* (sin-osc (* % 100))
-                              (maximum 0 (+ (lf-noise1:kr speed) (line:kr 1 -1 30))))
+                              (max 0 (+ (lf-noise1:kr speed) (line:kr 1 -1 30))))
                            (- (clojure.core/rand 2) 1))
                     (range sines)))
               (/ 1 sines))))
@@ -571,7 +571,7 @@
   (defsynth mod-syn [] (out delay-b (* (in mod-b 2) (sin-osc (+ 1100 (* 500 (in:kr k5-b)))))))
   (def m-syn (mod-syn :pos :before :tgt d-syn))

-  (defsynth gate-syn [] (out [0 mod-b] (* (in gate-b 2) (maximum 0 (in:kr k5-b)))))
+  (defsynth gate-syn [] (out [0 mod-b] (* (in gate-b 2) (max 0 (in:kr k5-b)))))
   (def g-syn (gate-syn :pos :before :tgt m-syn ))

   (def pb-group (group :before c-syn))
@@ -665,19 +665,19 @@

 (demo 15
       (* 0.3
-         (+ (* (sin-osc 220)  (maximum 0 (lf-noise1:kr 12)) 1)
-            (* (sin-osc 440)  (maximum 0 (lf-noise1:kr 12)) 1/2)
-            (* (sin-osc 660)  (maximum 0 (lf-noise1:kr 12)) 1/3)
-            (* (sin-osc 880)  (maximum 0 (lf-noise1:kr 12)) 1/4 )
-            (* (sin-osc 1110) (maximum 0 (lf-noise1:kr 12)) 1/5)
-            (* (sin-osc 1320) (maximum 0 (lf-noise1:kr 12)) 1/6))))
+         (+ (* (sin-osc 220)  (max 0 (lf-noise1:kr 12)) 1)
+            (* (sin-osc 440)  (max 0 (lf-noise1:kr 12)) 1/2)
+            (* (sin-osc 660)  (max 0 (lf-noise1:kr 12)) 1/3)
+            (* (sin-osc 880)  (max 0 (lf-noise1:kr 12)) 1/4 )
+            (* (sin-osc 1110) (max 0 (lf-noise1:kr 12)) 1/5)
+            (* (sin-osc 1320) (max 0 (lf-noise1:kr 12)) 1/6))))

 ;; or the more compact but equivalent:

 (demo 15
       (let [freqs [220 440 660 880 1110 1320]
             muls  [1   1/2 1/3 1/4 1/5  1/6]
-            mk-sin #(* (sin-osc %1) (maximum 0 (lf-noise1 12)) %2)
+            mk-sin #(* (sin-osc %1) (max 0 (lf-noise1 12)) %2)
             sins  (map mk-sin freqs muls)]
         (* (mix sins) 0.3)))

@@ -703,7 +703,7 @@
           (for [count (range 12)]
             (let [harm (* (inc count) 110)]
               (* (sin-osc harm)
-                 (maximum [0 0] (sin-osc:kr (/ (inc count) 4)))
+                 (max [0 0] (sin-osc:kr (/ (inc count) 4)))
                  (/ 1 (inc count))))))))


Refactor derivative code

Refactor derivative code

--- src/clj/algorithms_clj/derivative.clj
+++ src/clj/algorithms_clj/derivative.clj
@@ -9,31 +9,34 @@
 (defn prod? [expr] (contains? #{* '* `*} (first expr)))
 (defn sum?  [expr] (contains? #{+ '+ `+} (first expr)))

+(defn simplify-if-unary-op
+  [expr]
+  (cond
+    (= 1 (count expr)) (apply (first expr))
+    (= 2 (count expr)) (second expr)
+    :else expr))
+
 (defn make-sum
   "Simplify the sum, adding the constants together"
   [terms]
-  (let [parts (group-by number? terms)
-        number-sum (reduce + (parts true))]
+  (let [exprs (filter (complement number?) terms)
+        number-sum (reduce + (filter number? terms))]
     (cond
-      (empty? (parts false)) number-sum
-      (zero? number-sum) (if-not (= 1 (count (parts false)))
-                           (into [+] (parts false))
-                           (first (parts false)))
-      :else (into [+ number-sum] (parts false))
+      (empty? exprs) number-sum
+      (zero? number-sum) (simplify-if-unary-op (into [+] exprs))
+      :else (into [+ number-sum] exprs)
       )))

 (defn make-product
   "Simplify the product, multiplying the constants together"
   [terms]
-  (let [parts (group-by number? terms)
-        product (reduce * (parts true))]
+  (let [exprs (filter (complement number?) terms)
+        product (reduce * (filter number? terms))]
     (cond
-      (empty? (parts false)) product
-      (= 1 product) (if-not (= 1 (count (parts false)))
-       (into [*] (parts false))
-       (first (parts false)))
+      (empty? exprs) product
+      (= 1 product) (simplify-if-unary-op (into [*] exprs))
       (zero? product) 0
-      :else (into [* product] (parts false))
+      :else (into [* product] exprs)
       )))

 (declare derivative)


Remove spaces

Remove spaces

--- src-cljs/frontend/components/account.cljs
+++ src-cljs/frontend/components/account.cljs
@@ -115,15 +115,12 @@
                               :key-fn :token
                               :columns [{:header "Label"
                                          :cell-fn :label}
-
                                         {:header "Token"
                                          :type :shrink
                                          :cell-fn :token}
-
                                         {:header "Created"
                                          :type :shrink
                                          :cell-fn (comp datetime/medium-datetime js/Date.parse :time)}
-
                                         {:header "Remove"
                                          :type :shrink
                                          :cell-fn
@@ -132,7 +129,6 @@
                                             "Remove"
                                             (icon/cancel-circle)
                                             #(raise! owner [:api-token-revocation-attempted {:token token}])))}]}))]]]))])))))
-

 (def available-betas
   [{:id "project-cache-clear-buttons"


Changed copy from Primary to Default

Changed copy from Primary to Default

--- src-cljs/frontend/components/account.cljs
+++ src-cljs/frontend/components/account.cljs
@@ -303,7 +303,7 @@
   [:div.card
    [:div.header
     [:h2
-     "Primary Email Address"]]
+     "Default Email Address"]]
    [:div.body
     [:div.section
      [:form#email_address.form-horizontal


improve list of terms for make button

improve list of terms for make button

--- src-cljs/frontend/components/landing.cljs
+++ src-cljs/frontend/components/landing.cljs
@@ -124,32 +124,31 @@
     om/IDisplayName (display-name [_] "Landing Make Button")
     om/IInitState
     (init-state [_]
-      {:word-list ["demos"
+      {:word-list ["something"
+                   "UI/UX"
+                   "demos"
                    "stuff"
                    "lines"
                    "squares"
                    "circles"
                    "doodles"
-                   "mockups"
                    "designs"
                    "layouts"
-                   "details"
                    "diagrams"
                    "sketches"
                    "drawings"
                    "giraffes"
                    "projects"
-                   "concepts"
                    "products"
+                   "anything"
+                   "something"
                    "new ideas"
                    "documents"
-                   "precursors"
                    "prototypes"
                    "wireframes"
                    "user flows"
                    "flowcharts"
                    "interfaces"
-                   "inventions"
                    "some stuff"
                    "life easier"
                    "experiences"
@@ -160,6 +159,7 @@
                    "illustrations"
                    "walk-throughs"
                    "awesome ideas"
+                   "with Precursor"
                    "teammates happy"
                    "your team happy"]})
     om/IDidMount


tell people to email us if they're having problems with txes not saving

--- src-cljs/frontend/controllers/errors.cljs
+++ src-cljs/frontend/controllers/errors.cljs
@@ -126,12 +126,15 @@
   [container message {:keys [reason sente-event datom-group]} previous-state current-state]
   (chat-model/create-bot-chat (:db current-state)
                               current-state
-                              [:span "There was an error saving some of your recent changes. The affected shapes have been marked with dashed lines. "
+                              [:span "There was an error saving some of your recent changes. Affected shapes are marked with dashed lines. "
                                [:a {:role "button"
                                     :on-click #(put! (get-in current-state [:comms :controls])
                                                      [:retry-unsynced-datoms])}
                                 "Click here to retry"]
-                               ". You may also want to work on the document in a separate tab, in case there are any persistent problems."]
+                               ". You may also want to work on the document in a separate tab, in case there are any persistent problems. "
+                               "Email " [:a {:href "mailto:hi@precursorapp.com?subject=My+changes+aren't+saving"}
+                                         "hi@precursorapp.com"]
+                               " for help."]
                               {:error/id :error/sync-tx-error})
   (d/transact! (:db current-state)
                (mapv (fn [e] [:db/add e :unsaved true])


Allow job snapshot coordinates to be looked up by job-name AND tenancy-id (#877)

* Dispatch job-ids-history, clear-job-data, clear-tenancy on OnyxClient

* Allow job-ids-history to be restricted to tenancy-id

* Add named-job-snapshot-coordinates method for job lookup with tenancy-id

--- src/onyx/api.clj
+++ src/onyx/api.clj
@@ -282,27 +282,42 @@
    This information can then be used to playback a log and get the current job state, and to resolve to resume point coordinates via onyx.api/job-snapshot-coordinates.
    Connector can take either a ZooKeeper address as a string, or a ZooKeeper log component.
    History is the order of earliest to latest."
-  (fn [connector job-name]
-    (type connector)))
+  (fn
+    ([connector job-name]
+     (type connector))
+    ([connector tenancy-id job-name]
+     (type connector))))

 (defmethod job-ids-history org.apache.curator.framework.imps.CuratorFrameworkImpl
-  [conn job-name]
-  (loop [position 0 entries []]
-    (let [entry (try (extensions/read-job-name-metadata conn job-name position)
-                     (catch org.apache.zookeeper.KeeperException$NoNodeException nne))]
-      (if entry
-        (recur (inc position) (conj entries entry))
-        entries))))
+  ([conn job-name]
+   (job-ids-history conn nil job-name))
+  ([conn tenancy-id job-name]
+   (loop [position 0 entries []]
+     (let [entry (try (extensions/read-job-name-metadata conn job-name position)
+                      (catch org.apache.zookeeper.KeeperException$NoNodeException nne))]
+       (if entry
+         (recur (inc position) (conj entries entry))
+         (if (some? tenancy-id)
+           (filter #(= tenancy-id (:tenancy-id %)) entries)
+           entries))))))

 (defmethod job-ids-history String
-  [zookeeper-address job-name]
-  (s/validate s/Str zookeeper-address)
-  (s/validate os/JobName job-name)
-  (let [conn (zk/connect zookeeper-address)]
-    (try
-     (job-ids-history conn job-name)
-     (finally
-      (zk/close conn)))))
+  ([zookeeper-address job-name]
+   (job-ids-history zookeeper-address nil job-name))
+  ([zookeeper-address tenancy-id job-name]
+   (s/validate s/Str zookeeper-address)
+   (s/validate os/JobName job-name)
+   (let [conn (zk/connect zookeeper-address)]
+     (try
+       (job-ids-history conn tenancy-id job-name)
+       (finally
+         (zk/close conn))))))
+
+(defmethod job-ids-history OnyxClient
+  ([client job-name]
+   (job-ids-history client nil job-name))
+  ([client tenancy-id job-name]
+   (job-ids-history (:conn (:log client)) tenancy-id job-name)))

 (defmulti clear-job-data
   "Takes a peer-config, zookeeper-address string, or a curator connection, and deletes
@@ -327,6 +342,10 @@
      (finally
       (zk/close conn)))))

+(defmethod clear-job-data OnyxClient
+  [client tenancy-id job-id]
+  (clear-job-data (:conn (:log client)) tenancy-id job-id))
+
 (defmulti clear-tenancy
   "Takes a zookeeper-address string or a curator connection, and deletes
    all data for a given tenancy from ZooKeeper, including job data and cluster logs.
@@ -348,6 +367,10 @@
      (finally
       (zk/close conn)))))

+(defmethod clear-tenancy OnyxClient
+  [client tenancy-id]
+  (clear-tenancy (:conn (:log client)) tenancy-id))
+
 (defmulti job-snapshot-coordinates
   "Reads the latest full snapshot coordinate stored for a given job-id and
    tenancy-id. This snapshot coordinate can be supplied to build-resume-point
@@ -361,18 +384,42 @@
     ([connector job-name]
      (type connector))))

+(defmulti named-job-snapshot-coordinates
+  "Reads the latest full snapshot coordinate stored for a given job-name and
+   optional tenancy-id. This snapshot coordinate can be supplied to build-resume-point
+   to build a full resume point."
+  ^{:added "0.14.0"}
+  (fn
+    ([connector job-name]
+     (type connector))
+    ([connector tenancy-id job-name]
+     (type connector))))
+
+(defmethod named-job-snapshot-coordinates org.apache.curator.framework.imps.CuratorFrameworkImpl
+  ([conn job-name]
+   (named-job-snapshot-coordinates conn nil job-name))
+  ([conn tenancy-id job-name]
+   (s/validate os/JobName job-name)
+   (let [history (reverse (job-ids-history conn tenancy-id job-name))]
+     (loop [id (first history) rst (rest history)]
+       (when id
+         (if-let [coordinates (job-snapshot-coordinates conn (:tenancy-id id) (:job-id id))]
+           coordinates
+           (recur (first rst) (rest rst))))))))
+
+(defmethod named-job-snapshot-coordinates OnyxClient
+  ([client job-name]
+   (named-job-snapshot-coordinates (:conn (:log client)) nil job-name))
+  ([client tenancy-id job-name]
+   (named-job-snapshot-coordinates (:conn (:log client)) tenancy-id job-name)))
+
 (defmethod job-snapshot-coordinates org.apache.curator.framework.imps.CuratorFrameworkImpl
   ([conn tenancy-id job-id]
    (info "Reading checkpoint coordinate at: " tenancy-id job-id)
    (try (onyx.log.zookeeper/read-checkpoint-coord conn tenancy-id job-id)
         (catch org.apache.zookeeper.KeeperException$NoNodeException nne nil)))
   ([conn job-name]
-   (let [history (reverse (job-ids-history conn job-name))]
-     (loop [id (first history) rst (rest history)]
-       (when id
-         (if-let [coordinates (job-snapshot-coordinates conn (:tenancy-id id) (:job-id id))]
-           coordinates
-           (recur (first rst) (rest rst))))))))
+   (named-job-snapshot-coordinates conn job-name)))

 (defn ^{:no-doc true} with-conn [zookeeper-address f]
   (s/validate s/Str zookeeper-address)


Remove now useless todo comment.

Remove now useless todo comment.

--- src/continuo/postgresql/bootstrap.clj
+++ src/continuo/postgresql/bootstrap.clj
@@ -60,9 +60,7 @@

 (defn initialize'
   [conn schema]
-  (attrs/populate-schema conn schema)
-  ;; TODO: populate schema into local schema atom.
-  )
+  (attrs/populate-schema conn schema))

 (defn initialize
   [tx]


Don't overrwrite notify-email, it's loaded from config now.

--- backend/src/circle/web/views/github_commit_hook.clj
+++ backend/src/circle/web/views/github_commit_hook.clj
@@ -61,8 +61,7 @@
     (let [build (circle/circle-build)]
       (dosync
        (alter build merge
-              {:notify-email (-> github-json :repository :owner :email)
-               :vcs-url (->ssh (-> github-json :repository :url))
+              {:vcs-url (->ssh (-> github-json :repository :url))
                :repository (-> github-json :repository)
                :commits (-> github-json :commits)
                :vcs-revision (-> github-json :commits last :id)


got some more perf hints from the cljs compiler

--- src/chessground/ui.cljs
+++ src/chessground/ui.cljs
@@ -1,20 +1,24 @@
 (ns chessground.ui
   (:require [cljs.core.async :as a]
             [chessground.common :as common :refer [pp]]
-            [chessground.react :as react]
             [chessground.data :as data]
             [chessground.chess :as chess]
             [chessground.premove :as premove]
-            [chessground.drag :as drag]
-            [chessground.api :as api])
+            [chessground.drag :as drag])
   (:require-macros [cljs.core.async.macros :as am]))
+
+(def ^private dom (.-DOM js/React))
+
+(def ^private div (.-div dom))
+
+(defn- class-set [obj] (-> obj js/Object.keys (.filter #(aget obj %)) (.join " ")))

 (defn- piece-hash [props]
   (when-let [piece (aget props "piece")]
-    (str (aget piece "color") (aget piece "role") (aget piece "draggable?"))))
+    (.join #js [(aget piece "color") (aget piece "role") (aget piece "draggable?")])))

 (defn- make-diff [prev next]
-  (fn [k] (not= (aget prev k) (aget next k))))
+  (fn [k] (not (== (aget prev k) (aget next k)))))

 (def ^private piece-component
   (js/React.createClass
@@ -23,8 +27,8 @@
      :shouldComponentUpdate
      (fn [next-props _]
        (this-as this
-                (or (not= (aget (.-props this) "color") (aget next-props "color"))
-                    (not= (aget (.-props this) "role") (aget next-props "role")))))
+                (or (not (== (aget (.-props this) "color") (aget next-props "color")))
+                    (not (== (aget (.-props this) "role") (aget next-props "role"))))))
      :componentDidMount
      (fn []
        (this-as this
@@ -46,9 +50,9 @@
      :render
      (fn []
        (this-as this
-                (react/div #js {:className (str "cg-piece" " "
-                                                (aget (.-props this) "color") " "
-                                                (aget (.-props this) "role"))})))}))
+                (div #js {:className (str "cg-piece" " "
+                                          (aget (.-props this) "color") " "
+                                          (aget (.-props this) "role"))})))}))

 (def ^private square-component
   (js/React.createClass
@@ -64,10 +68,10 @@
                       (diff? "check?")
                       (diff? "last-move?")
                       (diff? "current-premove?")
-                      (not= (piece-hash (.-props this))
-                            (piece-hash next-props))
-                      (not= (aget (.-props this) "orientation")
-                            (aget next-props "orientation"))))))
+                      (not (== (piece-hash (.-props this))
+                               (piece-hash next-props)))
+                      (not (== (aget (.-props this) "orientation")
+                               (aget next-props "orientation")))))))
      :componentDidMount
      (fn []
        (this-as this
@@ -88,26 +92,23 @@
                       x (inc (.indexOf "abcdefgh" (get key 0)))
                       y (js/parseInt (get key 1))
                       style-x (str (* (dec x) 12.5) "%")
-                      style-y (str (* (dec y) 12.5) "%")
-                      style (if white?
-                              #js {"left" style-x "bottom" style-y}
-                              #js {"right" style-x "top" style-y})
-                      coord-x (when (= y (if white? 1 8)) (get key 0))
-                      coord-y (when (= x (if white? 8 1)) y)
-                      classes #js {"cg-square" true
-                                   "selected" (read "selected?")
-                                   "check" (read "check?")
-                                   "last-move" (read "last-move?")
-                                   "move-dest" (read "move-dest?")
-                                   "premove-dest" (read "premove-dest?")
-                                   "current-premove" (read "current-premove?")}]
-                  (react/div #js {:style style
-                                  :className (react/class-set classes)
-                                  :data-key key
-                                  :data-coord-x coord-x
-                                  :data-coord-y coord-y}
-                             (when-let [piece (read "piece")]
-                               (piece-component piece))))))}))
+                      style-y (str (* (dec y) 12.5) "%")]
+                  (div #js
+                       {:style (if white?
+                                 #js {"left" style-x "bottom" style-y}
+                                 #js {"right" style-x "top" style-y})
+                        :className (class-set #js {"cg-square" true
+                                                   "selected" (read "selected?")
+                                                   "check" (read "check?")
+                                                   "last-move" (read "last-move?")
+                                                   "move-dest" (read "move-dest?")
+                                                   "premove-dest" (read "premove-dest?")
+                                                   "current-premove" (read "current-premove?")})
+                        :data-key key
+                        :data-coord-x (when (== y (if white? 1 8)) (get key 0))
+                        :data-coord-y (when (== x (if white? 8 1)) y)}
+                       (when-let [piece (read "piece")]
+                         (piece-component piece))))))}))

 (def ^private board-component
   (js/React.createClass
@@ -116,9 +117,9 @@
      :render
      (fn []
        (this-as this
-                (react/div #js {:className "cg-board"}
-                           (.map (aget (.-props this) "chess")
-                                 square-component))))}))
+                (div #js {:className "cg-board"}
+                     (.map (aget (.-props this) "chess")
+                           square-component))))}))

 (def ^private all-keys
   (let [arr (array)]
@@ -136,8 +137,8 @@
         chess (get app :chess)
         draggable-color (data/draggable-color app)
         last-move (array-of (get app :last-move))
-        selected (array-of (get app :selected))
-        check (array-of (get app :check))
+        selected (get app :selected)
+        check (get app :check)
         current-premove (array-of (get (get app :premovable) :current))
         move-dests (array-of (when-let [orig (get app :selected)]
                                (when (data/movable? app orig)
@@ -155,13 +156,13 @@
                       #js {:ctrl ctrl
                            :color color
                            :role (get piece :role)
-                           :draggable? (= draggable-color color)}))
-           :selected? (= selected key)
-           :check? (= check key)
-           :last-move? (not= -1 (.indexOf last-move key))
-           :move-dest? (not= -1 (.indexOf move-dests key))
-           :premove-dest? (not= -1 (.indexOf premove-dests key))
-           :current-premove? (not= -1 (.indexOf current-premove key))})))
+                           :draggable? (== draggable-color color)}))
+           :selected? (== selected key)
+           :check? (== check key)
+           :last-move? (not (== -1 (.indexOf last-move key)))
+           :move-dest? (not (== -1 (.indexOf move-dests key)))
+           :premove-dest? (not (== -1 (.indexOf premove-dests key)))
+           :current-premove? (not (== -1 (.indexOf current-premove key)))})))

 (defn root [app ctrl]
   ; (js/console.time "root")


[core] only report time measurements that are larged than a given threshold (50ms by default)

--- core/src/gorillalabs/tesla/component/telemetry.clj
+++ core/src/gorillalabs/tesla/component/telemetry.clj
@@ -7,6 +7,8 @@
 ;;;              :prefix     "app.backend."     ;; automatically prefix all service names
 ;;;              :interval   60                 ;; seconds
 ;;;              :queue-size 1000               ;; how many messages can be buffered
+;;;              :threshold  50                 ;; minimum number of milliseconds
+;;;                                             ;; for a timed even to be actually reported
 ;;;              }}

 (ns gorillalabs.tesla.component.telemetry
@@ -58,14 +60,17 @@
   (let [start (gensym)
         result (gensym)
         elapsed (gensym)
-        values (gensym)]
+        values (gensym)
+        threshold (gensym)]
     (list 'if (list :host 'gorillalabs.tesla.component.telemetry/telemetry)
-          (list 'let [start   (list 'System/currentTimeMillis)
-                      result  expr
-                      elapsed (list '- (list 'System/currentTimeMillis) start)
-                      values  (list 'merge props {:service identifier :metric elapsed :unit "ms" :type "timed"})]
-                (list 'gorillalabs.tesla.component.telemetry/enqueue 'gorillalabs.tesla.component.telemetry/telemetry values)
+          (list 'let [threshold (list 'get-in 'gorillalabs.tesla.component.telemetry/telemetry [:config :threshold] 50)
+                      start     (list 'System/currentTimeMillis)
+                      result    expr
+                      elapsed   (list '- (list 'System/currentTimeMillis) start)
+                      values    (list 'merge props {:service identifier :metric elapsed :unit "ms" :type "timed"})]
                 (list 'log/debugf "[%s] took %dms." identifier elapsed)
+                (list 'if (list '>= elapsed threshold)
+                      (list 'gorillalabs.tesla.component.telemetry/enqueue 'gorillalabs.tesla.component.telemetry/telemetry values))
                 result)
           expr)))


Load speclj.run.standard to satisfy dependencies

closes #79

--- src/clj/speclj/core.clj
+++ src/clj/speclj/core.clj
@@ -2,6 +2,9 @@
   "Speclj's API.  It contains nothing but macros, so that it can be used
   in both Clojure and ClojureScript."
   (:require [clojure.data]))
+
+(try (require 'speclj.run.standard)
+  (catch Exception _))

 (def ^:private cljs? (boolean (find-ns 'cljs.analyzer)))


add docstring to cljs.core/*target*

add docstring to cljs.core/*target*

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -17,8 +17,12 @@

 (def *unchecked-if* false)

-(def ^{:dynamic true
-       :jsdoc ["@define {string}"]}
+(def
+  ^{:dynamic true
+    :doc "Var bound to the name value of the compiler build :target
+  option. If compiler build :target is :nodejs, *target* will be bound to
+  \"nodejs\"."
+    :jsdoc ["@define {string}"]}
   *target* "default")

 (defonce


Made extend-object! private.  There is probably a better way to achieve the functionality that it provides (e.g. extending Object on type definition)

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -1005,6 +1005,16 @@
 (defn- hash-coll [coll]
   (reduce #(hash-combine %1 (hash %2)) (hash (first coll)) (next coll)))

+(defn- extend-object!
+  "Takes a JavaScript object and a map of names to functions and
+  attaches said functions as methods on the object.  Any references to
+  JavaScript's implict this (via the this-as macro) will resolve to the
+  object that the function is attached."
+  [obj fn-map]
+  (doseq [[key-name f] fn-map]
+    (let [str-name (name key-name)]
+      (js* "~{obj}[~{str-name}] = ~{f}")))
+  obj)

 ;;;;;;;;;;;;;;;; cons ;;;;;;;;;;;;;;;;
 (deftype List [meta first rest count]
@@ -3265,14 +3275,3 @@
 (defn prefers
   "Given a multimethod, returns a map of preferred value -> set of other values"
   [multifn] (-prefers multifn))
-
-(defn extend-object!
-  "Takes a JavaScript object and a map of names to functions and
-  attaches said functions as methods on the object.  Any references to
-  JavaScript's implict this (via the this-as macro) will resolve to the
-  object that the function is attached."
-  [obj fn-map]
-  (doseq [[key-name f] fn-map]
-    (let [str-name (name key-name)]
-      (js* "~{obj}[~{str-name}] = ~{f}")))
-  obj)


fix reduce call in transduce

fix reduce call in transduce

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -1664,7 +1664,7 @@
   ([xform f coll] (transduce xform f (f) coll))
   ([xform f init coll]
      (let [f (xform (completing f))
-           ret (reduce coll f init)
+           ret (reduce f init coll)
            ret (f (if (reduced? ret) @ret ret))]
        (if (reduced? ret) @ret ret))))


Fix lone parens on newlines

Fix lone parens on newlines

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -280,8 +280,7 @@
     ([array f]
        (ci-reduce array f))
     ([array f start]
-       (ci-reduce array f start)))
-  )
+       (ci-reduce array f start))))

 (defn seq
   "Returns a seq on the collection. If the collection is
@@ -823,8 +822,7 @@
   (-seq [coll] coll)

   ICounted
-  (-count [coll] count)
-  )
+  (-count [coll] count))

 (deftype EmptyList [meta]
   IWithMeta
@@ -858,9 +856,7 @@
   (-seq [coll] nil)

   ICounted
-  (-count [coll] 0)
-
-  )
+  (-count [coll] 0))

 (set! cljs.core.List/EMPTY (EmptyList. nil))

@@ -897,9 +893,7 @@
   (-hash [coll] (hash-coll coll))

   ISeqable
-  (-seq [coll] coll)
-
-  )
+  (-seq [coll] coll))

 (defn cons
   "Returns a new seq where x is the first element and seq is the rest."


Add "!" to each function name that do some side-effect.

--- src/clojure/nanomsg.clj
+++ src/clojure/nanomsg.clj
@@ -10,14 +10,14 @@
                                  :req ReqSocket :rep RepSocket
                                  :bus BusSocket :pair PairSocket})

-(defn bind
+(defn bind!
   "Given a socket and connection string,
   add a local endpoint to the socket."
   [^RWSocket sock, ^String dir]
   (.bind sock dir)
   sock)

-(defn connect
+(defn connect!
   "Given a socket and connection string,
   connect to remote socket."
   [^RWSocket sock, ^String dir]
@@ -37,35 +37,35 @@
        (:connect opts) (connect instance (:connect opts)))
      instance)))

-(defn subscribe
+(defn subscribe!
   "Subscribe a current subscriber socket
   to specified string pattern."
   [^SubSocket sock, ^String pattern]
   {:pre [(instance? SubSocket sock)]}
   (.subscribe sock pattern))

-(defn send
+(defn send!
   "Send string data"
   [^RWSocket sock, ^String data & {:keys [blocking] :or {blocking true}}]
   {:pre [(string? data)]}
   (.sendString sock data blocking))

-(defn recv
+(defn recv!
   "Recv data as string"
   [^RWSocket sock & {:keys [blocking] :or {blocking true}}]
   (.recvString sock blocking))

-(defn send-bytes
+(defn send-bytes!
   "Send bytes data"
   [^RWSocket sock, data & {:keys [blocking] :or {blocking true}}]
   (.sendBytes sock data blocking))

-(defn recv-bytes
+(defn recv-bytes!
   "Recv data as bytes"
   [^RWSocket sock & {:keys [blocking] :or {blocking true}}]
   (.recvBytes sock blocking))

-(defn close
+(defn close!
   "Close socket."
   [^RWSocket sock]
   (.close sock))


Fixed issue #5: Ability to add new corrected and enhanced description for selected package.

--- src/clouseau/server.clj
+++ src/clouseau/server.clj
@@ -9,6 +9,12 @@

 (require '[clouseau.products :as products])

+(def ccs-db
+    {:classname   "org.sqlite.JDBC"
+     :subprotocol "sqlite"
+     :subname     "ccs_descriptions.db"
+    })
+
 (defn read-description
     [product package]
     (let [result (jdbc/query (second product) (str "select description from packages where name='" package "';"))
@@ -16,6 +22,20 @@
         (if (not desc)
             [:div {:class "alert alert-danger"} "Not found"]
             [:div {:class "alert alert-success"} (.replaceAll desc "\n" "
")])))
+
+(defn read-ccs-description
+    [package]
+    (let [result (jdbc/query ccs-db (str "select description from packages where name='" package "';"))
+          desc   (:description (first result))]
+        (if (not desc)
+            nil
+            desc))) ; (.replaceAll desc "\n" "
"))))
+
+(defn store-ccs-description
+    [package description]
+    (jdbc/delete! ccs-db :packages ["name = ?" package])
+    (jdbc/insert! ccs-db :packages {:name package :description description})
+)

 (defn render-html-header
     [package]
@@ -63,13 +83,25 @@
 ]);

 (defn html-renderer
-    [products package]
+    [products package ccs-description]
     (page/xhtml
         (render-html-header package)
         [:body
             [:div {:class "container"}
                 (render-navigation-bar-section package)

+                (if (and package (not (empty? package)))
+                    (form/form-to [:post "/"]
+                        [:div {:class "label label-primary"} "Description provided by CCS"]
+                        [:br]
+                        (form/hidden-field "package" (str package))
+                        (form/text-area {:cols "120" :rows "10"} "new-description" ccs-description)
+                        [:br]
+                        (form/submit-button {:class "btn btn-danger"} "Update description")
+                        [:br]
+                        [:br]
+                    ))
+
                 (if (and package (not (empty? package)))
                     [:table {:class "table table-stripped"}
                         (for [product products]
@@ -95,9 +127,13 @@
     (println "")
     (let [params              (request :params)
           uri                 (request :uri)
-          package             (get params "package")]
-          (-> (http-response/response (html-renderer products/products package))
-              (http-response/content-type "text/html"))))
+          package             (get params "package")
+          new-description     (get params "new-description")]
+          (if (and (not-empty-parameter? package) (not-empty-parameter? new-description))
+              (store-ccs-description package new-description))
+          (let [ccs-description (read-ccs-description package)]
+              (-> (http-response/response (html-renderer products/products package ccs-description))
+                  (http-response/content-type "text/html")))))

 (defn return-file
     [file-name content-type]


Whitespace.

Whitespace.

--- src/clum/app/state.cljs
+++ src/clum/app/state.cljs
@@ -3,11 +3,11 @@

 (defonce app-state
   (let [initial-state (-> (reduce (fn [acc [x y]]
-                                  (assoc acc [x y] {:highlighted? false}))
-                                {}
-                                (for [x (range 8)
-                                      y (range 8)]
-                                  [x y]))
+                                    (assoc acc [x y] {:highlighted? false}))
+                                  {}
+                                  (for [x (range 8)
+                                        y (range 8)]
+                                    [x y]))
                           (merge {:higlighted-set #{}
                                   :connected?     false}))]
     (r/atom initial-state)))


run-system takes profile as keyword

run-system takes profile as keyword

Taking it as a string is incorrect, profiles are expected to be
keywords.

--- build.boot
+++ build.boot
@@ -150,7 +150,7 @@
    (target :dir #{"static"})))

 (deftask run-system
-  [p profile VAL str "Profile to start system with"]
+  [p profile VAL kw "Profile to start system with"]
   (require 'edge.system)
   (let [new-system (resolve 'edge.system/new-system)]
     (with-post-wrap fileset


use refactored boot_lib

use refactored boot_lib

--- build.boot
+++ build.boot
@@ -1,50 +1,16 @@
-;; use lein to parse the project.clj for the deps
-;; since lein-modules merges from the hierarchy
-(require '[boot.pod :as pod])
+(load-file "../build/boot_lib.clj")

-(def lein-pod (pod/make-pod
-               (update-in (get-env) [:dependencies]
-                          conj '[leiningen "2.7.1"])))
+(configure-minimal-env
+ {:source-paths #{"src" "test"}
+  :resource-paths  #{"dev-resources"}})

-(defn cassandra-unit-proj
-  []
-  (pod/with-eval-in lein-pod
-    (require '[leiningen.core.project :as p])
-    (p/read "project.clj" [:cassandra-unit])))
+(run-embedded-cassandra)

-(def cass-deps (:dependencies (cassandra-unit-proj)))
+(configure-yapster-repos)

-(def cass-pod (pod/make-pod
-               (update-in (get-env) [:dependencies]
-                          concat cass-deps)))
-
-(pod/with-eval-in cass-pod
-  (import '[org.cassandraunit.utils EmbeddedCassandraServerHelper])
-  (EmbeddedCassandraServerHelper/startEmbeddedCassandra))
-
-(defn test-proj
-  []
-  (pod/with-eval-in lein-pod
-    (require '[leiningen.core.project :as p])
-    (p/read "project.clj" [:test])))
-
-(def test-deps (:dependencies (test-proj)))
 (set-env!
- :wagons       '[[s3-wagon-private "1.2.0"]]
-
- :repositories #(concat % [["releases" {:url "s3p://yapster-s3-wagon/releases/"
-                                        :username [:env/aws_access_key :gpg]
-                                        :passphrase [:env/aws_secret_key :gpg]}]
-                           ["snapshots" {:url "s3p://yapster-s3-wagon/snapshots/"
-                                         :username [:env/aws_access_key :gpg]
-                                         :passphrase [:env/aws_secret_key :gpg]}]])
-
- :dependencies test-deps
-
- :source-paths #{"src" "test"})
+ :dependencies
+ (:dependencies (read-project "project.clj" [:test])))

 (require
  '[adzerk.boot-test :refer [test]])
-
-;; set system-property for embedded test
-(System/setProperty "cassandra_port" "9142")


deps must be vectors

deps must be vectors

--- build.boot
+++ build.boot
@@ -3,25 +3,26 @@
  :version "0.1.0-SNAPSHOT"
  :description "A clojure(script) library to assist with transitions between dimensions"
  :url "http://github.com/pleasetrythisathome/bardo"
- :dependencies (concat (->>
-                        '[[adzerk/boot-cljs "0.0-2411-5"]
-                          [adzerk/boot-cljs-repl "0.1.7"]
-                          [adzerk/boot-reload "0.2.0"]
-                          [deraen/boot-cljx "0.2.0"]
-                          [pandeiro/boot-http "0.3.0"]
-                          [com.cemerick/double-check "0.6.1"]
-                          [org.clojure/tools.namespace "0.2.7"]
-                          [clojure-complete "0.2.4"]
-                          [garden "1.2.5"]
-                          [om "0.8.0-beta3"]
-                          [sablono "0.2.22" :exclusions [com.facebook/react]]]
-                        (mapv #(conj % :scope "test")))
-                       '[[org.clojure/clojure "1.7.0-alpha4"]
-                         [org.clojure/clojurescript "0.0-2411"]
-                         [org.clojure/core.async "0.1.346.0-17112a-alpha"]
-                         [org.clojure/core.match "0.2.2"]
-                         [clj-time "0.8.0"]
-                         [com.andrewmcveigh/cljs-time "0.2.4"]])
+ :dependencies (vec
+                (concat (->>
+                         '[[adzerk/boot-cljs "0.0-2411-5"]
+                           [adzerk/boot-cljs-repl "0.1.7"]
+                           [adzerk/boot-reload "0.2.0"]
+                           [deraen/boot-cljx "0.2.0"]
+                           [pandeiro/boot-http "0.3.0"]
+                           [com.cemerick/double-check "0.6.1"]
+                           [org.clojure/tools.namespace "0.2.7"]
+                           [clojure-complete "0.2.4"]
+                           [garden "1.2.5"]
+                           [om "0.8.0-beta3"]
+                           [sablono "0.2.22" :exclusions [com.facebook/react]]]
+                         (mapv #(conj % :scope "test")))
+                        '[[org.clojure/clojure "1.7.0-alpha4"]
+                          [org.clojure/clojurescript "0.0-2411"]
+                          [org.clojure/core.async "0.1.346.0-17112a-alpha"]
+                          [org.clojure/core.match "0.2.2"]
+                          [clj-time "0.8.0"]
+                          [com.andrewmcveigh/cljs-time "0.2.4"]]))
  :source-paths    #{"src"}
  :resource-paths    #{"resources"})


fixed a small bug

fixed a small bug

--- src/cards/untangled/components/forms.cljs
+++ src/cards/untangled/components/forms.cljs
@@ -11,6 +11,8 @@
             [untangled.client.core :as uc]
             [untangled.client.mutations :as m]))

+(declare add-phone-mutation ValidatedPhoneForm)
+
 (defn field-with-label
   "A non-library helper function, written by you to help lay out your form."
   ([comp form name label] (field-with-label comp form name label nil))
@@ -43,9 +45,9 @@

 (defn add-phone-mutation [{:keys [state]} k {:keys [id person]}]
   {:action (fn []
-             (let [new-phone (uc/initial-state PhoneForm {:db/id id :phone/type :home :phone/number ""})
+             (let [new-phone (uc/initial-state ValidatedPhoneForm {:db/id id :phone/type :home :phone/number ""})
                    person-ident [:people/by-id person]
-                   phone-ident (om/ident PhoneForm new-phone)]
+                   phone-ident (om/ident ValidatedPhoneForm new-phone)]
                (swap! state assoc-in phone-ident new-phone)
                (uc/integrate-ident! state phone-ident :append (conj person-ident :person/phone-numbers))))})

@@ -182,7 +184,7 @@

 (defui ValidatedPhoneRoot
   static om/IQuery
-  (query [this] [{:phone (om/get-query ValidatedPhoneForm)}])
+  (query [this] [:ui/form {:phone (om/get-query ValidatedPhoneForm)}])
   static uc/InitialAppState
   (initial-state [this params]
     (let [phone-number {:db/id 1 :phone/type :home :phone/number "555-1212"}]
@@ -240,7 +242,6 @@
   (initial-state [this params] (f/build-form this (or params {})))
   static f/IForm
   (fields [this] [(f/id-field :db/id)
-                  (f/text-input :person/name 'name-valid?)
                   (f/text-input :person/name 'name-valid?)
                   (f/numeric-input :person/age 'in-range? {:min 1 :max 110})
                   (f/checkbox-input :person/registered-to-vote?)])
@@ -347,7 +348,7 @@
   each represented by a nested phone number entity/form. Note the use of `InitialAppState` in Root to build out sample
   data.
   "
-  (dc/mkdn-pprint-source PhoneForm)
+  (dc/mkdn-pprint-source ValidatedPhoneForm)
   (dc/mkdn-pprint-source PersonForm)
   (dc/mkdn-pprint-source Root)
   "


added a hook for main

added a hook for main

--- src/leiningen/new/cryogen/project.clj
+++ src/leiningen/new/cryogen/project.clj
@@ -18,5 +18,6 @@
                  [crouton "0.1.2"]
                  [cheshire "5.3.1"]]
   :plugins [[lein-ring "0.8.13"]]
+  :main cryogen.compiler
   :ring {:init cryogen.server/init
          :handler cryogen.server/handler})


support for fetching service tasks by label (agent related) #260

--- src/clj/swarmpit/docker/engine/client.clj
+++ src/clj/swarmpit/docker/engine/client.clj
@@ -33,21 +33,43 @@
       :body))

 (defn service-tasks
-  [id]
-  (-> (execute {:method  :GET
-                :api     "/tasks"
-                :options {:query-params {:filters (generate-string {:service [id]})}}})
-      :body))
+  ([id]
+   (service-tasks id false))
+  ([id running?]
+   (-> (execute {:method  :GET
+                 :api     "/tasks"
+                 :options {:query-params
+                           {:filters
+                            (generate-string
+                              (merge {:service [id]}
+                                     (when running?
+                                       {:desired-state ["running"]})))}}})
+       :body)))
+
+(defn service-tasks-by-label
+  ([label]
+   (service-tasks-by-label label false))
+  ([label running?]
+   (-> (execute {:method  :GET
+                 :api     "/tasks"
+                 :options {:query-params
+                           {:filters
+                            (generate-string
+                              (merge {:label [label]}
+                                     (when running?
+                                       {:desired-state ["running"]})))}}})
+       :body)))

 (defn service-logs
-  [id]
+  [id since]
   (-> (execute {:method  :GET
                 :api     (str "/services/" id "/logs")
                 :options {:query-params {:details    true
                                          :stdout     true
                                          :stderr     true
                                          :timestamps true
-                                         :tail       2000}}})
+                                         :tail       2000
+                                         :since      since}}})
       :body))

 (defn delete-service


fixed merge

fixed merge

--- src/cljs/redditv/components/sidepane.cljs
+++ src/cljs/redditv/components/sidepane.cljs
@@ -10,9 +10,8 @@
   (swap! app-state assoc
          :subreddit subreddit
          :playlist-selected-index 0)
-  (playlist/reload app-state)
-  (set-hash! (app-hash app-state))
-  (force-app-reload! app-state))
+  (playlist/reload app-state :reload? true)
+  (set-hash! (app-hash app-state)))

 (def mixin-focus-search-bar
   {:did-update (fn [state]


Add more logging when we join on the mesos driver (#1297)


adds append-output and update-action pusher handling

--- frontend/controllers/ws.cljs
+++ frontend/controllers/ws.cljs
@@ -38,3 +38,33 @@
                                                                           :actions []}))
             (update-in [:current-build] build-model/fill-actions step-index action-index action-log)
             (assoc-in [:current-build :steps step-index :actions action-index] action-log))))))
+
+(defmethod ws-event :build/update-action
+  [pusher-imp message {:keys [data channel-name]} state]
+  (let [build (:current-build state)]
+    (if-not (= (pusher/build-channel build) channel-name)
+      (do
+        (mlog "Ignoring event for old build channel: " channel-name)
+        state)
+      (let [{step-index :step action-index :index action-log :log} (js->clj data :keywordize-keys true)]
+        (-> state
+            (update-in [:current-build] build-model/fill-steps step-index)
+            (update-in [:current-build :steps step-index] (fnil identity {:name (:name action-log)
+                                                                          :actions []}))
+            (update-in [:current-build] build-model/fill-actions step-index action-index action-log)
+            (update-in [:current-build :steps step-index :actions action-index] merge action-log))))))
+
+(defmethod ws-event :build/append-action
+  [pusher-imp message {:keys [data channel-name]} state]
+  (let [build (:current-build state)]
+    (if-not (= (pusher/build-channel build) channel-name)
+      (do
+        (mlog "Ignoring event for old build channel: " channel-name)
+        state)
+      (let [{step-index :step action-index :index output :out} (js->clj data :keywordize-keys true)]
+        (-> state
+            (update-in [:current-build] build-model/fill-steps step-index)
+            (update-in [:current-build :steps step-index] (fnil identity {:actions []}))
+            (update-in [:current-build] build-model/fill-actions step-index action-index {})
+            (update-in [:current-build :steps step-index :actions action-index] (fnil identity {:output []}))
+            (update-in [:current-build :steps step-index :actions action-index :output] conj output))))))


Wrap request-token in let form

Wrap request-token in let form


Correct popup: the HTML hard limit is 10000

--- src/qu/views.clj
+++ src/qu/views.clj
@@ -204,7 +204,7 @@
      {:key "where"    :label "Where"            :bootstrap_span 12     :tooltip_title "Where Clause"     :tooltip_body "Filters the result set via a subset of SQL syntax. Supports standard comparison and boolean operators. See the API documentation for more details." }
      {:key "group"    :label "Group By"         :bootstrap_span 6      :tooltip_title "Group By Clause"  :tooltip_body "As in SQL, projects rows with common values into a smaller set. Supports the aggregation functions SUM, MIN, MAX, and COUNT. Requires a select clause."}
      {:key "orderBy"  :label "Order By"         :bootstrap_span 6      :tooltip_title "Order By Clause"  :tooltip_body "A comma-delimited list of fields used to sort the result set. As with SQL, use DESC for descending order. If blank, the order will be consistent but unspecified."}
-     {:key "limit"    :label "Limit"            :bootstrap_span 1      :tooltip_title "Limit Clause"     :tooltip_body "The maximum number of results to return. Defaults to 100. For HTML output format, the hard limit is 1000."}
+     {:key "limit"    :label "Limit"            :bootstrap_span 1      :tooltip_title "Limit Clause"     :tooltip_body "The maximum number of results to return. Defaults to 100. For HTML output format, the hard limit is 10,000 results."}
      {:key "offset"   :label "Offset"           :bootstrap_span 1      :tooltip_title "Offset Clause"    :tooltip_body "Zero-based offset to start the result set from. Defaults to 0."}
      ])


Use managed-button component in env var modal

--- src-cljs/frontend/components/project_settings.cljs
+++ src-cljs/frontend/components/project_settings.cljs
@@ -495,15 +495,14 @@
                                                                                :auto-complete "off"
                                                                                :on-change #(utils/edit-input owner (conj state/inputs-path :new-env-var-value) %)}))])
                                        :actions [(button/button {:on-click close-fn} "Cancel")
-                                                 (forms/managed-button
-                                                  [:input.btn.btn-primary {:data-failed-text "Failed" ,
-                                                                           :data-success-text "Added" ,
-                                                                           :data-loading-text "Adding..." ,
-                                                                           :value "Add Variable" ,
-                                                                           :type "submit"
-                                                                           :on-click #(raise! owner [:created-env-var
-                                                                                {:project-id project-id
-                                                                                :on-success close-fn}])}])]
+                                                 (button/managed-button {:data-failed-text "Failed" ,
+                                                                         :data-success-text "Added" ,
+                                                                         :data-loading-text "Adding..." ,
+                                                                         :primary? true
+                                                                         :on-click #(raise! owner [:created-env-var
+                                                                                {:project-id project-id
+                                                                                :on-success close-fn}])}
+                                                                        "Add Variable")]
                                        :close-fn close-fn})))
               (when-let [env-vars (seq (:envvars project-data))]
                 (om/build table/table


cleanup.

cleanup.

--- src/metabase/events/sync_database.clj
+++ src/metabase/events/sync_database.clj
@@ -21,14 +21,12 @@

 (defn process-sync-database-event
-  "Handle processing for a single event notification received on the revisions-channel"
+  "Handle processing for a single event notification received on the sync-database-channel"
   [sync-database-event]
   ;; try/catch here to prevent individual topic processing exceptions from bubbling up.  better to handle them here.
   (try
-    (log/info "holla")
     (when-let [{topic :topic object :item} sync-database-event]
       (when-let [database (db/sel :one Database :id (events/object->model-id topic object))]
-        (log/info "kicking off" database)
         ;; just kick off a sync on another thread
         (future (driver/sync-database! database))))
     (catch Throwable e