delete unused about button component

delete unused about button component

--- src-cljs/frontend/components/overlay.cljs
+++ src-cljs/frontend/components/overlay.cljs
@@ -16,17 +16,6 @@
             [om.dom :as dom :include-macros true])
   (:require-macros [frontend.utils :refer [html]])
   (:import [goog.ui IdGenerator]))
-
-(defn about-button [data owner]
-  (reify
-    om/IRender
-    (render [_]
-      (let [cast! (om/get-shared owner :cast!)
-            menu-button-learned? (get-in data state/menu-button-learned-path)] ; TODO figure out if this should be different because we used to call chat menu "the menu"
-        (html
-          [:a.about-cta {:on-click #(cast! :overlay-info-toggled)
-                         :role "button"}
-           "About"])))))

 (defn main-menu-button [data owner]
   (reify


always reload overlay

always reload overlay

--- src-cljs/frontend/components/overlay.cljs
+++ src-cljs/frontend/components/overlay.cljs
@@ -1,4 +1,4 @@
-(ns frontend.components.overlay
+(ns ^:figwheel-always frontend.components.overlay
   (:require [cemerick.url :as url]
             [clojure.set :as set]
             [clojure.string :as str]


add markup for access grant

add markup for access grant

--- src-cljs/frontend/components/overlay.cljs
+++ src-cljs/frontend/components/overlay.cljs
@@ -162,9 +162,14 @@

 (defmethod render-access-entity :access-grant
   [entity cast!]
-  [:div
-   [:img {:src (utils/gravatar-url (:access-grant/email entity))}]
-   (:access-grant/email entity)])
+  [:div.access-card
+   [:div.access-avatar
+    [:img {:src (utils/gravatar-url (:access-grant/email entity))}]]
+   [:div.access-details
+    [:div.access-detail {:title (:access-grant/email entity)}
+     [:div.access-name (:access-grant/email entity)]]
+    [:div.access-detail
+     [:div.access-status "Was granted access today."]]]])

 (defmethod render-access-entity :access-request
   [entity cast!]


Sablonification of page.

Sablonification of page.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -12,7 +12,8 @@
      [kixi.hecuba.common :refer (index-of map-replace find-first interval)]
      [kixi.hecuba.history :as history]
      [kixi.hecuba.model :refer (app-model)]
-     [kixi.hecuba.sensor :as sensor]))
+     [kixi.hecuba.sensor :as sensor]
+     [sablono.core :as html :refer-macros [html]]))

 (enable-console-print!)

@@ -198,26 +199,32 @@
         ;;
         (let [{:keys [programmes projects properties devices sensor-select]} tables]
           (dom/div nil
-                   (dom/h1 {:id "programmes"} (:title data))
-                   (om/build table programmes {:opts {:histkey :programme}})
-                   (dom/h2 {:id "projects"} (str  "Projects " (title-for programmes)))
-                   (om/build table projects {:opts {:histkey :project}})
-                   (dom/h2 {:id "properties"} (str "Properties" (title-for projects)))
-                   (om/build table properties {:opts {:histkey :property}})
-                   (dom/h2 {:id "devices"} "Devices" (title-for properties :title-key :addressStreetTwo))
-                   (om/build table devices {:opts {:histkey :device}})
-                   (om/build device-detail devices)
-                   (dom/h2 {:id "sensors"} "Sensors" (title-for devices :title-key [:location :name]))
-                   (om/build sensor/table data {:opts {:histkey :sensor
-                                                       :path    :readings}})
-                   (om/build sensor/define-data-set-button data)
-                   (dom/h2 nil "Chart")
-                   (dom/div #js {:id "date-picker"}
-                            (om/build dtpicker/date-picker data {:opts {:histkey :range}}))
-                   (om/build chart-feedback-box (get-in data [:chart :message]))
-                   (dom/div #js {:className "well" :id "chart" :style {:width "100%" :height 600}}
-                            (om/build chart/chart-figure (:chart data)))
-                   (om/build sensor/selection-dialog (:tables data)
+                   (html [:h1 {:id "programmes"} (:title data)]
+                         (om/build table programmes {:opts {:histkey :programme}})
+
+                         [:h2 {:id "projects"} (str  "Projects " (title-for programmes))]
+                         (om/build table projects {:opts {:histkey :project}})
+
+                         [:h2  {:id "properties"} (str "Properties" (title-for projects))]
+                         (om/build table properties {:opts {:histkey :property}})
+
+                         [:h2 {:id "devices"} "Devices" (title-for properties :title-key :addressStreetTwo)]
+                         (om/build table devices {:opts {:histkey :device}})
+
+                         (om/build device-detail devices)
+
+                         [:h2 {:id "sensors"} "Sensors" (title-for devices :title-key [:location :name])]
+                         (om/build sensor/table data {:opts {:histkey :sensor
+                                                             :path    :readings}})
+                         (om/build sensor/define-data-set-button data)
+
+                         [:h2 "Chart"]
+                         [:div {:id "date-picker"}
+                          (om/build dtpicker/date-picker data {:opts {:histkey :range}})]
+                         (om/build chart-feedback-box (get-in data [:chart :message]))
+                         [:div {:className "well" :id "chart" :style {:width "100%" :height 600}}
+                          (om/build chart/chart-figure (:chart data))]
+                         (om/build sensor/selection-dialog (:tables data)
                              {:opts {:id "sensor-selection-dialog"
                                      :handler (fn [e]
                                                 (.preventDefault e)
@@ -226,6 +233,6 @@
                                                        :handler         #(println "Yah!")
                                                        :error-handler   #(println "Error!")
                                                        :response-format "application/edn"
-                                                       :keywords?       true}))}})))))))
-
-
+                                                       :keywords?       true}))}}))))))))
+
+


WIP Flattened sensors.

WIP Flattened sensors.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -121,7 +121,7 @@
   (om/update! data [:projects :fetching] :fetching)
   (GET (str "/4/programmes/" programme-id "/projects/")
        {:handler  (fn [x]
-                    (println "Fetching data for programme: " programme-id)
+                    (println "Fetching projects for programme: " programme-id)
                     (om/update! data [:projects :data] (mapv slugify-project x))
                     (om/update! data [:projects :fetching] (if (empty? x) :no-data :has-data))
                     (om/update! data [:projects :selected] nil))
@@ -149,13 +149,17 @@
         :response-format :text}))

 (defn flatten-device [device]
+  (println "Flattening: " device)
   (let [device-keys (->> device keys (remove #(= % :readings)))
             parent-device (select-keys device device-keys)
             readings (:readings device)]
         (map #(assoc % :parent-device parent-device) readings)))

 (defn extract-sensors [devices]
-  (mapcat flatten-device devices))
+  (println "Devices to extract sensors from: " devices)
+  (let [sensors (vec (mapcat flatten-device devices))]
+    (println "Flattened sensors: " sensors)
+    sensors))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; History loop - this drives the fetches and clear downs
@@ -219,9 +223,11 @@
                                     :properties
                                     :data
                                     (filter #(= (:id %) properties))
-                                    first)]
+                                    first)
+              devices (get property-details :devices [])]
+          (println "property-details keys: " (keys property-details))
           (om/update! data [:property-details :data] property-details)
-          (om/update! data [:sensors :data] (extract-sensors (get property-details :devices [])))))
+          (om/update! data [:sensors :data] (extract-sensors devices))))

       ;; Update the new active components
       (om/update! data :active-components (-> nav-event :args :ids)))
@@ -486,6 +492,88 @@
                   {:onClick (back-to-projects history)}
                   (title-for projects)]]]
            (om/build properties-table properties {:opts {:histkey :properties}})]])))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; sensors
+(defn status-label [status]
+  (if (= status "OK")
+    [:span {:class "label label-success"} status]
+    [:span {:class "label label-danger"} status]))
+
+(defn sensors-table [data owner {:keys [histkey path]}]
+  (reify
+    om/IRender
+    (render [_]
+      (let [sensors (:sensors data)
+            chart   (:chart data)
+            history (om/get-shared owner :history)
+            table-id "sensors-table"]
+
+        (html
+         [:table {:className "table table-hover"}
+          [:thead
+           [:tr [:th "Type"] [:th "Unit"] [:th "Period"] [:th "Device"] [:th "Status"]]]
+          [:tbody
+           (for [row (sort-by :type (-> sensors :data))]
+             (let [{:keys [device_id type unit period status]} row
+                   id (str type "-" device_id)]
+               [:tr {:onClick (fn [_ _]
+                                (om/update! sensors :selected id)
+                                (om/update! chart :sensor id)
+                                (om/update! chart :unit unit)
+                                (history/update-token-ids! history :sensors id))
+                     :className (if (= id (:selected sensors)) "success")
+                     :id (str table-id "-selected")}
+                [:td type]
+                [:td unit]
+                [:td period]
+                [:td device_id]
+                [:td (status-label status)]]))]])))))
+
+(defn chart-summary
+  "Show min, max, delta and average of chart data."
+  [chart owner]
+  (reify
+    om/IRender
+    (render [_]
+      (let [{:keys [unit measurements]} chart
+            ;; FIXME why are measurements nested? (in prep for multi-series?)
+            series-1 (:measurements measurements)
+            vals-1 (map :value series-1)
+            series-1-min (apply min vals-1)
+            series-1-max (apply max vals-1)
+            series-1-sum (reduce + vals-1)
+            series-1-count (count series-1)
+            series-1-mean (if (not= 0 series-1-count) (/ series-1-sum series-1-count) "NA")]
+        (html
+         (if (seq series-1)
+           [:div.col-md-12#summary-stats
+            [:div {:class "col-md-3"}
+             (bs/panel "Minimum" (str (.toFixed (js/Number. series-1-min) 3) " " unit))]
+            [:div {:class "col-md-3"}
+             (bs/panel "Maximum" (str (.toFixed (js/Number. series-1-max) 3) " " unit))]
+            [:div {:class "col-md-3"}
+             (bs/panel "Average (mean)" (str (.toFixed (js/Number. series-1-mean) 3) " " unit))]
+            [:div {:class "col-md-3"}
+             (bs/panel "Range" (str (.toFixed (js/Number. (- series-1-max series-1-min)) 3) " " unit))]]
+           [:div.row#summary-stats [:div.col-md-12.text-center [:p.lead {:style {:padding-top 30}} "No data."]]]))))))
+
+(defn sensors-div [data owner]
+  (reify
+    om/IRender
+    (render [_]
+      (html
+       [:div.col-md-12
+        [:h3 {:id "sensors"} "Sensors"]
+        (om/build sensors-table data {:opts {:histkey :sensors
+                                             :path    :readings}})
+        [:div {:id "chart-div"}
+         [:div {:id "date-picker"}
+          (om/build dtpicker/date-picker data {:opts {:histkey :range}})]
+         (om/build chart-feedback-box (get-in data [:chart :message]))
+         (om/build chart-summary (:chart data))
+         [:div {:className "well" :id "chart" :style {:width "100%" :height 600}}
+          (om/build chart/chart-figure (:chart data))]]]))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; property-details
@@ -548,252 +636,12 @@
                   [:p (:design_strategy property_data)]

                   [:h3 "Energy Strategy"]
-                  [:p (:energy_strategy property_data)]]
-
-                 ]
-                )]
-
-              )))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; devices
-(defn slugify-device
-  "Create a user friendly slug for a device"
-  [device]
-  (assoc device :slug (apply str (interpose ", " (->> (vector (:name device) (:description device))
-                                                      (keep identity)
-                                                      (remove empty?))))))
-
-(defmulti devices-table-html (fn [devices owner] (:fetching devices)))
-(defmethod devices-table-html :fetching [devices owner]
-  (fetching-row devices))
-
-(defmethod devices-table-html :no-data [devices owner]
-  (no-data-row devices))
-
-(defmethod devices-table-html :error [devices owner]
-  (error-row devices))
-
-(defmethod devices-table-html :has-data [devices owner]
-  (let [table-id   "devices-table"
-        history    (om/get-shared owner :history)]
-    [:div.row
-     [:div.col-md-12
-      [:table {:className "table table-hover"}
-       [:thead
-        [:tr [:th "Name"] [:th "Description"] [:th "Privacy"]]]
-       [:tbody
-        (for [row (sort-by :name (:data devices))]
-          (let [{:keys [id location description privacy]} row
-                name (:name location)]
-            [:tr {:onClick (fn [_ _]
-                             (om/update! devices :selected id)
-                             (history/update-token-ids! history :devices id)
-                             (fixed-scroll-to-element "sensors-div"))
-                  :className (if (= id (:selected devices)) "success")
-                  :id (str table-id "-selected")}
-             [:td name]
-             [:td description]
-             [:td privacy]]))]]]]))
-
-(defmethod devices-table-html :default [devices owner]
-  [:div.row [:div.col-md-12]])
-
-(defn devices-table [devices owner]
-  (reify
-    om/IRender
-    (render [_]
-      (html (devices-table-html devices owner)))))
-
-(defn devices-div [data owner]
-  (reify
-    om/IDidUpdate
-    (did-update [_ prev-props prev-state]
-      (let [{:keys [properties devices active-components]} data
-            new-property-id (:properties active-components)]
-
-        ;; handle selection properties table
-        (when-not new-property-id
-          (om/update! devices :data [])
-          (om/update! devices :selected nil))
-
-        (if (and new-property-id
-                 (not (= (:property_id devices) new-property-id)))
-          (do
-            (om/update! devices :fetching :fetching)
-            (GET (str "/4/entities/" new-property-id "/devices/")
-                 {:handler  (fn [x]
-                              ;; (println "Fetching devices for property: " new-property-id)
-                              (om/update! devices :fetching false)
-                              (om/update! devices :data (mapv slugify-device x))
-                              (om/update! devices :fetching (if (empty? x) :no-data :has-data))
-                              (om/update! devices :selected nil))
-                  :error-handler (fn [{:keys [status status-text]}]
-                                   (om/update! devices :fetching :error)
-                                   (om/update! devices :error-status status)
-                                   (om/update! devices :error-text status-text))
-                  :headers {"Accept" "application/edn"}
-                  :response-format :text})))
-        (om/update! devices :property_id new-property-id)
-
-        ;; handle selection in devices table
-        (om/update! devices :selected (:devices active-components))))
-    om/IRender
-    (render [_]
-      (let [{:keys [programmes projects properties devices active-components]} data
-            history (om/get-shared owner :history)]
-        (html
-         [:div.row#devices-div
-          [:div {:class (str "col-md-12 " (if (:property_id devices) "" "hidden"))}
-           [:h2  "Devices"]
-           [:ul {:class "breadcrumb"}
-            [:li [:a
-                  {:href "/app"}
-                  (title-for programmes)]]
-            [:li [:a
-                  {:onClick (back-to-projects history)}
-                  (title-for projects)]]
-            [:li [:a
-                  {:onClick (back-to-properties history)}
-                  (title-for properties)]]]
-           (om/build devices-table devices {:opts {:histkey :devices}})]])))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; sensors
-(defn status-label [status]
-  (if (= status "OK")
-    [:span {:class "label label-success"} status]
-    [:span {:class "label label-danger"} status]))
-
-(defn sensors-table [data owner {:keys [histkey path]}]
-  (reify
-    om/IRender
-    (render [_]
-      ;; Select the first row
-      ;;(put! out {:type :row-selected :row (first (om/get-state owner :data))})
-      (let [sensors (:sensors data)
-            chart   (:chart data)
-            cols    (get-in sensors [:header :cols])
-            history (om/get-shared owner :history)
-            table-id "sensors-table"]
-
-        (html
-         [:table {:className "table table-hover"}
-          [:thead
-           [:tr [:th "Type"] [:th "Unit"] [:th "Period"] [:th "Device"] [:th "Status"]]]
-          [:tbody
-           (for [row (sort-by :type (-> sensors :data :readings))]
-             (let [{:keys [device_id type unit period status]} row
-                   id (str type "-" device_id)]
-               [:tr {:onClick (fn [_ _]
-                                (om/update! sensors :selected id)
-                                (om/update! chart :sensor id)
-                                (om/update! chart :unit unit)
-                                (history/update-token-ids! history :sensors id))
-                     :className (if (= id (:selected sensors)) "success")
-                     :id (str table-id "-selected")}
-                [:td type]
-                [:td unit]
-                [:td period]
-                [:td device_id]
-                [:td (status-label status)]]))]])))))
-
-(defn chart-summary
-  "Show min, max, delta and average of chart data."
-  [chart owner]
-  (reify
-    om/IRender
-    (render [_]
-      (let [{:keys [unit measurements]} chart
-            ;; FIXME why are measurements nested? (in prep for multi-series?)
-            series-1 (:measurements measurements)
-            vals-1 (map :value series-1)
-            series-1-min (apply min vals-1)
-            series-1-max (apply max vals-1)
-            series-1-sum (reduce + vals-1)
-            series-1-count (count series-1)
-            series-1-mean (if (not= 0 series-1-count) (/ series-1-sum series-1-count) "NA")]
-        (html
-         (if (seq series-1)
-           [:div.row#summary-stats
-            [:div {:class "col-md-3"}
-             (bs/panel "Minimum" (str (.toFixed (js/Number. series-1-min) 3) " " unit))]
-            [:div {:class "col-md-3"}
-             (bs/panel "Maximum" (str (.toFixed (js/Number. series-1-max) 3) " " unit))]
-            [:div {:class "col-md-3"}
-             (bs/panel "Average (mean)" (str (.toFixed (js/Number. series-1-mean) 3) " " unit))]
-            [:div {:class "col-md-3"}
-             (bs/panel "Range" (str (.toFixed (js/Number. (- series-1-max series-1-min)) 3) " " unit))]]
-           [:div.row#summary-stats [:div.col-md-12.text-center [:p.lead {:style {:padding-top 30}} "No data."]]]))))))
-
-(defn sensors-div [data owner]
-  (reify
-    om/IDidUpdate
-    (did-update [_ prev-props prev-state]
-      (let [{:keys [sensors active-components]} data
-            new-device_id                       (:devices active-components)
-            property_id                         (:properties active-components)]
-
-        ;; handle selection properties table
-        (when-not new-device_id
-          (om/update! sensors :data [])
-          (om/update! sensors :selected nil))
-
-        (if (and new-device_id
-                 (not= (:device_id sensors) new-device_id))
-          (do
-            (om/update! sensors :fetching true)
-            ;; "/4/entities/:properties/devices/:devices"
-            (GET (str "/4/entities/" property_id "/devices/" new-device_id)
-                 {:handler  (fn [x]
-                              ;; (println "Fetching sensors for device: " new-device_id)
-                              (om/update! sensors :fetching false)
-                              (om/update! sensors :data x)
-                              (om/update! sensors :selected nil))
-                  :error-handler (fn [{:keys [status status-text]}]
-                                   (om/update! sensors :fetching false)
-                                   (om/update! sensors :error-status status)
-                                   (om/update! sensors :error-text status-text))
-                  :headers {"Accept" "application/edn"}})))
-        (om/update! sensors :device_id new-device_id)
-
-        ;; handle selection in sensors table
-        (om/update! sensors :selected (:sensors active-components))))
-    om/IRender
-    (render [_]
-      (let [{:keys [programmes projects properties devices sensors active-components]} data
-            history (om/get-shared owner :history)]
-        (html
-         [:div.row#sensors-div
-          [:div {:class (str "col-md-12 "  (if (:device_id sensors) "" "hidden"))}
-           [:h2 {:id "sensors"} "Sensors"]
-           [:ul {:class "breadcrumb"}
-            [:li [:a
-                  {:href "/app"}
-                  (title-for programmes)]]
-            [:li [:a
-                  {:onClick (back-to-projects history)}
-                  (title-for projects)]]
-            [:li [:a
-                  {:onClick (back-to-properties history)}
-                  (title-for properties)]]
-            [:li [:a
-                  {:onClick (back-to-devices history)}
-                  (title-for devices)]]]
-           (om/build sensors-table data {:opts {:histkey :sensors
-                                                :path    :readings}})
-           (if (or (not agent/IE)
-                   (agent/isVersionOrHigher 9))
-             [:div {:id "chart-div"}
-              [:div {:id "date-picker"}
-               (om/build dtpicker/date-picker data {:opts {:histkey :range}})]
-              (om/build chart-feedback-box (get-in data [:chart :message]))
-              (om/build chart-summary (:chart data))
-              [:div {:className "well" :id "chart" :style {:width "100%" :height 600}}
-               (om/build chart/chart-figure (:chart data))]]
-             [:div.col-md-12.text-center
-              [:p.lead {:style {:padding-top 30}}
-               "Charting in Internet Explorer version " agent/VERSION " coming soon."]])]])))))
+                  [:p (:energy_strategy property_data)]]]
+                [:div.col-md-12
+                 (om/build sensors-div data)]
+                )
+               ])
+        ))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Main View
@@ -823,8 +671,5 @@
              (om/build properties-div data)
              (om/build property-details-div data)
              ;; (om/build devices-div data)
-             ;; (om/build device-detail devices)
-             ;; (om/build sensors-div data)
-             ;; (om/build sensor/define-data-set-button data)
-
+             ;;
              ]))))


Add build number to circleci deploys, to make the directory name happy

--- src/circleci/backend/project/circleci.clj
+++ src/circleci/backend/project/circleci.clj
@@ -15,7 +15,8 @@
                          :group circle/circleci-group))

 (def circle-deploy (build :project-name "CircleCI"
-                          :type :deploy ;;?
+                          :build-num 1
+                          :type :deploy
                           :group circle/circleci-group
                           :actions [(checkout "git@github.com:arohner/CircleCI.git")
                                     (bash [(lein deps)


Upgrade karma to 4.4.1

Upgrade karma to 4.4.1

--- src/deps.cljs
+++ src/deps.cljs
@@ -1,5 +1,5 @@
 {:npm-dev-deps {"shadow-cljs"           "2.8.67"
-                "karma"                 "4.3.0"
+                "karma"                 "4.4.1"
                 "karma-chrome-launcher" "3.1.0"
                 "karma-cljs-test"       "0.1.0"
                 "karma-junit-reporter"  "2.0.1"}}


New tests: test-encode-spaces and test-encode-spaces-NPE

--- test/clj_jenkins_api/jenkins_api_test.clj
+++ test/clj_jenkins_api/jenkins_api_test.clj
@@ -49,4 +49,24 @@
     (testing "if the clj-jenkins-api.jenkins-api/update-jenkins-url definition exists."
         (is (callable? 'clj-jenkins-api.jenkins-api/update-jenkins-url))))

+;
+; Function behaviours
+;

+(deftest test-encode-spaces
+    "Check that the clj-jenkins-api.jenkins-api/encode-spaces definition exists."
+    (testing "if the clj-jenkins-api.jenkins-api/encode-spaces definition exists."
+        (are [x y] (= x y)
+            ""            (encode-spaces "")
+            "%20"         (encode-spaces " ")
+            "x%20"        (encode-spaces "x ")
+            "%20y"        (encode-spaces " y")
+            "x%20y"       (encode-spaces "x y")
+            "x%20y%20z"   (encode-spaces "x y z")
+            "x%20%20%20z" (encode-spaces "x   z"))))
+
+(deftest test-encode-spaces-NPE
+    "Check that the clj-jenkins-api.jenkins-api/encode-spaces definition exists."
+    (testing "if the clj-jenkins-api.jenkins-api/encode-spaces definition exists."
+        (is (thrown? NullPointerException (encode-spaces nil)))))
+


Take parameters to (circle.ruby/rspec). (rspec "requests" "controllers") is the same as "$ rspec spec/requests spec/controllers"

--- src/circle/ruby.clj
+++ src/circle/ruby.clj
@@ -2,6 +2,7 @@
   (:refer-clojure :exclude [eval])
   (:import org.jruby.RubySymbol)
   (:import java.lang.ref.WeakReference)
+  (:require fs)
   (:use midje.sweet))

 ;; This is the runtime all ruby requests will go through. It's
@@ -103,10 +104,13 @@
 Note that rspec will run in whatever RAILS_ENV you started in, so you
   probably want to start in RAILS_ENV=test, or rspec will clear your
   DB, or tests will fail because they assume the DB cleaner runs."
-  []
-  (eval "
+  [& subdirs]
+  (let [subdirs (if (empty? subdirs) [""] subdirs)
+        subdirs (map #(fs/join "spec" %) subdirs)
+        command (format "
 require 'rubygems'
 require 'rspec/core/rake_task'

-RSpec::Core::Runner.run(['spec'])
-"))+RSpec::Core::Runner.run(%s)
+" (vec subdirs))]
+    (eval command)))


Show links received

Show links received

--- src/cljs/hello.cljs
+++ src/cljs/hello.cljs
@@ -8,7 +8,7 @@

 (def tweets-channel (chan))

-(def app-state (atom {:tweets [] :tweets-count 50}))
+(def app-state (atom {:tweets [] :tweets-count 50 :tweets-received 0}))

 (defn log [text]
   (.log js/console text))
@@ -33,11 +33,14 @@
     (will-mount [this]
       (go (while true
             (let [tweet (<! tweets-channel)]
+              (om/transact! app :tweets-received inc)
               (om/transact! app :tweets #(take tweets-count (conj % tweet)))))))
     om/IRender
     (render [this]
-      (apply dom/div #js {:className "tweets"}
-             (om/build-all tweet (:tweets app))))))
+      (dom/div #js {:id "tweets"}
+               (dom/div nil (str "Received " (:tweets-received app) " links so far"))
+               (apply dom/div #js {:className "tweets"}
+                      (om/build-all tweet (:tweets app)))))))

 (om/root tweets app-state
          {:target (. js/document (getElementById "app"))})


fix the layout

fix the layout

--- src-cljs/bitfondue/core.cljs
+++ src-cljs/bitfondue/core.cljs
@@ -27,8 +27,8 @@

 (defn layout
   []
-  [header]
   [:div
+   [header]
    [chunks]])

 ;; ---


Update default state

Update default state

--- src-cljs/frontend/state.cljs
+++ src-cljs/frontend/state.cljs
@@ -1,9 +1,10 @@
 (ns frontend.state)

 (defn initial-state []
-  {:camera {:x  0
-            :y  0
-            :zf 1}
+  {:camera {:x          0
+            :y          0
+            :zf         1
+            :show-grid? true}
    :error-message nil
    :changelog nil
    :environment "development"


Deleted this old file as it is from another more complex version of the code and required for higher-level integration with this library.

--- src/main/clojure/plugboard/controller.clj
+++ src/main/clojure/plugboard/controller.clj
@@ -1,122 +0,0 @@
-;; Copyright 2010 Malcolm Sparks.
-;;
-;; This file is part of Plugboard.
-;;
-;; Plugboard is free software: you can redistribute it and/or modify it under the
-;; terms of the GNU Affero General Public License as published by the Free
-;; Software Foundation, either version 3 of the License, or (at your option) any
-;; later version.
-;;
-;; Plugboard is distributed in the hope that it will be useful but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-;; A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
-;; details.
-;;
-;; Please see the LICENSE file for a copy of the GNU Affero General Public License.
-
-(ns plugboard.controller
-  #^{:author "Malcolm Sparks"
-     :doc "Handle the incoming request and delegate to more specialised
-controllers as appropriate."  }
-  (:use
-   clout.core
-   compojure.response
-   plugboard.util
-   plugboard.status
-   plugboard.response
-   )
-  (:require
-   ring.middleware.reload
-   ring.middleware.stacktrace
-   ring.middleware.params
-   ))
-
-(defn- get-location-header [state]
-  (let [location (get state :location)]
-    (if location {"Location" location} {})
-    ))
-
-(defn- guess-content-type [uri]
-  (case uri
-        "html" "text/html; charset=iso-8859-1"
-        "xhtml" "application/xhtml+xml; charset=iso-8859-1"
-        "css" "text/css; charset=iso-8859-1"
-        "png" "image/png"
-        "js" "text/javascript; charset=iso-8859-1"
-        ))
-
-(defn- get-response-headers [state]
-  (merge (get-location-header state)
-         {"Content-Type" (guess-content-type
-                          (get-suffix (get-in state [:request :uri])))
-          "X-Lang" "Clojure"
-          })
-)
-
-(defstruct controller-def
-  :status-overrides ; A function which returns a mapping between decision point codes and decision functions.
-  :view-overrides ; A function which returns a mapping between status codes and view functions.
-  )
-
-(defn- create-response [request controller-def]
-  (let [[status state] (get-status ((:status-overrides controller-def))
-                                   {:request request})
-        view (create-view status state ((:view-overrides controller-def)))
-        ]
-    {:status status ; TODO: Allow the view to override the status?
-      :headers (merge (get-response-headers state) (:headers view))
-      :body (:body view)}
-     ))
-
-(defn create-controller
-  [controller-def]
-  (fn
-    [request]
-    (render request (create-response request controller-def))
-    ))
-
-(defn create-handler [& mappings]
-  "Create a handler that will try each mapping in turn until it finds a match."
-  (fn [request]
-    (some
-     (fn [mapping]
-       (if-let [route-params (route-matches (first mapping) request)]
-         ((second mapping) ; call the sub-handler
-          ;; with a request that includes route parameters.
-          (merge-with merge request {:route-params route-params})
-          )))
-     mappings)))
-
-(defn not-found-handler [request]
-  "A temporary catch-all handler, to be replaced by something more sophisticated."
-  {:status 404 :headers {} :body "Not found"}
-  )
-
-(defn create-root-handler [handlers]
-  #^{:doc
-     "These are the predetermined routes, mapped to handlers which further
-        process the request and provide the response."}
-  (apply create-handler
-         (concat handlers
-                 [["*" not-found-handler]])))
-
-(defn create-app [handlers]
-  #^{:doc
-     "Define the structure of the root application. This matches the URL
-     against predetermined routes to identify which handler to delegate
-     responsibility to. It creates the main handler and then wraps it in a
-     number of other handlers. The reason we refer to (var resources) is because
-     the '->' macro is expanded before evaluation and if we in-lined the
-     resources the form would get called multiple times."}
-  (let [h (create-root-handler handlers)]
-    (-> h
-        (ring.middleware.reload/wrap-reload
-         '( ; Reload if any of these modules change.
-           plugboard.controller
-           plugboard.response
-           plugboard.status
-           plugboard.util
-           ))
-        (ring.middleware.params/wrap-params) ; Parse query-string parameters.
-        (ring.middleware.stacktrace/wrap-stacktrace) ; Emit a stack-trace if something goes wrong.
-        )))


Add functionality to Logout button

Add functionality to Logout button

Fix #29, does not redirect main page to the sign-in

--- src-cljs/rmfu_ui/nav.cljs
+++ src-cljs/rmfu_ui/nav.cljs
@@ -1,5 +1,10 @@
 (ns rmfu-ui.nav
   (:require [secretary.core :as secretary :include-macros true]))
+
+(defn logout []
+  "Logs the user out by deleting key form local storage"
+  (.removeItem (.-localStorage js/window) "rmfu-feed-identity-token")
+)

 (defn nav
   "Renders basic nav with an .active link"
@@ -13,4 +18,4 @@
       ^{:key anchor} [:li {:className class-names}
                       [:a.nav-link {:href (str "/#/" anchor)} title]])]
    [:form.form-inline.navbar-form.pull-right
-    [:button.btn.btn-success-outline {:type "button"} "logout"]]])+    [:button.btn.btn-success-outline {:type "button" :on-click #(logout)} "logout"]]])


improve struct conversion performance

improve struct conversion performance

--- src/domkm/whois.clj
+++ src/domkm/whois.clj
@@ -1,19 +1,21 @@
 (ns domkm.whois
-  (:require [clojure.java.io :as io]
-            [zweikopf.multi :as rb :refer [call-ruby clojurize Clojurize ruby-eval]])
+  (:require  [zweikopf.multi :as rb :refer [call-ruby clojurize Clojurize ruby-eval]])
   (:import [org.jruby.embed ScriptingContainer LocalContextScope]
-           [org.jruby RubyStruct]))
+           [org.jruby.RubyStruct]
+           [org.jruby.runtime.Block]))

 (extend-protocol Clojurize
-  RubyStruct
+  org.jruby.RubyStruct
   (clojurize [this ruby]
-    (persistent!
-      (reduce (fn [acc key]
-                (assoc! acc
-                        (keyword (clojurize key ruby))
-                        (clojurize (call-ruby ruby this "[]" key) ruby)))
-              (transient {})
-              (.members this)))))
+    (let [context (-> ruby .getProvider .getRuntime .getCurrentContext)
+          null-block org.jruby.runtime.Block/NULL_BLOCK]
+      (persistent!
+        (reduce (fn [acc [key val]]
+                  (assoc! acc
+                          (keyword (clojurize key ruby))
+                          (clojurize val ruby)))
+                (transient {})
+                (call-ruby ruby (.each_pair this context null-block) :to_a))))))

 (def ^:private ruby (ScriptingContainer. LocalContextScope/THREADSAFE))


[JM][000000] Updated docstring

[JM][000000] Updated docstring

--- src/dotenv/core.clj
+++ src/dotenv/core.clj
@@ -1,9 +1,9 @@
-(ns ^{:author "Jack Morrill for RentPath.com"
-      :doc "Load environment variable definitions from .env into the JVM System Properties."}
+(ns ^{:author "Jack Morrill, RentPath.com"
+      :doc "Load environment variable definitions from .env<.environment> file into the JVM System Properties."}
       dotenv.core
-      (:require [clojure.java.io :as io]
-                [clojure.string :as string]
-                [environs.core  :as environs]))
+      (:require [clojure.java.io :as io      ]
+                [clojure.string  :as string  ]
+                [environs.core   :as environs]))

 (defn exists?
   "Returns true if file exists and is a regular file, else returns false."
@@ -25,12 +25,12 @@
     foo=1
     bar='hairy URL'

-    YAML-like format:
+  YAML-like format:

     foo: 1
     bar: 'hairy URL'

-    For convienence, a Bourne Shell format is accepted:
+  For convienence, a Bourne Shell format is accepted:

     export foo=1
     export bar='hairy URL'


metadata: quick fix to also show metadata of symbols representing namespaces.

--- ccw.core/src/clj/ccw/editors/clojure/editor_common.clj
+++ ccw.core/src/clj/ccw/editors/clojure/editor_common.clj
@@ -70,16 +70,20 @@

 (defn find-var-metadata
   "Given editor, and an already resolved current-namespace, makes a call to
-   the editor REPL to find metadata associated to var. If there's currently
-   no REPL, just return nil."
+   the editor REPL to find metadata associated to symbol. If there's currently
+   no REPL, just return nil.
+   CURRENTLY works for namespace vars, and namespaces."
   [current-namespace ^IClojureEditor editor var]
   (when-let [repl (.getCorrespondingREPL editor)]
     (let [connection (.getToolingConnection repl)
           command (format (str "(ccw.debug.serverrepl/var-info "
-                               "(clojure.core/ns-resolve "
-                               "(clojure.core/the-ns '%s) '%s))")
+                               "  (or (try (clojure.core/ns-resolve "
+                               "             (clojure.core/the-ns '%s) '%s)"
+                               "        (catch Exception e nil))"
+                               "      (try (clojure.core/the-ns '%s)"
+                               "        (catch Exception e nil))))")
                           current-namespace
-                          var)
+                          var var)
           response (send-message connection command)]
       (first response))))


[#533] Test for delete invite API endpoint

--- backend/test/akvo/lumen/component/user_manager_test.clj
+++ backend/test/akvo/lumen/component/user_manager_test.clj
@@ -87,6 +87,17 @@
       (is (= "ruth@t2.lumen.localhost"
              (-> resp :body first :email)))))

+  (testing "Delete non consumed invite"
+    (let [invite-id (-> (user-manager/invites *user-manager* *tenant-conn*)
+                        :body first :id)
+          resp (user-manager/delete-invite *user-manager* *tenant-conn* invite-id)]
+      (is (= 204 (:status resp)))
+      (is (map? (:body resp)))
+      (is (empty? (:body resp)))
+      (is (= 0 (-> (user-manager/invites *user-manager* *tenant-conn*)
+                   :body count)))))
+
+
   ;; Work in progress - we need to clean Keycloak for these to work properly
   #_(testing "Accepting invite"
     (let [original-users (user-manager/users *user-manager* "t1")


Experimenting without drumbeat

Experimenting without drumbeat

--- src/aeolian/midi/core.clj
+++ src/aeolian/midi/core.clj
@@ -8,7 +8,7 @@
 (def four-beat-metro (str "%%MIDI drum dzdzdzdz " (apply str (repeat 4 (str beat " "))) "\n"))
 (def no-accents "%%MIDI nobeataccents\n")
 (def first-beat-emphasis "%%MIDI beatstring pppp\n")
-(def header (str first-beat-emphasis four-beat-metro no-accents "%%MIDI drumon\n%%MIDI gchord c\n"))
+(def header (str first-beat-emphasis four-beat-metro no-accents "%%MIDI drumoff\n%%MIDI gchord c\n"))

 (def flute 73)
 (def voice 53)


Implement button to check API status, see #49

--- frontend/src/cruncher/utils/status.cljs
+++ frontend/src/cruncher/utils/status.cljs
@@ -5,31 +5,29 @@
             [cruncher.communication.main :as com]
             [cruncher.config :as config]
             [cruncher.utils.extensions]
+            [cruncher.utils.views :as vlib]
             [cruncher.utils.lib :as lib])
   (:require-macros [cljs.core.async.macros :refer [go]]))

-(defn success-handler [this]
-  (om/transact! this `[(status/niantic {:status true})]))
+(defn success-handler []
+  (om/transact! lib/reconciler `[(status/niantic {:status true})]))

-(defn query
-  "Query API to find if I am still connected."
-  [this]
-  (com/ajax-get (:api-status config/api) #(success-handler this) com/error-handler false)
-  (go (loop [_ 1]
-        (<! (lib/timeout 120000))
-        (com/ajax-get (:api-status config/api) #(success-handler this) com/error-handler false)
-        (recur 1)))
-  (dom/div nil))
+(defn error-handler []
+  (om/transact! lib/reconciler `[(status/niantic {:status false})]))

-(defui APIConnectedBadge
+(defui APITest
   static om/IQuery
   (query [_]
-    [:connected?])
+    [:api :connected?])
   Object
   (render [this]
     (let [{:keys [connected?]} (om/props this)]
       (dom/div nil
-               #_(query this)
-               (when-not connected?
-                 (dom/img #js {:src "img/status/api_not_connected.svg"}))))))
-(def api-connected-badge (om/factory APIConnectedBadge {}))+               (vlib/button (fn [] (com/ajax-get (:api-status config/api) success-handler error-handler false))
+                            true "Test API" "btn-default btn-xs")
+               (when (nil? connected?)
+                 (com/ajax-get (:api-status config/api) success-handler error-handler false))
+               (if connected?
+                 (dom/span #js {:className "label label-success"} "API connected")
+                 (dom/span #js {:className "label label-warning"} "API not connected"))))))
+(def api-test (om/factory APITest {}))


Changes to accommodate termseq processing; reimplement exp-samplesheet processing to be more general with map output

--- src/aerobio/htseq/common.clj
+++ src/aerobio/htseq/common.clj
@@ -57,6 +57,20 @@
        (coll/drop-until #(= (first %) "Sample_ID"))
        rest))

+(defn term-seq-adjust
+  [secmap]
+  (let [run-xref (->> secmap :run-xref (mapv #(coll/takev 3 %))
+                      (mapv (fn[[_ rt bc]]
+                              [bc [(keyword (cljstr/lower-case rt)) rt]]))
+                      (into {}))
+        bc-xref (->> secmap :bc-xref
+                     (mapv (fn[[n nm ibc sbc]]
+                             (let [rtnm (second (get run-xref ibc [:na ""]))
+                                   [strain cond lib] (str/split #"-" nm)]
+                               [n (cljstr/join "-" [strain (str rtnm cond) lib])
+                                ibc sbc]))))]
+    (assoc secmap :run-xref run-xref :bc-xref bc-xref)))
+
 (defn get-exp-sample-info [csv]
   (let [recs (->> csv slurp csv/read-csv)
         x (coll/dropv-until
@@ -74,8 +88,7 @@
               secmap (zipmap ks sections)
               secmap (if (not= exp :termseq)
                        secmap
-                       (assoc secmap :run-xref
-                              (mapv #(coll/takev 3 %) (secmap :run-xref))))]
+                       (term-seq-adjust secmap))]
           secmap)
         (let [s (coll/dropv-until (fn[v] (str/digits? (first v))) S)
               i (coll/takev-until (fn[v] (not (str/digits? (first v)))) s)
@@ -281,11 +294,7 @@
                 (get-exp-sample-info exp-ssheet))))
       ((fn[m]
          (assoc m :run-xref
-                (->> (m :exp-sample-info)
-                     :run-xref
-                     (mapv (fn[[_ rt bc]]
-                             [bc [(keyword (cljstr/lower-case rt)) rt]]))
-                     (into {})))))
+                (->> (m :exp-sample-info) :run-xref))))
       ((fn[m]
          (assoc m :exp (get-exp-type (m :exp-sample-info))
                 :sample-names
@@ -419,20 +428,14 @@
           (fs/mkdir dir))))))

 (defn get-exp-file-specs
-  [eid exp-illumina-xref exp-dir ibc ftype]
-  (let [exp (get-exp-info eid :exp)
-        run-xref (get-exp-info eid :run-xref)
-        rtnm (second (get run-xref ibc [:na ""]))]
-    (->>  ibc exp-illumina-xref
-          (map (fn[[id nm ibc sbc]]
-                 (let [[strain cond lib] (str/split #"-" nm)
-                       nm (cljstr/join "-" [strain (str rtnm cond) lib])]
-                   [sbc (str nm "-" sbc ftype)])))
-          (map (fn[[sbc spec]] [sbc (fs/join exp-dir spec)]))
-          (into {}))))
+  [exp-illumina-xref exp-dir ibc ftype]
+  (->>  ibc exp-illumina-xref
+        (map (fn[[id nm ibc sbc]] [sbc (str nm "-" sbc ftype)]))
+        (map (fn[[sbc spec]] [sbc (fs/join exp-dir spec)]))
+        (into {})))

 (defn get-bc-file-specs
-  [eid base exp-illumina-xref illumina-sample-xref
+  [base exp-illumina-xref illumina-sample-xref
    & {:keys [ftype]
       :or {ftype ".fastq.gz"}}]
   (let [base (get-sample-base-dir base)
@@ -441,8 +444,7 @@
                              (map #(fs/join base %)))]
     (into {}
           (map (fn[exp-dir ibc]
-                 [ibc (get-exp-file-specs
-                       eid exp-illumina-xref exp-dir ibc ftype)])
+                 [ibc (get-exp-file-specs exp-illumina-xref exp-dir ibc ftype)])
                exp-sample-dirs
                ibcs))))

@@ -530,7 +532,7 @@
         red1codes (get-exp-info eid :red1codes)
         [qc-ctpt _] (fil/qcscore-min-entropy baseqc% 0.9 10)
         bc-file-specs (get-bc-file-specs
-                       eid base exp-illumina-xref illumina-sample-xref)
+                       base exp-illumina-xref illumina-sample-xref)
         ifastqs (fs/directory-files (get-exp-info eid :fastq) "fastq.gz")
         sample-illumina-xref (clojure.set/map-invert illumina-sample-xref)
         sample-ifq-xref (reduce (fn[M fq]
@@ -690,7 +692,9 @@
     (cond
       (#{"phase-0" "phase-0b" "phase-0c"
          "phase-1" "bt2-phase-1" "bt1-phase-1"
-         "phase-2" "phase-2b"} action)
+         "phase-2" "phase-2b"
+         "phase-2-rnaseq" "phase-2-termseq"
+         "phase-2-5NTap" "phase-2-5PTap"} action)
       (let [phase action]
         (cond
           (#{"phase-0" "phase-0b" "phase-0c"} phase)
@@ -702,7 +706,11 @@
             (run-phase-1 eid recipient get-toolinfo template :repk rep))

           (#{"phase-2" "phase-2b"} phase)
-          (run-phase-2 exp eid recipient get-toolinfo template)))
+          (run-phase-2 exp eid recipient get-toolinfo template)
+
+          (#{"phase-2-rnaseq" "phase-2-term-seq"
+             "phase-2-5NTap"  "phase-2-5PTap"} phase)
+          (run-phase-2 exp eid recipient get-toolinfo template phase)))

       (#{"compare"} action) :HOW??


Fix outdated comment.

Fix outdated comment.

--- src/afterglow/dj_link.clj
+++ src/afterglow/dj_link.clj
@@ -108,7 +108,7 @@
         ;;       resyncing the bar start on each beat from the Pioneer equipment.
         ;;
         ;;       If/when that mode is figured out and made an option, the following
-        ;;       line will be invoked INSTEAD of the one above.
+        ;;       line will be invoked INSTEAD of the metro-beat-phase one above.
         #_(rhythm/metro-bar-phase (:metronome (/ (dec beat) 4)))))))

 (defn start


docstring cleanup for Cljdoc - keypin.core namespace

--- src/keypin/core.clj
+++ src/keypin/core.clj
@@ -25,7 +25,7 @@

 (defn lookup-key
-  "Look up a key in an associative data structure - Java map or something that implements clojure.lang.Associative."
+  "Look up a key in an associative data structure - a map or something that implements `clojure.lang.Associative`."
   [the-map the-key validator description value-parser default-value? default-value not-found]
   (when-not (or (instance? Map the-map)
               (instance? Associative the-map))
@@ -43,7 +43,7 @@

 (defn lookup-keypath
-  "Look up a key path in an associative data structure - Java map or something that implements clojure.lang.Associative."
+  "Look up a key path in an associative data structure - a map or something that implements `clojure.lang.Associative`."
   [the-map ks validator description value-parser default-value? default-value not-found]
   (let [value (loop [data the-map
                      path ks]
@@ -105,9 +105,13 @@

 (defn realize-config
   "Realize config by applying variable substitution, if any.
-  Options:
-  :logger        (object) instance of keypin.Logger, defaults to printing to *err*
-  :config-mapper (object) instance of keypin.Mapper, default: keypin.Mapper/DEFAULT"
+
+  ## Options
+
+  | Kwarg          | Type   | Description                 | Default                 |
+  |----------------|--------|-----------------------------|-------------------------|
+  |`:logger`       | object | instance of `keypin.Logger` | prints to `*err*`       |
+  |`:config-mapper`| object | instance of `keypin.Mapper` | `keypin.Mapper/DEFAULT` |"
   ([config]
     (realize-config config {}))
   ([config {:keys [logger config-mapper]
@@ -118,13 +122,17 @@

 (defn read-config
-  "Read config file(s) returning a java.util.Map instance.
-  Options:
-  :parent-key     (string)   key to identify the parent filenames having K/V pairs, default: \"parent.filenames\"
-  :logger         (object)   instance of keypin.Logger, defaults to printing to *err*
-  :config-readers (list/vec) collection of keypin.ConfigIO instances, default: for Properties and EDN files
-  :media-readers  (list/vec) collection of keypin.MediaReader instances, default: for Filesystem and Classpath
-  :realize?       (boolean)  whether realize the template variables in the string, default: true"
+  "Read config file(s) returning a `java.util.Map` instance.
+
+  ## Options
+
+  | Kwarg           | Type     | Description                                  | Default                         |
+  |-----------------|----------|----------------------------------------------|---------------------------------|
+  |`:parent-key`    | string   | key to identify the parent config filenames  | `\"parent.filenames\"`          |
+  |`:logger`        | object   | instance of `keypin.Logger`                  | prints to `*err*`               |
+  |`:config-readers`| list/vec | collection of `keypin.ConfigIO` instances    | for `.properties`, `.edn` files |
+  |`:media-readers` | list/vec | collection of `keypin.MediaReader` instances | for filesystem and classpath    |
+  |`:realize?`      | boolean  | whether realize template variables in string | `true`                          |"
   (^Map [config-filenames]
     (read-config config-filenames {}))
   (^Map [config-filenames {:keys [^String parent-key logger config-readers media-readers realize?]
@@ -147,10 +155,14 @@

 (defn write-config
   "Write config to a specified file.
-  Options:
-  :logger         (object)   instance of keypin.Logger, defaults to printing to *err*
-  :config-writers (list/vec) collection of keypin.ConfigIO instances, default: for Properties and EDN files
-  :escape?        (boolean)  whether escape values when writing, default: true"
+
+  ## Options
+
+  | Kwarg           | Type     | Description                               | Default                         |
+  |-----------------|----------|-------------------------------------------|---------------------------------|
+  |`:logger`        | object   | instance of `keypin.Logger`               | prints to `*err*`               |
+  |`:config-writers`| list/vec | collection of `keypin.ConfigIO` instances | for `.properties`, `.edn` files |
+  |`:escape?`       | boolean  | whether escape values when writing        | `true`                          |"
   ([config-filename config]
     (write-config config-filename config {}))
   ([config-filename config {:keys [logger config-writers escape?]
@@ -167,15 +179,26 @@
 (defn make-key
   "Create a key that can be looked up in a config store (keypin.type/IStore, java.util.Map/Properties or map/vector)
   instance. The following optional keys are supported:
-  :lookup  - The function to look the key up:
-             (fn [the-map the-key validator description value-parser default-value? default-value
-                  (fn not-found-fn [not-found-message])])
-             default: ordinary key look up
-  :parser  - The value parser function (args: key, value)
-  :default - Default value to return if key is not found
-  :sysprop - System property name that can override the config value (before parsing)
-  :envvar  - Environment variable that can override the config value and system property (before parsing)
-  :source  - Source or container (of reference type, e.g. atom/promise etc.) of key/value pairs"
+
+  | Kwarg    | Description                 |
+  |----------|-----------------------------|
+  |`:lookup` |Function to look the key up (details below) - default: [[lookup-key]] - ordinary key look up |
+  |`:parser` |The value parser function `(fn [key value])`                                                 |
+  |`:default`|Default value to return if key is not found                                                  |
+  |`:sysprop`|System property name that can override the config value (before parsing)                     |
+  |`:envvar` |Environment variable that can override the config value and system property (before parsing) |
+  |`:source` |Source or container (of reference type, e.g. atom/agent/promise etc.) of key/value pairs     |
+
+  ## Lookup function
+
+  ```
+  (fn [store key validator description value-parser default-value? default-value not-found-handler])->value
+
+  ;; validator is a predicate function: (fn [parsed-value])->boolean
+  ;; not-found-handler is function (fn not-found-fn [not-found-message]) called when the store does not have the kay
+  ```
+
+  See: [[lookup-key]], [[lookup-keypath]]"
   [the-key validator description {:keys [lookup parser default sysprop envvar source]
                                   :or {lookup lookup-key
                                        parser i/identity-parser}
@@ -204,20 +227,32 @@

 (defmacro defkey
   "Define one or more keys as vars using argument vectors. Every argument vector must have one of the following arities:
+
+  ```
   [key]
   [key options]
   [key validator description]
   [key validator description options]
-  See `make-key` for details. First argument to `defkey` can optionally be a base option-map for all argument vectors.
-  Examples:
+  ```
+
+  The `validator` is a predicate fn `(fn [parsed-value])->boolean` that returns true for valid values, false otherwise.
+
+  See [[make-key]] for options. First argument to `defkey` can optionally be a base option-map for all argument vectors.
+
+  ## Examples
+
+  ```
   (defkey
     ip   [:ip-address]
     port [:port #(< 1023 % 65535) \"Server port\" {:parser str->int :default 3000}])
+
   (defkey
     {:lookup lookup-key}
     ip   [\"server.ip.address\"]
     port [\"server.port\" #(< 1023 % 65535) \"Server port\" {:parser str->int :default 3000}])
-  See: make-key"
+  ```
+
+  See: [[make-key]]"
   [the-sym arg-vec & more]
   (let [options (if (odd? (count more))
                   (i/expect-arg the-sym map? ["Expected an option map, found" (pr-str the-sym)])
@@ -265,14 +300,18 @@

 (defmacro letval
-  "Like let, except in which the left hand side is a destructuring map, right hand side is the argument to key finder.
-  Beside symbols, the destructuring map optionally supports :defs (symbols bound to key finders) and :as keys.
-  Example:
+  "Like `let`, except in which the left hand side is a destructuring map, right hand side is the argument to key finder.
+  Beside symbols, the destructuring map optionally supports `:defs` (symbols bound to key finders) and `:as` keys.
+
+  ## Example
+
+  ```
   (letval [{:defs [foo bar] ; foo, bar are key finders
             baz baz-key     ; baz-key is a key finder
             :as m} {:foo 10 :bar 20 :baz 30}]
     ;; foo, bar and baz are now bound to values looked up in the map
-    ...)"
+    ...)
+  ```"
   [bindings & body]
   (i/expect-arg bindings vector? ["Expected a binding vector, but found" (pr-str bindings)])
   (i/expect-arg (count bindings) even? ["Expected even number of binding forms, but found" (pr-str bindings)])


Modfies control-group output to include errors from validation.

--- src/cadence/views/common.clj
+++ src/cadence/views/common.clj
@@ -2,6 +2,7 @@
   (:require [clojure.string :as string]
             [cemerick.friend :as friend]
             [cadence.model :as m]
+            [noir.validation :as vali]
             [cadence.model.flash :as flash])
   (:use noir.core
         hiccup.core
@@ -68,14 +69,30 @@
            [:strong (string/capitalize type) ": "] message]))
       content]]))

-(defpartial control-group [params]
-  (let [name (string/replace (string/lower-case (:name params)) #"\s" "-")]
-    [:div.control-group
+(defn format-errors
+  "Takes a collection of error messages and formats it into html."
+  [errs]
+  (if (> (count errs) 1)
+    [:div.help-block
+     [:ul (map #(html [:li %]) errs)]]
+    [:span.help-inline
+     (first errs)]))
+
+(defn control-group
+  "Renders a single form element in a control-group."
+  [params]
+  (let [name (string/replace (string/lower-case (:name params))
+                             #"\s" "-")
+        field (keyword name)
+        errors (vali/get-errors field)]
+    [:div {:class (str "control-group" (when (not (empty? errors)) " error"))}
      [:label.control-label {:for name} (str (:name params) ": ")]
      [:div.controls
       (if (= (:type params) "custom")
         (:content params)
         [:input (assoc (dissoc params :more) :name name)])
+      (when (not (nil? errors))
+        (format-errors errors))
       (:more params)]]))

 (defn- as-css-id [s]


load the bitfondue.config namespace in the handler

--- src/bitfondue/handler.clj
+++ src/bitfondue/handler.clj
@@ -14,6 +14,7 @@
             [buddy.auth :refer [authenticated? throw-unauthorized]]
             [buddy.auth.backends.token :refer [jwe-backend]]
             [buddy.auth.middleware :refer [wrap-authentication wrap-authorization]]
+            [bitfondue.config :as config]
             (bitfondue.models [users :as users]))
   (:use [ring.adapter.jetty :as ring])
   (:gen-class))


:use the amazonica namespace into the handler

--- src/bitfondue/handler.clj
+++ src/bitfondue/handler.clj
@@ -21,7 +21,10 @@
             [bitfondue.config :as config]
             (bitfondue.models [users :as users]
                               [chunks :as chunks]))
-  (:use [ring.adapter.jetty :as ring])
+  (:use [ring.adapter.jetty :as ring]
+        [clojure.pprint]
+        [amazonica.aws.s3]
+        [amazonica.aws.s3transfer :exclude [upload]])
   (:gen-class))

 (defn ok [d] {:status 200 :body d})


CMR-2482: More refactoring.

CMR-2482: More refactoring.

--- indexer-app/src/cmr/indexer/services/index_service.clj
+++ indexer-app/src/cmr/indexer/services/index_service.clj
@@ -166,20 +166,51 @@
               concept-id
               revision-date)))))

-(defn- get-collection-elastic-version
-  "Returns the elastic version of the collection with the given concept-id and revision-id"
-  ([context concept]
-   (let [tag-associations (mdb/get-tag-associations-for-collection context concept)]
-     (get-collection-elastic-version context concept tag-associations)))
-  ([_ concept tag-associations]
-   (es/get-elastic-version (assoc concept :tag-associations tag-associations))))
+(defmulti get-elastic-version-with-tag-associations
+  "Returns the elastic version of the concept and its tag associations"
+  (fn [context concept tag-associations]
+    (:concept-type concept)))
+
+(defmethod get-elastic-version-with-tag-associations :default
+  [context concept tag-associations]
+  (:revision-id concept))
+
+(defmethod get-elastic-version-with-tag-associations :collection
+  [context concept tag-associations]
+  (es/get-elastic-version (assoc concept :tag-associations tag-associations)))
+
+(defmulti get-elastic-version
+  "Returns the elastic version of the concept"
+  (fn [context concept]
+    (:concept-type concept)))
+
+(defmethod get-elastic-version :default
+  [context concept]
+  (:revision-id concept))
+
+(defmethod get-elastic-version :collection
+  [context concept]
+  (let [tag-associations (mdb/get-tag-associations-for-collection context concept)]
+    (get-elastic-version-with-tag-associations context concept tag-associations)))
+
+(defmulti get-tag-associations
+  "Returns the tag associations of the concept"
+  (fn [context concept]
+    (:concept-type concept)))
+
+(defmethod get-tag-associations :default
+  [context concept]
+  nil)
+
+(defmethod get-tag-associations :collection
+  [context concept]
+  (mdb/get-tag-associations-for-collection context concept))

 (defmulti index-concept
   "Index the given concept with the parsed umm record."
   (fn [context concept parsed-concept options]
     (:concept-type concept)))

-;; TODO Refactor this method and the next to pull out common code into a separate function.
 (defmethod index-concept :default
   [context concept parsed-concept options]
   (let [{:keys [all-revisions-index?]} options
@@ -190,35 +221,9 @@
       (let [concept-mapping-types (idx-set/get-concept-mapping-types context)
             delete-time (get-in parsed-concept [:data-provider-timestamps :delete-time])]
         (when (or (nil? delete-time) (t/after? delete-time (tk/now)))
-          (let [concept-index (idx-set/get-concept-index-name context concept-id revision-id
-                                                              all-revisions-index? concept)
-                es-doc (es/concept->elastic-doc context concept parsed-concept)
-                elastic-options (-> options
-                                    (select-keys [:all-revisions-index? :ignore-conflict?])
-                                    (assoc :ttl (when delete-time
-                                                  (t/in-millis (t/interval (tk/now) delete-time)))))]
-            (es/save-document-in-elastic
-              context
-              concept-index
-              (concept-mapping-types concept-type)
-              es-doc
-              concept-id
-              revision-id
-              revision-id
-              elastic-options)))))))
-
-(defmethod index-concept :collection
-  [context concept parsed-concept options]
-  (let [{:keys [all-revisions-index?]} options
-        {:keys [concept-id revision-id concept-type]} concept]
-    (when (indexing-applicable? concept-type all-revisions-index?)
-      (info (format "Indexing concept %s, revision-id %s, all-revisions-index? %s"
-                    concept-id revision-id all-revisions-index?))
-      (let [concept-mapping-types (idx-set/get-concept-mapping-types context)
-            delete-time (get-in parsed-concept [:data-provider-timestamps :delete-time])]
-        (when (or (nil? delete-time) (t/after? delete-time (tk/now)))
-          (let [tag-associations (mdb/get-tag-associations-for-collection context concept)
-                elastic-version (get-collection-elastic-version context concept tag-associations)
+          (let [tag-associations (get-tag-associations context concept)
+                elastic-version (get-elastic-version-with-tag-associations
+                                  context concept tag-associations)
                 tag-associations (map cp/parse-concept (filter #(not (:deleted %)) tag-associations))
                 concept-index (idx-set/get-concept-index-name context concept-id revision-id
                                                               all-revisions-index? concept)
@@ -276,9 +281,7 @@
   (let [{:keys [all-revisions-index?]} options
         concept-type (cs/concept-id->type concept-id)
         concept (meta-db/get-concept context concept-id revision-id)
-        elastic-version (if (= :collection concept-type)
-                          (get-collection-elastic-version context concept)
-                          revision-id)]
+        elastic-version (get-elastic-version context concept)]
     (when (indexing-applicable? concept-type all-revisions-index?)
       (info (format "Deleting concept %s, revision-id %s, all-revisions-index? %s"
                     concept-id revision-id all-revisions-index?))


added a few help topics

added a few help topics

--- src/cljs/netrunner/help.cljs
+++ src/cljs/netrunner/help.cljs
@@ -9,14 +9,37 @@
   "Sablono tags with FAQ about jinteki.net. Every header tag MUST have an ID here, defined with # in the keyword."
   (list [:h3#general "General"]

+        [:h4#dosomething "How do I do X (in game)?"] ;; TODO
+
+        [:h4#undo "How do I undo an action?"] ;; TODO
+
+        [:h4#closemenu "How do I close a card's menu?"] ;; TODO
+
+        [:h4#commands "What are the commands available during a game?"] ;; TODO
+
         [:h4#documentation "Is there more documentation on how to use jinteki.net?"]
         [:p "Read the "
          [:a {:href "https://github.com/mtgred/netrunner/wiki/Jinteki.net-Guide" :target "_blank"}
           "Jinteki.net Guide"] " on the GitHub wiki."]

+        [:h3#beginners "Beginners"]
+
+        [:h4#learnrules "Where can I find the game's rules explanation?"]
+        [:p "First step is reading " [:a {:href "https://www.fantasyflightgames.com/ffg_content/android-netrunner/support/android-netrunner-core-rules.pdf" :target "_blank"} "the official rulebook"]
+         ". If you prefer video form, FFG has prepared " [:a {:href "https://www.youtube.com/watch?v=VAslVfZ9p-Y" :target "_blank"} "a video tutorial"]
+         ", too."]
+        [:p "Once familiar with the basics, the finer points of rules/card interactions can be found in "
+         [:a {:href "https://www.fantasyflightgames.com/ffg_content/android-netrunner/support/FAQ/Android-Netrunner%20FAQ.pdf"} "the official FFG FAQ"] "."]
+
+        [:h4#firstgame "Can I play my first game on jinteki.net even though I'm a total beginner and never played in meatspace?"] ;; TODO
+
+        [:h4#finddecks "Where can I find some good starting decks?"] ;; TODO
+
+        [:h4#communities "Where can I find other Netrunner players to talk to?"] ;; TODO
+
         [:h3#site "Website"]

-        [:h4#avatar "How can I change my avatar?"]
+        [:h4#avatar "How do I change my avatar?"]
         [:p "Go to " [:a {:href "http://gravatar.com" :target "_blank"} "gravatar.com"]
          " and create an account with the same email as the one used to register on Jinteki.net."]

@@ -24,7 +47,19 @@
         [:p "Google Chrome or Firefox on a desktop or laptop is recommended. Safari should work fine too. "
          "Touchscreen devices (smartphones, tablets etc.) are currently not supported."]

+        [:h4#privatemsg "How do I send a private message / add someone to friendlist?"] ;; TODO
+
         [:h3#cards "Cards and Rules"]
+
+        [:h4#shards "How do I install Eden/Hades/Utopia Shard during a run?"] ;; TODO
+
+        [:h4#nasir "How do I use Nasir's ability?"] ;; TODO
+
+        [:h4#adam "How do I install Adam's directives?"] ;; TODO
+
+        [:h4#mwl "What is MWL? Why is my deck marked as \"Casual play only\"?"] ;; TODO
+
+        [:h4#rezaccess "How do I rez cards as Corp in the 4.3 run timing window?"] ;;TODO

         [:h3#troubleshooting "Troubleshooting"]

@@ -44,23 +79,23 @@
         [:h3#getinv "Getting Involved"]

         [:h4#bugs "How can I report a bug?"]
-        [:p "The best place to report bugs is the " [:a {:href "https://github.com/mtgred/netrunner/issues"} "GitHub issue tracker"]
+        [:p "The best place to report bugs is the " [:a {:href "https://github.com/mtgred/netrunner/issues" :target "_blank"} "GitHub issue tracker"]
          ". Before reporting, it is best to make a quick search to see if it's already been reported. "
          "If the bug concerns a card, look it up in "
-         [:a {:href "https://docs.google.com/spreadsheets/d/1ICv19cNjSaW9C-DoEEGH3iFt09PBTob4CAutGex0gnE/pubhtml"} "Card implementation status"]
+         [:a {:href "https://docs.google.com/spreadsheets/d/1ICv19cNjSaW9C-DoEEGH3iFt09PBTob4CAutGex0gnE/pubhtml" :target "_blank"} "Card implementation status"]
          " - the card in question may be unimplemented yet."]

         [:h4#features "How can I suggest a feature?"]
-        [:p "Same as bugs - feature requests should go on the " [:a {:href "https://github.com/mtgred/netrunner/issues"} "GitHub issue tracker"]
+        [:p "Same as bugs - feature requests should go on the " [:a {:href "https://github.com/mtgred/netrunner/issues" :target "_blank"} "GitHub issue tracker"]
          ". Again, it's best to make a quick search first to avoid duplicating existing issues."]

         [:h4#donations "How can I make a donation?"]
         [:p "Donation info can be found on the " [:a {:href "/about"} "About"] " page."]

         [:h4#devs "How can I help with the coding/webdesign?"]
-        [:p "Visit the project page on " [:a {:href "https://github.com/mtgred/netrunner/"} "GitHub"] " and fork "
+        [:p "Visit the project page on " [:a {:href "https://github.com/mtgred/netrunner/" :target "_blank"} "GitHub"] " and fork "
          "the repository. Implement the changes you were planning on doing and create a PR (Pull Request). If you are in "
-         "need of some ideas, check out " [:a {:href "https://github.com/mtgred/netrunner/labels/easy"} "issues marked 'easy' on GitHub"] "."]
+         "need of some ideas, check out " [:a {:href "https://github.com/mtgred/netrunner/labels/easy" :target "_blank"} "issues marked 'easy' on GitHub"] "."]
         [:p "After two of your PRs have been merged into the master branch, send an e-mail to "
          [:a {:href "mailto:mtgred@gmail.com"} "mtgred@gmail.com"] " stating who you are on GitHub and ask for access "
          "to Jinteki.net Slack, so you can get in better contact with the dev team."]


navbar a links to # for pointer

navbar a links to # for pointer

--- src/cljs/sjlibrary/core.cljs
+++ src/cljs/sjlibrary/core.cljs
@@ -8,11 +8,11 @@
 (defn app []
   [:div {:class "app"}
    [:div {:class "header navbar navbar-default"}
-    [:span {:class "pull-right"}
-     [:a {:class "navbar-text"} "Log in"]
-     [:a {:class "navbar-text"} "Get a card"]
-     [:a {:class "navbar-text"} "Contact us"]
-     [:a {:class "navbar-text"} "Help"]]]
+    [:ul {:class "nav navbar-nav pull-right"}
+     [:li [:a {:href "#"} "Log in"]]
+     [:li [:a {:href "#"} "Get a card"]]
+     [:li [:a {:href "#"} "Contact us"]]
+     [:li [:a {:href "#"} "Help"]]]]
    [:div {:class "subheader row"}
     [:div {:class "col-md-6"}
      [:h3 {:class ""} "The San Jose Public Library"]]


parameterize the depth of search

parameterize the depth of search

--- src/cljs/triboard/ai/ai.cljs
+++ src/cljs/triboard/ai/ai.cljs
@@ -16,13 +16,13 @@
   "The top level of the minimax algorithm
    * Trigger sub-game-trees minimax evaluations
    * Remember the transition that led to the max"
-  [ai turn]
+  [ai turn depth]
   (first
     (ai-algo/minimax-step-by
       second ai turn
       (fn [coord transition]
         (let [new-turn (turn/next-turn turn transition)]
-          [coord (ai-algo/minimax ai new-turn 1)]))
+          [coord (ai-algo/minimax ai new-turn depth)]))
       )))

 (defn- human-player-winning?
@@ -63,4 +63,4 @@
   [game]
   (let [turn (game/current-turn game)
         ai (high-level-ai turn)]
-    (move-tree-search ai turn)))
+    (move-tree-search ai turn 1)))


fix mistake in rw for duragent

fix mistake in rw for duragent

--- src/clojure/duratom/core.clj
+++ src/clojure/duratom/core.clj
@@ -619,7 +619,7 @@
 (defmethod duragent :postgres-db
   [_ & {:keys [db-config table-name row-id init lock rw meta]
         :or {lock (ReentrantLock.)
-             rw default-sqlite-rw}}]
+             rw default-postgres-rw}}]
   (let [make-backend (partial storage/->PGSQLBackend
                               db-config
                               (if (ut/postgres-table-exists? db-config table-name)
@@ -634,7 +634,7 @@
 (defmethod duragent :sqlite-db
   [_ & {:keys [db-config table-name row-id init lock rw meta]
         :or {lock (ReentrantLock.)
-             rw default-postgres-rw}}]
+             rw default-sqlite-rw}}]
   (let [make-backend (partial storage/->SQLiteBackend
                               db-config
                               (if (ut/sqlite-table-exists? db-config table-name)


Coerce `Path` objects to string for configuration.

--- src/clojure/parkour/conf.clj
+++ src/clojure/parkour/conf.clj
@@ -6,6 +6,7 @@
   (:import [java.io Writer]
            [java.util List Map Set]
            [org.apache.hadoop.conf Configuration Configurable]
+           [org.apache.hadoop.fs Path]
            [org.apache.hadoop.mapreduce Job JobContext]))

 (def ^:dynamic ^:private ^Configuration *default*
@@ -139,6 +140,7 @@
   Boolean (.setBoolean conf key (boolean val)))

 (defmethod conf-coerce :default [val] val)
+(defmethod conf-coerce Path [val] (str val))
 (defmethod conf-coerce Class [val] (.getName ^Class val))
 (defmethod conf-coerce List [val] (str/join "," (map conf-coerce val)))
 (defmethod conf-coerce Set [val] (str/join "," (map conf-coerce val)))


Trying to get some extra perfz in a hot path

--- src/clojure/picard/netty.clj
+++ src/clojure/picard/netty.clj
@@ -10,6 +10,7 @@
     ChannelEvent
     ChannelFuture
     ChannelFutureListener
+    ChannelHandlerContext
     ChannelPipeline
     ChannelPipelineFactory
     ChannelState
@@ -190,7 +191,7 @@
   "Creates a pipeline state for upstream events."
   [handler]
   (reify ChannelUpstreamHandler
-    (handleUpstream [_ ctx evt]
+    (^void handleUpstream [_ ^ChannelHandlerContext ctx ^ChannelEvent evt]
       (handler (.getChannel evt) evt)
       (.sendUpstream ctx evt))))


Await uninterruptible when shutting down a server

--- src/clojure/picard/netty.clj
+++ src/clojure/picard/netty.clj
@@ -295,9 +295,9 @@

 (defn shutdown
   [[bootstrap channel-group]]
-  (on-complete
-   (.close channel-group)
-   (fn [_] (.releaseExternalResources bootstrap))))
+  (let [close-future (.close channel-group)]
+    (.awaitUninterruptibly close-future)
+    (.releaseExternalResources bootstrap)))

 (defn start-server
   "Starts a server. Returns a function that stops the server"


Remove BlockCipher hint from the hashmaps of said

--- src/buddy/core/crypto.clj
+++ src/buddy/core/crypto.clj
@@ -42,7 +42,7 @@
 ;; --- Constants

 (def ^:no-doc
-  ^BlockCipher +block-cipher-engines+
+  +block-cipher-engines+
   {:aes     #(AESFastEngine.)
    :serpent #(SerpentEngine.)
    :twofish #(TwofishEngine.)})
@@ -52,7 +52,7 @@
   {:chacha #(ChaChaEngine.)})

 (def ^:no-doc
-  ^BlockCipher +cipher-modes+
+  +cipher-modes+
   {:ecb #(identity %)
    :cbc #(CBCBlockCipher. %)
    :gcm #(GCMBlockCipher. %)


Add enumeration to file store.

Add enumeration to file store.

--- src/blocks/store/file.clj
+++ src/blocks/store/file.clj
@@ -194,7 +194,16 @@
     [this id]
     (when-block id
       (locking this
-        (.delete file)))))
+        (.delete file))))
+
+
+  store/BlockEnumerator
+
+  (enumerate
+    [this]
+    (->> (.listFiles root)
+         (mapcat #(.listFiles %))
+         (map #(file->block (file->id root %) %)))))

 (defn erase!


CLJS-1171: map clojure.repl/doc, clojure.repl/source, clojure.repl/dir

map clojure.repl -> cljs.repl

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -1782,6 +1782,7 @@
           (if-let [nstr (namespace sym)]
             (when-let [ns (cond
                            (= "clojure.core" nstr) (find-ns 'cljs.core)
+                           (= "clojure.repl" nstr) (find-ns 'cljs.repl)
                            (.contains nstr ".") (find-ns (symbol nstr))
                            :else
                            (some-> env :ns :require-macros (get (symbol nstr)) find-ns))]


Fix reflection warnings on repl startup

Fix reflection warnings on repl startup

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -743,7 +743,7 @@
       (.eval jse r))
     (.eval jse bootjs)
     ;; Load deps.js line-by-line to avoid 64K method limit
-    (doseq [line (line-seq (io/reader deps))]
+    (doseq [^String line (line-seq (io/reader deps))]
       (.eval jse line))
     {:jse jse}))


CLJS-254: error on multiple :require, :use, etc in ns

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -1204,14 +1204,19 @@
                   (if (= k :refer-clojure)
                     (do
                       (assert (= exclude :exclude) "Only [:refer-clojure :exclude [names]] form supported")
+                      (assert (not (seq s)) "Only one :refer-clojure form is allowed per namespace definition")
                       (into s xs))
                     s))
                 #{} args)
         deps (atom #{})
+        valid-forms (atom #{:use :use-macros :require :require-macros})
         {uses :use requires :require uses-macros :use-macros requires-macros :require-macros :as params}
         (reduce (fn [m [k & libs]]
                   (assert (#{:use :use-macros :require :require-macros} k)
                           "Only :refer-clojure, :require, :require-macros, :use and :use-macros libspecs supported")
+                  (assert (@valid-forms k)
+                          (str "Only one " k " form is allowed per namespace definition"))
+                  (swap! valid-forms disj k)
                   (assoc m k (into {}
                                    (mapcat (fn [[lib kw expr]]
                                              (swap! deps conj lib)


* src/clj/cljs/compiler.clj: only try to optimize higher order fn calls when *cljs-static-fns* true

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -751,7 +751,7 @@
        (emits f "(" (comma-sep args)  ")")

        :else
-       (if (= (:op f) :var)
+       (if (and *cljs-static-fns* (= (:op f) :var))
          (let [fprop (str ".cljs$lang$arity$" (count args))]
            (emits "(" f fprop " ? " f fprop "(" (comma-sep args) ") : " f ".call(" (comma-sep (cons "null" args)) "))"))
          (emits f ".call(" (comma-sep (cons "null" args)) ")"))))))


Remove events from server

Remove events from server

--- src/clj/threed/server.clj
+++ src/clj/threed/server.clj
@@ -30,21 +30,10 @@
    :headers {"Content-Type" "application/edn"}
    :body (pr-str data)})

-(defonce events (atom []))
-
 (defroutes routes
   (resources "/")

   (GET "/ws" [] comms/ws)
-
-  ;; TODO remove /events -- use system-bus
-  (wrap-restful-response (GET "/events" [] {:body {:events @events}}) :formats [:edn])
-
-  ;;wrap-json-body
-  (POST "/events" {params :params}
-        (do (swap! events concat (:events params))
-            ;;(comms/send-events! @events)
-            {:status 200 :body "OK"}))

   (GET "/*" req (page)))


Improve Username and Password Clear after Sign-In

--- src/cljs/lens/navbar.cljs
+++ src/cljs/lens/navbar.cljs
@@ -41,9 +41,7 @@
        :expanded false})
   (will-mount [_]
     (bus/listen-on owner :signed-in
-      #(do
-        (om/set-state! owner :username "")
-        (om/set-state! owner :password ""))))
+      (om/update-state! owner #(assoc % :username "" :password ""))))
   (will-unmount [_]
     (bus/unlisten-all owner))
   (did-update [_ _ prev-state]


Remove reader monad from labs.

Remove reader monad from labs.

--- src/cats/labs/reader.cljc
+++ src/cats/labs/reader.cljc
@@ -1,186 +0,0 @@
-;; Copyright (c) 2014-2015 Andrey Antukh <niwi@niwi.nz>
-;; Copyright (c) 2014-2015 Alejandro Gómez <alejandro@dialelo.com>
-;; All rights reserved.
-;;
-;; Redistribution and use in source and binary forms, with or without
-;; modification, are permitted provided that the following conditions
-;; are met:
-;;
-;; 1. Redistributions of source code must retain the above copyright
-;;    notice, this list of conditions and the following disclaimer.
-;; 2. Redistributions in binary form must reproduce the above copyright
-;;    notice, this list of conditions and the following disclaimer in the
-;;    documentation and/or other materials provided with the distribution.
-;;
-;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-(ns cats.labs.reader
-  "The Reader Monad."
-  #?(:clj  (:require [cats.context :as ctx]
-                     [cats.protocols :as p]
-                     [cats.util :as util])
-     :cljs (:require [cats.context :as ctx :include-macros true]
-                     [cats.protocols :as p]
-                     [cats.util :as util])))
-
-(declare context)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Protocol declaration
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defprotocol MonadReader
-  "A specific case of Monad abstraction that
-  allows a read only access to an environment."
-  (-ask [m] "Return the current environment.")
-  (-local [m f reader] "Create a reader in a modified version of the environment."))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Type constructors and functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(deftype Reader [mfn]
-  p/Contextual
-  (-get-context [_] context)
-
-  #?@(:cljs [cljs.core/IFn
-             (-invoke [self seed]
-               (mfn seed))]
-      :clj  [clojure.lang.IFn
-             (invoke [self seed]
-               (mfn seed))]))
-
-(alter-meta! #'->Reader assoc :private true)
-
-(defn reader
-  "The Reader type constructor.
-
-  The purpose of Reader type is wrap a simple
-  function that fullfill the reader signature.
-
-  It exists just for avoid extend the clojure
-  function type because is very generic type."
-  [f]
-  (Reader. f))
-
-(defn reader?
-  "Return true if `s` is instance
-  of Reader type."
-  [s]
-  (instance? Reader s))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Monad definition
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(def ^{:no-doc true}
-  context
-  (reify
-    p/Context
-    (-get-level [_] ctx/+level-default+)
-
-    p/Functor
-    (-fmap [_ f fv]
-      (reader (fn [env]
-                (f (fv env)))))
-
-    p/Monad
-    (-mreturn [_ v]
-      (reader (fn [env]
-                v)))
-
-    (-mbind [_ mv f]
-      (reader (fn [env]
-                ((f (mv env)) env))))
-
-    MonadReader
-    (-ask [_]
-      (reader (fn [env]
-                env)))
-
-    (-local [_ f mr]
-      (reader (fn [env]
-                (mr (f env)))))
-
-    p/Printable
-    (-repr [_]
-      #"<Reader>")))
-
-(util/make-printable (type context))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Monad Transformer
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defn reader-t
-  "The Reader transformer constructor."
-  [inner-monad]
-  (reify
-    p/Context
-    (-get-level [_] ctx/+level-transformer+)
-
-    p/Functor
-    (-fmap [_ f fv]
-      (reader (fn [env]
-                (p/-fmap inner-monad f (fv env)))))
-
-    p/Monad
-    (-mreturn [_ v]
-      (p/-mreturn context (p/-mreturn inner-monad v)))
-
-    (-mbind [_ mr f]
-      (fn [env]
-        (p/-mbind inner-monad
-                     (mr env)
-                     (fn [a]
-                       ((f a) env)))))
-
-    p/MonadTrans
-    (-lift [m mv]
-      (fn [_] mv))
-
-    MonadReader
-    (-ask [_]
-      (fn [env]
-        (p/-mreturn inner-monad env)))
-
-    (-local [_ f mr]
-      (fn [env]
-        (mr (f env))))
-
-    p/Printable
-    (-repr [_]
-      "#<Reader-T")))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Reader monad functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defn run-reader
-  "Given a Reader instance, execute the
-  wrapped computation and returns a value."
-  [reader seed]
-  (ctx/with-context context
-    (reader seed)))
-
-(def ask
-  (reader
-   (fn [env]
-     (let [ctx (ctx/get-current context)]
-       ((-ask ctx) env)))))
-
-(def local
-  (fn [f mr]
-    (reader
-     (fn [env]
-       (let [ctx (ctx/get-current context)]
-         ((-local ctx f mr) env))))))


CLJS-268 warn on calling type constructor with wrong number of arguments

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -1113,7 +1113,13 @@
   (disallowing-recur
    (let [enve (assoc env :context :expr)
          ctorexpr (analyze enve ctor)
-         argexprs (vec (map #(analyze enve %) args))]
+         argexprs (vec (map #(analyze enve %) args))
+         known-num-fields (:num-fields (resolve-existing-var env ctor))
+         argc (count args)]
+     (when (and known-num-fields (not= known-num-fields argc))
+       (warning env
+         (str "WARNING: Wrong number of args (" argc ") passed to " ctor)))
+
      {:env env :op :new :form form :ctor ctorexpr :args argexprs
       :children (into [ctorexpr] argexprs)})))

@@ -1220,7 +1226,9 @@
   (let [t (munge (:name (resolve-var (dissoc env :locals) tsym)))]
     (swap! namespaces update-in [(-> env :ns :name) :defs tsym]
            (fn [m]
-             (let [m (assoc (or m {}) :name t)]
+             (let [m (assoc (or m {})
+                       :name t
+                       :num-fields (count fields))]
                (if-let [line (:line env)]
                  (-> m
                      (assoc :file *cljs-file*)


Update docstring

Update docstring

--- src/clj/precept/core.cljc
+++ src/clj/precept/core.cljc
@@ -203,7 +203,16 @@
   [facts]
   (dispatch! (fn [session] (util/insert session facts))))

-(defn start! [options]
+(defn start!
+  "Initializes session with facts.
+
+  - :session - the `session` from which changes will be tracked
+  - :facts - initial facts
+
+  Once initialized, facts are synced to a reagent ratom (`state/store`) and accessed via
+  subscriptions.
+  "
+  [{:keys [session facts] :as options}]
   (let [opts (or options (hash-map))]
     (swap-session-sync!
       (l/replace-listener (:session opts))


allow accidental whitespace at the beginning/end of sms messages

--- src/clj/tictag/server.clj
+++ src/clj/tictag/server.clj
@@ -18,18 +18,14 @@
             [hiccup.core :refer [html]]
             [hiccup.page :refer [html5]]))

-(def delimiters #"[ ,]")
-
 (defn str-number? [s]
   (try (Long. s) (catch Exception e nil)))

-(defn parse-body [body]
-  (let [[id & tags] (str/split (str/lower-case body) delimiters)]
-    {:id id
-     :tags tags}))
-
 (defn parse-sms-body [body]
-  (let [[cmd? & args :as all-args] (str/split (str/lower-case body) #" ")]
+  (let [[cmd? & args :as all-args] (-> body
+                                       (str/lower-case)
+                                       (str/trim)
+                                       (str/split #" "))]
     (if (str-number? cmd?)
       (if (> (count cmd?) 3)
         {:command :tag-ping-by-long-time


Fix typo

Fix typo

--- src/cljam/util/region.clj
+++ src/cljam/util/region.clj
@@ -7,7 +7,7 @@
 ;;; ----------

 (defn overlapped-regions?
-  "Returns true iff two regions are overlapped with each other."
+  "Returns true if two regions are overlapped with each other."
   [x y]
   (and (= (:chr x) (:chr y))
        (<= (:start y) (:end x))


add todo for #148

add todo for #148

--- src/cljs_api_gen/read.clj
+++ src/cljs_api_gen/read.clj
@@ -38,6 +38,12 @@
     (let [is (io/input-stream path)
           r1 (readers/input-stream-push-back-reader is)
           r  (readers/source-logging-push-back-reader r1 1 path)]
+      ;; TODO: For starters, if the file is cljc, run read-forms twice with :clj and :cljs,
+      ;; and maybe add a metadata tag {:reader-feature :cljs},
+      ;;
+      ;; I believe we only need the :cljs forms to add the extra source entry to the primary :clj form.
+      ;;
+      ;; Not sure where to perform that merge.  Maybe in parse-ns*
       (read-forms r))))

 (defn read-forms-from-str


Added vector instructions to instruction-types

--- src/clojush/pushstate.clj
+++ src/clojush/pushstate.clj
@@ -247,6 +247,7 @@
     exec_yankdup [:exec :integer]
     float_add [:float]
     float_cos [:float]
+    float_dec [:float]
     float_div [:float]
     float_dup [:float]
     float_empty [:boolean :float]
@@ -258,6 +259,7 @@
     float_fromstring [:string :float]
     float_gt [:float :boolean]
     float_gte [:float :boolean]
+    float_inc [:float]
     float_lt [:float :boolean]
     float_lte [:float :boolean]
     float_max [:float]
@@ -335,6 +337,7 @@
     string_containschar [:string :boolean :char]
     string_dup [:string]
     string_empty [:boolean :string]
+    string_emptystring [:boolean :string]
     string_eq [:string :boolean]
     string_first [:string :char]
     string_flush [:string]
@@ -346,7 +349,7 @@
     string_last [:string :char]
     string_length [:string :integer]
     string_nth [:string :integer :char]
-    string_occurencesofchar [:string :integer :char]
+    string_occurrencesofchar [:string :integer :char]
     string_parse_to_chars [:string]
     string_pop [:string]
     string_rand [:string :random]
@@ -366,6 +369,126 @@
     string_take [:string :integer]
     string_yank [:string :integer]
     string_yankdup [:string :integer]
+    vector_boolean_butlast [:vector_boolean]
+    vector_boolean_concat [:vector_boolean]
+    vector_boolean_conj [:vector_boolean :boolean]
+    vector_boolean_contains [:vector_boolean :boolean]
+    vector_boolean_dup [:vector_boolean]
+    vector_boolean_empty [:vector_boolean :boolean]
+    vector_boolean_emptyvector [:vector_boolean :boolean]
+    vector_boolean_eq [:vector_boolean :boolean]
+    vector_boolean_first [:vector_boolean :boolean]
+    vector_boolean_flush [:vector_boolean]
+    vector_boolean_indexof [:vector_boolean :boolean :integer]
+    vector_boolean_last [:vector_boolean :boolean]
+    vector_boolean_length [:vector_boolean :integer]
+    vector_boolean_nth [:vector_boolean :boolean :integer]
+    vector_boolean_occurrencesof [:vector_boolean :boolean :integer]
+    vector_boolean_pop [:vector_boolean]
+    vector_boolean_pushall [:vector_boolean :boolean]
+    vector_boolean_remove [:vector_boolean :boolean]
+    vector_boolean_replace [:vector_boolean :boolean]
+    vector_boolean_replacefirst [:vector_boolean :boolean]
+    vector_boolean_rest [:vector_boolean]
+    vector_boolean_reverse [:vector_boolean]
+    vector_boolean_rot [:vector_boolean]
+    vector_boolean_shove [:vector_boolean :integer]
+    vector_boolean_stackdepth [:vector_boolean :integer]
+    vector_boolean_subvec [:vector_boolean :integer]
+    vector_boolean_swap [:vector_boolean]
+    vector_boolean_take [:vector_boolean :integer]
+    vector_boolean_yank [:vector_boolean :integer]
+    vector_boolean_yankdup [:vector_boolean :integer]
+    vector_float_butlast [:vector_float]
+    vector_float_concat [:vector_float]
+    vector_float_conj [:vector_float :float]
+    vector_float_contains [:vector_float :boolean :float]
+    vector_float_dup [:vector_float]
+    vector_float_empty [:vector_float :boolean]
+    vector_float_emptyvector [:vector_float :boolean]
+    vector_float_eq [:vector_float :boolean]
+    vector_float_first [:vector_float :float]
+    vector_float_flush [:vector_float]
+    vector_float_indexof [:vector_float :float :integer]
+    vector_float_last [:vector_float :float]
+    vector_float_length [:vector_float :integer]
+    vector_float_nth [:vector_float :float :integer]
+    vector_float_occurrencesof [:vector_float :float :integer]
+    vector_float_pop [:vector_float]
+    vector_float_pushall [:vector_float :float]
+    vector_float_remove [:vector_float :float]
+    vector_float_replace [:vector_float :float]
+    vector_float_replacefirst [:vector_float :float]
+    vector_float_rest [:vector_float]
+    vector_float_reverse [:vector_float]
+    vector_float_rot [:vector_float]
+    vector_float_shove [:vector_float :integer]
+    vector_float_stackdepth [:vector_float :integer]
+    vector_float_subvec [:vector_float :integer]
+    vector_float_swap [:vector_float]
+    vector_float_take [:vector_float :integer]
+    vector_float_yank [:vector_float :integer]
+    vector_float_yankdup [:vector_float :integer]
+    vector_integer_butlast [:vector_integer]
+    vector_integer_concat [:vector_integer]
+    vector_integer_conj [:vector_integer :integer]
+    vector_integer_contains [:vector_integer :integer :boolean]
+    vector_integer_dup [:vector_integer]
+    vector_integer_empty [:vector_integer :boolean]
+    vector_integer_emptyvector [:vector_integer :boolean]
+    vector_integer_eq [:vector_integer :boolean]
+    vector_integer_first [:vector_integer :integer]
+    vector_integer_flush [:vector_integer]
+    vector_integer_indexof [:vector_integer :integer]
+    vector_integer_last [:vector_integer :integer]
+    vector_integer_length [:vector_integer :integer]
+    vector_integer_nth [:vector_integer :integer]
+    vector_integer_occurrencesof [:vector_integer :integer]
+    vector_integer_pop [:vector_integer]
+    vector_integer_pushall [:vector_integer :integer]
+    vector_integer_remove [:vector_integer :integer]
+    vector_integer_replace [:vector_integer :integer]
+    vector_integer_replacefirst [:vector_integer :integer]
+    vector_integer_rest [:vector_integer]
+    vector_integer_reverse [:vector_integer]
+    vector_integer_rot [:vector_integer]
+    vector_integer_shove [:vector_integer :integer]
+    vector_integer_stackdepth [:vector_integer :integer]
+    vector_integer_subvec [:vector_integer :integer]
+    vector_integer_swap [:vector_integer]
+    vector_integer_take [:vector_integer :integer]
+    vector_integer_yank [:vector_integer :integer]
+    vector_integer_yankdup [:vector_integer :integer]
+    vector_string_butlast [:vector_string]
+    vector_string_concat [:vector_string]
+    vector_string_conj [:vector_string :string]
+    vector_string_contains [:vector_string :string :boolean]
+    vector_string_dup [:vector_string]
+    vector_string_empty [:vector_string :boolean]
+    vector_string_emptyvector [:vector_string :boolean]
+    vector_string_eq [:vector_string :boolean]
+    vector_string_first [:vector_string :string]
+    vector_string_flush [:vector_string]
+    vector_string_indexof [:vector_string :string :integer]
+    vector_string_last [:vector_string :string]
+    vector_string_length [:vector_string :integer]
+    vector_string_nth [:vector_string :string :integer]
+    vector_string_occurrencesof [:vector_string :string :integer]
+    vector_string_pop [:vector_string]
+    vector_string_pushall [:vector_string :string]
+    vector_string_remove [:vector_string :string]
+    vector_string_replace [:vector_string :string]
+    vector_string_replacefirst [:vector_string :string]
+    vector_string_rest [:vector_string]
+    vector_string_reverse [:vector_string]
+    vector_string_rot [:vector_string]
+    vector_string_shove [:vector_string :integer]
+    vector_string_stackdepth [:vector_string :integer]
+    vector_string_subvec [:vector_string :integer]
+    vector_string_swap [:vector_string]
+    vector_string_take [:vector_string :integer]
+    vector_string_yank [:vector_string :integer]
+    vector_string_yankdup [:vector_string :integer]
     zip_append_child_fromcode [:zip :code]
     zip_append_child_fromexec [:zip :exec]
     zip_branch? [:zip :boolean]
@@ -405,8 +528,17 @@
 ; The following finds instructions that haven't yet been added to instruction-types
 (defn print-instructions-without-types
   []
+  (println "===============================")
+  (println "The following are in @registered-instructions but not in instruction-types (and should be added)")
+  (println "===============================")
   (doseq [ins (sort-by name (clojure.set/difference (set @registered-instructions)
                                                     (set (keys instruction-types))))]
+    (println ins))
+  (println "===============================")
+  (println "The following are in instruction-types but not in @registered-instructions")
+  (println "===============================")
+  (doseq [ins (sort-by name (clojure.set/difference (set (keys instruction-types))
+                                                    (set @registered-instructions)))]
     (println ins)))

 (defn registered-for-stacks


fix advanced compilation bug

fix advanced compilation bug

--- frontend/components/build_steps.cljs
+++ frontend/components/build_steps.cljs
@@ -143,9 +143,9 @@
         (html
          [:div#container_scroll_parent ;; hides horizontal scrollbar
           [:div#container_parent {:on-wheel (fn [e]
-                                              (when (not= 0 (.-deltaX e))
+                                              (when (not= 0 (aget e "deltaX"))
                                                 (.preventDefault e)
-                                                (aset js/document.body "scrollTop" (+ js/document.body.scrollTop (.-deltaY e)))))
+                                                (aset js/document.body "scrollTop" (+ (aget js/document.body "scrollTop") (aget e "deltaY")))))
                                   :on-scroll (fn [e]
                                                ;; prevent handling scrolling if we're animating the
                                                ;; transition to a new selected container


(maint) rename check-endpoint-test to endpoint-test

We're testing the Endpoint definition, rather than a function called
check-endpoint

--- test/puppetlabs/cthun/validation_test.clj
+++ test/puppetlabs/cthun/validation_test.clj
@@ -3,7 +3,7 @@
             [puppetlabs.cthun.validation :refer :all]
             [schema.core :as s]))

-(deftest check-endpoint-test
+(deftest endpoint-test
   (testing "it raises an exception for invalid endpoints"
     (is (thrown? Exception (s/validate Endpoint "")))
     (is (thrown? Exception (s/validate Endpoint "http://")))