implement authentication

implement authentication

--- src_cljs/rrm/corecljs.cljs
+++ src_cljs/rrm/corecljs.cljs
@@ -31,6 +31,7 @@
                           :o2mutations {}
                           :o4mutations {}
                           :o6mutations {}
+                          :token ""
                           :is-searched-results false
                           :user nil}))

@@ -42,6 +43,9 @@
 (defn http-get [url callback]
   (xhr/send url callback))

+(defn http-get-auth [url callback]
+  (xhr/send url callback "GET" "" (clj->js {:rrm-auth (get-value! :token)})))
+
 (defn get-value! [k]
   (k @storage))

@@ -58,13 +62,13 @@
   (.getStatus (.-target res)))

 (defn http-post [url callback data]
-  (xhr/send url callback "POST" data  (structs/Map. (clj->js {:Content-Type "application/json"}))))
+  (xhr/send url callback "POST" data  (structs/Map. (clj->js {:Content-Type "application/json" :rrm-auth (get-value! :token)}))))

 (defn http-put [url callback data]
-  (xhr/send url callback "PUT" data  (structs/Map. (clj->js {:Content-Type "application/json"}))))
+  (xhr/send url callback "PUT" data  (structs/Map. (clj->js {:Content-Type "application/json" :rrm-auth (get-value! :token)}))))

 (defn http-delete [url callback]
-  (xhr/send url callback "DELETE"  (structs/Map. (clj->js {:Content-Type "application/json"}))))
+  (xhr/send url callback "DELETE" "" (structs/Map. (clj->js {:Content-Type "application/json" :rrm-auth (get-value! :token)}))))

 ;; =====================================================================================================
@@ -73,8 +77,8 @@

 (defn login-validator [data-set]
   (first (b/validate data-set
-                     :email [[v/required :message "Filed is required"]
-                             [v/email :message "Enter valid email-id"]]
+                     :username [[v/required :message "Filed is required"]
+                         [v/email :message "Enter valid email-id"]]
                      :password [[v/required :message "Filed is required"]
                                 [v/string  :message "Enter valid password"]])))

@@ -109,9 +113,10 @@
   (if (= nil (login-validator @data-set))
     (let [onresp (fn [json]
                    (if (= (get-status json) 200)
-                     ((set-key-value :user (getdata json))
-                      (secretary/dispatch! "/documents"))))]
-      (http-post (str serverhost "user/authenticate")
+                     ((set-key-value :user (.-_2 (getdata json)))
+                      (set-key-value :token (.-_1 (getdata json)))
+                      (secretary/dispatch! "/"))))]
+      (http-post (str serverhost "login")
                  onresp (.serialize (Serializer.) (clj->js @data-set ))))
     (reset! focus "on")))

@@ -129,7 +134,7 @@
         [:div.panel-heading
          [:h2 "Log-in"]]
         [:div.panel-body
-         [login-input-element :email "Email"  "input-group-addon glyphicon glyphicon-user" "email" my-data "Email" focus]
+         [login-input-element :username "Email"  "input-group-addon glyphicon glyphicon-user" "email" my-data "Email" focus]
          [login-input-element :password "Password"  "input-group-addon glyphicon glyphicon-lock" "password" my-data "password" focus]
          [submit-button my-data focus ]]]])))

@@ -141,8 +146,9 @@
   (not (nil? (get-value! :user))))

 (defn set-page! [currnt-page]
-  (set-key-value :page-location
-                 currnt-page))
+  (if (nil? (get-value! :user)) (set-key-value :page-location [login])
+      (set-key-value :page-location
+                     currnt-page)))

 (defn get-total-rec-no [nos]
   (let [totrec (quot nos 10)]
@@ -229,13 +235,12 @@
                 (let [dt (getdata json)]
                   (set-key-value :mutations (.-data dt))
                   (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location
-                                 [render-mutations (get-value! :mutations)])))]
-    (http-get (get-index-url (get-value! :is-searched-results)
-                             (dec (get-value! :current-page))
-                             vid mn fp sp po
-                             kknum so2 st knum)
-              onres)))
+                  (set-page! [render-mutations (get-value! :mutations)])))]
+    (http-get-auth (get-index-url (get-value! :is-searched-results)
+                                  (dec (get-value! :current-page))
+                                  vid mn fp sp po
+                                  kknum so2 st knum)
+                   onres)))

 (defn pager [value total-rec]
   [pager-elem {:bsSize "large"
@@ -313,13 +318,13 @@
                           (set-key-value :mutations (.-data data))
                           (set-key-value :total-pages
                                          (get-total-rec-no (.-pagesCount data)))
-                          (set-key-value :page-location
-                                         [render-mutations (get-value! :mutations)])))]
+                          (set-page! :page-location
+                                     [render-mutations (get-value! :mutations)])))]
     (set-key-value :current-page 1)
     (set-key-value :is-searched-results true)
-    (http-get (str (get-search-url
-                    vid mn fp sp po
-                    kknum so2 st knum)"&pageIndex=0&pageSize=10") onres)))
+    (http-get-auth (str (get-search-url
+                         vid mn fp sp po
+                         kknum so2 st knum)"&pageIndex=0&pageSize=10") onres)))

 (defn input [label type id]
@@ -396,9 +401,8 @@
               (let [dt (getdata json)]
                 (set-key-value :subdivisions dt)
                 (set-key-value :villages nil)))]
-    (do (http-get (str  serverhost "districts/" val  "/subdivisions") res)
-        (swap! data-set assoc id val)
-        )))
+    (do (http-get-auth (str  serverhost "districts/" val  "/subdivisions") res)
+        (swap! data-set assoc id val))))

 (defn dist-sel-tag [id data data-set]
   [:select.form-control {:id id
@@ -419,9 +423,8 @@
   (let [res (fn [json]
               (let [dt (getdata json)]
                 (set-key-value :villages dt)))]
-    (do (http-get (str serverhost "subdivisions/" val  "/villages") res)
-        (swap! data-set assoc id val)
-        )))
+    (do (http-get-auth (str serverhost "subdivisions/" val  "/villages") res)
+        (swap! data-set assoc id val))))

 (defn sub-sel-tag [id data data-set]
   [:select.form-control {:id id
@@ -542,9 +545,7 @@
 (defn add-form-onclick [data-set focus]
   (if (= nil (form-validator @data-set))
     (let [onres (fn[json]
-                  (secretary/dispatch! "/"))
-                                        ; data (swap! data-set dissoc :districtid :subdivisionid)
-          ]
+                  (secretary/dispatch! "/"))]
       (http-post (str serverhost "mutations")
                  onres  (.serialize (Serializer.) (clj->js (map-mutation-data @data-set)))))
     (reset! focus "on")))
@@ -552,9 +553,7 @@
 (defn update-form-onclick [data-set focus]
   (if (= nil (form-validator @data-set))
     (let [onres (fn[data]
-                  (secretary/dispatch! "/"))
-         ; data (swap! data-set dissoc :districtid :subdivisionid)
-          ]
+                  (secretary/dispatch! "/"))]
       (http-put (str serverhost "mutations/" (:id @data-set))
                 onres (.serialize (Serializer.) (clj->js (map-mutation-data @data-set))))))
   (reset! focus "on"))
@@ -580,10 +579,9 @@
                   (set-key-value :total-pages (get-total-rec-no
                                                (.-pagesCount mt)))
                   (set-key-value :current-page 1)
-                  (set-key-value :page-location
-                                 [render-mutations (get-value! :mutations)])))]
+                  (set-page! [render-mutations (get-value! :mutations)])))]
     (set-key-value :is-searched-results false)
-    (http-get (str serverhost "mutations?pageIndex=0&pageSize=10") onres)))
+    (http-get-auth (str serverhost "mutations?pageIndex=0&pageSize=10") onres)))

 (defn src-dist-onchange [val]
@@ -591,7 +589,7 @@
               (let [dt (getdata json)]
                 (set-key-value :subdivisions dt)
                 (set-key-value :villages nil)))]
-    (http-get (str  serverhost "districts/" val  "/subdivisions") res)))
+    (http-get-auth (str  serverhost "districts/" val  "/subdivisions") res)))

 (defn src-dist-sel-tag []
   [:select.form-control {:id :src-dist
@@ -606,7 +604,7 @@
   (let [res (fn [json]
               (let [dt (getdata json)]
                 (set-key-value :villages dt)))]
-    (http-get (str serverhost "subdivisions/" val  "/villages") res)))
+    (http-get-auth (str serverhost "subdivisions/" val  "/villages") res)))

 (defn src-sub-sel-tag []
   [:select.form-control {:id :src-sub
@@ -746,16 +744,16 @@
                 (let [dt (getdata json)]
                   (set-key-value :mutations (.-data dt))
                   (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-mutations (get-value! :mutations)])))]
-          (set-key-value :is-searched-results false)
-      (http-get (str serverhost "mutations?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+                  (set-page!  [render-mutations (get-value! :mutations)])))]
+    (set-key-value :is-searched-results false)
+    (http-get-auth (str serverhost "mutations?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))

 (defroute documents-path "/mutations/add" []
   (let [onres (fn[json](
-                        (set-key-value :districts (getdata json))
-                        (set-page! [mutation-add-template])))]
-    (http-get (str serverhost "districts") onres)))
+                       (set-key-value :districts (getdata json))
+                       (set-page! [mutation-add-template])))]
+    (http-get-auth (str serverhost "districts") onres)))

 (defroute documents-path1 "/mutations/update/:id" [id]
   (let [upd-data (first (filter (fn[obj] (=(.-id obj) (.parseInt js/window id))) (get-value! :mutations)))
@@ -766,7 +764,7 @@
         vill-res (fn[json](set-key-value :villages (getdata json)))
         sub-res (fn[json](set-key-value :subdivisions (getdata json)))
         dist-res (fn[json] ((set-key-value :districts (getdata json))
-                            (set-page! [mutation-update-template id upd-data])))]
+                           (set-page! [mutation-update-template id upd-data])))]
     (do
       ;; (http-get (str serverhost "villages/" (.-villageid upd-data))
       ;;           (fn [json]
@@ -780,12 +778,11 @@
       ;; (js/console.log upd-data)
       ;; (js/console.log sub-id)
       ;; (js/console.log )
-      (http-get (str serverhost "districts") dist-res)
+      (http-get-auth (str serverhost "districts") dist-res)
       ;; (http-get (str serverhost "districts" (.-districtid dist-id) "subdivisions") sub-res)
       ;; (http-get (str serverhost "subdivisions" (.-subdivionid sub-id) "villages") vill-res)
-      (http-get (str serverhost "villages") vill-res)
-      (http-get (str serverhost "subdivisions") sub-res)
-      )))
+      (http-get-auth (str serverhost "villages") vill-res)
+      (http-get-auth (str serverhost "subdivisions") sub-res))))

@@ -885,7 +882,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn revenue-tags-template [data-set]
@@ -941,28 +938,29 @@

 (defroute revenue-list "/revenue" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :revenues (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-revenue (get-value! :revenues)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "revenuerecords?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :revenues (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-revenue (get-value! :revenues)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "revenuerecords?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute revenue-add-path "/revenue/add" []
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [revenue-add-template])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [revenue-add-template])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute revenue-upd-path "/revenue/update/:id" [id]
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [revenue-update-template id
-                                    (first (filter (fn[obj]
-                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :revenues)))])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [revenue-update-template id
+                                   (first (filter (fn[obj]
+                                                    (=(.-id obj) (.parseInt js/window id))) (get-value! :revenues)))])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defn revenue-add [event]
   (secretary/dispatch! "/revenue/add"))
@@ -1103,7 +1101,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn khasragirdwani-tags-template [data-set]
@@ -1159,29 +1157,30 @@

 (defroute khasragirdwani-list "/khasragirdwani" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :khasragirdwanis (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-khasragirdwani (get-value! :khasragirdwanis)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "khasragirdwanis?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :khasragirdwanis (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-khasragirdwani (get-value! :khasragirdwanis)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "khasragirdwanis?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute khasragirdwani-add-path "/khasragirdwani/add" []
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [khasragirdwani-add-template])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [khasragirdwani-add-template])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute khasragirdwani-upd-path "/khasragirdwani/update/:id" [id]
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [khasragirdwani-update-template id
-                                    (first (filter (fn[obj]
-                                                     (=(.-id obj) (.parseInt js/window id)))
-                                                   (get-value! :khasragirdwanis)))])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [khasragirdwani-update-template id
+                                   (first (filter (fn[obj]
+                                                    (=(.-id obj) (.parseInt js/window id)))
+                                                  (get-value! :khasragirdwanis)))])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defn khasragirdwani-add [event]
   (secretary/dispatch! "/khasragirdwani/add"))
@@ -1318,7 +1317,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn masavi-tags-template [data-set]
@@ -1373,28 +1372,29 @@

 (defroute masavi-list "/masavi" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :masavis (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-masavi (get-value! :masavis)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "masavis?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :masavis (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-masavi (get-value! :masavis)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "masavis?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute masavi-add-path "/masavi/add" []
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [masavi-add-template])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [masavi-add-template])))]
+    (hthttp-get-auth (str serverhost "villages") onres)))

 (defroute masavi-upd-path "/masavi/update/:id" [id]
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [masavi-update-template id
-                                    (first (filter (fn[obj]
-                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :masavis)))])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [masavi-update-template id
+                                   (first (filter (fn[obj]
+                                                    (=(.-id obj) (.parseInt js/window id))) (get-value! :masavis)))])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defn masavi-add [event]
   (secretary/dispatch! "/masavi/add"))
@@ -1532,7 +1532,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn consolidation-tags-template [data-set]
@@ -1587,28 +1587,29 @@

 (defroute consolidation-list "/consolidation" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :consolidations (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-consolidation (get-value! :consolidations)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "consolidations?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :consolidations (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-consolidation (get-value! :consolidations)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "consolidations?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute consolidation-add-path "/consolidation/add" []
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [consolidation-add-template])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [consolidation-add-template])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute consolidation-upd-path "/consolidation/update/:id" [id]
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [consolidation-update-template id
-                                    (first (filter (fn[obj]
-                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :consolidations)))])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [consolidation-update-template id
+                                   (first (filter (fn[obj]
+                                                    (=(.-id obj) (.parseInt js/window id))) (get-value! :consolidations)))])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defn consolidation-add [event]
   (secretary/dispatch! "/consolidation/add"))
@@ -1745,7 +1746,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn fieldbook-tags-template [data-set]
@@ -1800,28 +1801,29 @@

 (defroute fieldbook-list "/fieldbook" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :fieldbooks (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-fieldbook (get-value! :fieldbooks)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "fieldbooks?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :fieldbooks (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-fieldbook (get-value! :fieldbooks)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "fieldbooks?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute fieldbook-add-path "/fieldbook/add" []
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [fieldbook-add-template])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [fieldbook-add-template])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute fieldbook-upd-path "/fieldbook/update/:id" [id]
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [fieldbook-update-template id
-                                    (first (filter (fn[obj]
-                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :fieldbooks)))])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [fieldbook-update-template id
+                                   (first (filter (fn[obj]
+                                                    (=(.-id obj) (.parseInt js/window id))) (get-value! :fieldbooks)))])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defn fieldbook-add [event]
   (secretary/dispatch! "/fieldbook/add"))
@@ -1985,28 +1987,29 @@

 (defroute misc-list "/misc" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :miscs (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-misc (get-value! :miscs)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "miscs?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :miscs (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-misc (get-value! :miscs)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "miscs?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute misc-add-path "/misc/add" []
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [misc-add-template])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [misc-add-template])))]
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute misc-upd-path "/misc/update/:id" [id]
   (let [onres (fn[json](
-                        (set-key-value :villages (getdata json))
-                        (set-page! [misc-update-template id
-                                    (first (filter (fn[obj]
-                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :miscs)))])))]
-    (http-get (str serverhost "villages") onres)))
+                       (set-key-value :villages (getdata json))
+                       (set-page! [misc-update-template id
+                                   (first (filter (fn[obj]
+                                                    (=(.-id obj) (.parseInt js/window id))) (get-value! :miscs)))])))]
+    (http-get-auth (str serverhost "villages") onres)))

@@ -2123,15 +2126,15 @@
         onres (fn [json] (let [d (first (getdata json))]
                           (set-o2-fields data-set d)))]
     (if (= selval "select") (reset-o2-fields data-set)
-        (http-get (str serverhost "o2registers/"selval"/mutations")
-                  onres))))
+        (http-get-auth (str serverhost "o2registers/"selval"/mutations")
+                   onres))))

 (defn o2-select
   [data-set]
   [:div.form-group
    [:label.col-sm-3.control-label "O2 Number"]
    [:div.col-sm-6
-    [:select.form-control {:id "O2-select" :value (:o2number @data-set) :on-change #(on-o2-change data-set)}
+    [:select.form-control {:id "O2-select" :value "abcd" :on-change #(on-o2-change data-set)}
      (for [d (get-value! :o2mutations)]
        ^{:key d} [:option {:value d} d])]]])

@@ -2187,7 +2190,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn o2register-tags-template [id data-set]
@@ -2246,13 +2249,14 @@

 (defroute o2register-list "/o2register" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :o2registers (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-o2register (get-value! :o2registers)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "o2registers?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :o2registers (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page! [render-o2register (get-value! :o2registers)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "o2registers?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute o2register-add-path "/o2register/add" []
@@ -2261,8 +2265,8 @@
                        (set-page! [o2register-add-template])))
         ono2resp (fn [json] (set-key-value :o2mutations
                                           (clj->js (cons "select" (js->clj (getdata json))))))]
-    (http-get (str serverhost "mutations/o2numbers/search") ono2resp)
-    (http-get (str serverhost "villages") onres)))
+    (http-get-auth (str serverhost "mutations/o2numbers/search") ono2resp)
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute o2register-upd-path "/o2register/update/:id" [id]
   (let [onres (fn[json](
@@ -2272,8 +2276,8 @@
                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :o2registers)))])))
         ono2resp (fn [json] (set-key-value :o2mutations
                                           (clj->js (cons "select" (js->clj (getdata json))))))]
-    (http-get (str serverhost "mutations/o2numbers/search") ono2resp)
-    (http-get (str serverhost "villages") onres)))
+    (http-get-auth (str serverhost "mutations/o2numbers/search") ono2resp)
+    (http-get-auth (str serverhost "villages") onres)))

 (defn o2register-add [event]
   (secretary/dispatch! "/o2register/add"))
@@ -2434,8 +2438,8 @@
         onres (fn [json] (let [d (aget (getdata json) 0)]
                           (set-o4-fields data-set d)))]
     (if (= selval "select") (reset-o4-fields data-set)
-        (http-get (str serverhost "o4registers/"selval"/mutations")
-                  onres))))
+        (http-get-auth (str serverhost "o4registers/"selval"/mutations")
+                   onres))))

 (defn o4-select
@@ -2479,13 +2483,14 @@

 (defroute o4register-list "/o4register" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :o4registers (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-o4register (get-value! :o4registers)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "o4registers?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :o4registers (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-o4register (get-value! :o4registers)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "o4registers?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute o4register-add-path "/o4register/add" []
@@ -2494,13 +2499,13 @@
                        (set-page! [o4register-add-template])))
         ono4resp (fn [json] (set-key-value :o4mutations
                                           (clj->js (cons {:id 0 :o4number "select"} (js->clj (getdata json))))))]
-    (http-get (str serverhost "mutations/o4numbers/search") ono4resp)
-    (http-get (str serverhost "villages") onres)))
+    (http-get-auth (str serverhost "mutations/o4numbers/search") ono4resp)
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute o4register-upd-path "/o4register/update/:id" [id]
   (let [ono4resp (fn [json] (set-key-value :o4mutations
                                           (clj->js (cons {:id 0 :o4number "select"} (js->clj (getdata json))))))]
-    (http-get (str serverhost "mutations/o4numbers/search") ono4resp)
+    (http-get-auth (str serverhost "mutations/o4numbers/search") ono4resp)
     (set-page! [o4register-update-template id
                 (first (filter (fn[obj]
                                  (=(.-id obj) (.parseInt js/window id))) (get-value! :o4registers)))])))
@@ -2576,8 +2581,8 @@
         onres (fn [json] (let [d (first (getdata json))]
                           (set-o6-fields data-set d)))]
     (if (= selval "select") (reset-o6-fields data-set)
-        (http-get (str serverhost "o6registers/"selval"/mutations")
-                  onres))))
+        (http-get-auth (str serverhost "o6registers/"selval"/mutations")
+                       onres))))

 (defn o6-select
@@ -2646,6 +2651,7 @@
 (defn o6register-update-form-onclick [data-set focus]
   (if (= nil (o6register-form-validator @data-set))
     (do (reset! data-set (assoc @data-set :o6number (.-value (.getElementById js/document "O6-select"))))
+        (js/console.log (clj->js @data-set))
         (let [onres (fn[data] (secretary/dispatch! "/o6register"))]
           (http-put (str serverhost "o6registers/" (:id @data-set)) onres (.serialize (Serializer.) (clj->js @data-set)))))
     (reset! focus "on")))
@@ -2661,7 +2667,7 @@
                    (set-key-value :villages dt)))]
     (set-key-value :villages [])
     (when-not ( >  1 (.-length eval))
-      (http-get (str serverhost "villages/search?name=" eval) onresp))))
+      (http-get-auth (str serverhost "villages/search?name=" eval) onresp))))

 (defn o6register-tags-template [data-set]
@@ -2688,6 +2694,7 @@

 (defn o6register-update-template [id dmt]
   (let [update-data (r/atom {:id (int id)
+                             :mutationid (.-mutationid dmt)
                              :o6number (.-o6number dmt)
                              :subdivisionname (.-subdivisionname dmt)
                              :year (.-year dmt)
@@ -2713,13 +2720,14 @@

 (defroute o6register-list "/o6register" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :o6registers (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (set-key-value :page-location  [render-o6register (get-value! :o6registers)])))]
-    (set-key-value :is-searched-results false)
-    (http-get (str serverhost "o6registers?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)))
+  (if (nil? (get-value! :user)) (set-page! [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :o6registers (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page!  [render-o6register (get-value! :o6registers)])))]
+        (set-key-value :is-searched-results false)
+        (http-get-auth (str serverhost "o6registers?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres))))

 (defroute o6register-add-path "/o6register/add" []
@@ -2728,8 +2736,8 @@
                        (set-page! [o6register-add-template])))
         ono6resp (fn [json] (set-key-value :o6mutations
                                           (clj->js (cons {:id 0 :o6number "select"} (js->clj (getdata json))))))]
-    (http-get (str serverhost "mutations/o6numbers/search") ono6resp)
-    (http-get (str serverhost "villages") onres)))
+    (http-get-auth (str serverhost "mutations/o6numbers/search") ono6resp)
+    (http-get-auth (str serverhost "villages") onres)))

 (defroute o6register-upd-path "/o6register/update/:id" [id]
   (let [onres (fn[json](
@@ -2739,8 +2747,8 @@
                                                     (=(.-id obj) (.parseInt js/window id))) (get-value! :o6registers)))])))
         ono6resp (fn [json] (set-key-value :o6mutations
                                           (clj->js (cons {:id 0 :o6number "select"} (js->clj (getdata json))))))]
-    (http-get (str serverhost "mutations/o6numbers/search") ono6resp)
-    (http-get (str serverhost "villages") onres)))
+    (http-get-auth (str serverhost "mutations/o6numbers/search") ono6resp)
+    (http-get-auth (str serverhost "villages") onres)))

 (defn o6register-add [event]
   (secretary/dispatch! "/o6register/add"))
@@ -2800,17 +2808,17 @@

 (defroute home-path "/" []
-  (let [onres (fn [json]
-                (let [dt (getdata json)]
-                  (set-key-value :mutations (.-data dt))
-                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
-                  (js/console.log (.-mutationnumber (.-numbers (first (get-value! :mutations)))))
-                  (set-key-value :page-location  [render-mutations (get-value! :mutations)])))
-        dist-res (fn[json] (set-key-value :districts (getdata json)))]
-    (do
-      (set-key-value :is-searched-results false)
-      (http-get (str serverhost "mutations?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)
-      (http-get (str serverhost "districts") dist-res))))
+  (if (nil? (get-value! :user)) (set-key-value :page-location [login])
+      (let [onres (fn [json]
+                    (let [dt (getdata json)]
+                      (set-key-value :mutations (.-data dt))
+                      (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
+                      (set-page! [render-mutations (get-value! :mutations)])))
+            dist-res (fn[json] (set-key-value :districts (getdata json)))]
+        (do
+          (set-key-value :is-searched-results false)
+          (http-get-auth (str serverhost "mutations?pageIndex="(dec (get-value! :current-page))"&pageSize=10") onres)
+          (http-get-auth (str serverhost "districts") dist-res)))))

 (defroute "*" []
   (js/alert "<h1>Not Found Page</h1>"))


Add "Success" case to all-success status check

--- src/cljs/org/broadinstitute/firecloud_ui/page/workspace/monitor/common.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/workspace/monitor/common.cljs
@@ -6,7 +6,7 @@

 (defn all-success? [submission]
-  (and (every? #(= "Succeeded" (% "status")) (submission "workflows"))
+  (and (every? #(or (= "Succeeded" (% "status")) (= "Success" (% "status"))) (submission "workflows"))
     (zero? (count (submission "notstarted")))))


CMR-5750 More test fixes.

CMR-5750 More test fixes.

--- system-int-test/test/cmr/system_int_test/ingest/granule_validation_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/granule_validation_test.clj
@@ -56,8 +56,8 @@

 (deftest validation-endpoint-test
   (let [invalid-granule-xml "<Granule>invalid xml</Granule>"
-        expected-errors ["Line 1 - cvc-complex-type.2.3: Element 'Granule' cannot have character [children], because the type's content type is element-only."
-                         "Line 1 - cvc-complex-type.2.4.b: The content of element 'Granule' is not complete. One of '{GranuleUR}' is expected."]]
+        expected-errors ["Exception while parsing invalid XML: Line 1 - cvc-complex-type.2.3: Element 'Granule' cannot have character [children], because the type's content type is element-only."
+                         "Exception while parsing invalid XML: Line 1 - cvc-complex-type.2.4.b: The content of element 'Granule' is not complete. One of '{GranuleUR}' is expected."]]

     (testing "granule with end date slightly in the future and collection with
              EndsAtPresentFlag=true and end date in the far future (see CMR-1351)"
@@ -94,7 +94,7 @@
           (assert-validation-errors
             400
             [(msg/invalid-parent-collection-for-validation
-               "Line 1 - cvc-elt.1: Cannot find the declaration of element 'Granule'.")]
+               "Exception while parsing invalid XML: Line 1 - cvc-elt.1: Cannot find the declaration of element 'Granule'.")]
             (d/item->concept (dg/granule-with-umm-spec-collection collection (:concept-id collection)))
             (assoc coll-concept :metadata invalid-granule-xml)))


Added exclusion of dictybase id's to ontology_id_denotes_concept_gen_obo rule

Although the DictyBase URIs are prefixed with the OBO namespace, they
are handled by a separate rule, so are excluded from this general OBO
rule.

--- resources/rules/pre_identifier_merge/step_a_ontology_to_ice/step_b/ontology_id_denotes_concept_gen_obo.clj
+++ resources/rules/pre_identifier_merge/step_a_ontology_to_ice/step_b/ontology_id_denotes_concept_gen_obo.clj
@@ -23,5 +23,7 @@
                   filter (contains (str(?ontology_concept), 'http://purl.obolibrary.org/obo/'))
                   # exclude ICE world concepts (IAO, CCP extension ontology, OA ontology)
                   filter (!contains (str(?ontology_concept), 'obo/IAO_'))
+                  # exclude DictyBase IDs. They use the OBO namespace but are handled by a separate rule
+                  filter (!contains (str(?ontology_concept), 'http://ccp.ucdenver.edu/obo/ext/dictyBase'))
                   }"
   }


Formatting

Formatting

--- test/onyx/log/greedy_multi_job_test.clj
+++ test/onyx/log/greedy_multi_job_test.clj
@@ -95,10 +95,9 @@
 (def replica-1
   (playback-log (:log env) (extensions/subscribe-to-log (:log env) ch) ch 2000))

-(let [])
 (fact "5 peers were allocated to job 1, task A, 5 peers were allocated to job 1, task B"
       (get-counts replica-1 [j1 j2]) => (fn [x] (or (= x [[5 5] [0 0]])
-                                                   (= x [[5 5] []]))))
+                                                    (= x [[5 5] []]))))

 (>!! a-chan :done)
 (close! a-chan)
@@ -108,7 +107,7 @@

 (fact "5 peers were reallocated to job 2, task C, 5 peers were reallocated to job 2, task D"
       (get-counts replica-2 [j1 j2]) => (fn [x] (or (= x [[0 0] [5 5]])
-                                                   (= x [[] [5 5]]))))
+                                                    (= x [[] [5 5]]))))

 (>!! c-chan :done)
 (close! c-chan)
@@ -118,7 +117,7 @@

 (fact "No peers are executing any tasks" (get-counts replica-3 [j1 j2])
       => (fn [x] (or (= x [[0 0] [0 0]])
-                    (= x [[] []]))))
+                     (= x [[] []]))))

 (close! b-chan)
 (close! d-chan)


Just build for host platform in build_images.sh

It's way too hard to do anything multi-platform unless you're just pushing to a registry. This is mostly for building and testing images locally, so this is all we need.

--- src/docker_clojure/core.clj
+++ src/docker_clojure/core.clj
@@ -147,21 +147,8 @@
         {:keys [dockerfile build-dir]}
         (generate-dockerfile! installer-hashes variant)

-        ;; alpine won't build for arm64.
-        ;; boot crashes under qemu (i.e. non-host arch) but does anyone even
-        ;; use boot anymore?
-        platform-arg (cond
-                       (str/includes? image-tag "alpine")
-                       "--platform=linux/amd64"
-
-                       (str/includes? image-tag "boot")
-                       nil ; default to host arch
-
-                       :else
-                       "--platform=linux/amd64,linux/arm64")
-        build-cmd (remove nil? ["docker" "buildx" "build" "--no-cache"
-                                platform-arg "--output=type=tar,dest=images.tar"
-                                "-t" image-tag "-f" dockerfile "."])]
+        build-cmd (remove nil? ["docker" "build" "--no-cache" "-t" image-tag
+                                "-f" dockerfile "."])]
     (apply println "Running" build-cmd)
     (let [{:keys [out err exit]}
           (with-sh-dir build-dir (apply sh build-cmd))]


Use common redis options.

Use common redis options.

--- src/dragon/config/redis.clj
+++ src/dragon/config/redis.clj
@@ -41,17 +41,18 @@
          :command "redis-server"))

 (def ^:private start-args-docker
-  [(:executable start-docker)
-   "run"
-   "-d"
-   "-v" (format "%s/%s:%s" (:home start-docker)
-                           (:host-data-dir base-config-docker)
-                           (:guest-data-dir base-config-docker))
-   "--cidfile" (:container-id-file base-config-docker)
-   "-p" (format "%s:%s" (:port base-config-docker) (:port base-config-docker))
-   (:image-name base-config-docker)
-   (:command start-docker)
-   "--appendonly" "yes"])
+  (concat
+    [(:executable start-docker)
+     "run"
+     "-d"
+     "-v" (format "%s/%s:%s" (:home start-docker)
+                             (:host-data-dir base-config-docker)
+                             (:guest-data-dir base-config-docker))
+     "--cidfile" (:container-id-file base-config-docker)
+     "-p" (format "%s:%s" (:port base-config-docker) (:port base-config-docker))
+     (:image-name base-config-docker)
+     (:command start-docker)]
+     redis-options))

 (def config-docker
   (assoc config


Fix latency tracking.

Fix latency tracking.

--- src/onyx_benchmark/peer.clj
+++ src/onyx_benchmark/peer.clj
@@ -56,11 +56,11 @@
                 start (System/currentTimeMillis)
                 _ (reset! retry-counter 0)
                 latencies (:latencies latency)
-                latency-00 (get latency 0.0)
-                latency-05 (get latency 0.5)
-                latency-095 (get latency 0.95)
-                latency-099 (get latency 0.99)
-                latency-0999 (get latency 0.999)]
+                latency-00 (get latencies 0.0)
+                latency-05 (get latencies 0.5)
+                latency-095 (get latencies 0.95)
+                latency-099 (get latencies 0.99)
+                latency-0999 (get latencies 0.999)]
             (info "-> " throughput ", retries: " retry-cnt ", latency " latency " <-")
             (info "-> " latency-00 latency-05 latency-095 latency-099 latency-0999)
             (r/send-event client {:service "onyx-retry" :state "ok" :metric retry-cnt :tags ["benchmark"]})


load_all.clj: updated to match current job structure

--- src/org/altlaw/load_all.clj
+++ src/org/altlaw/load_all.clj
@@ -1,22 +1,11 @@
 (ns org.altlaw.load-all
   (:require
-;;    org.altlaw.jobs.distindex
-;;    org.altlaw.jobs.genhtml
-;;    org.altlaw.jobs.getindexes
-;;    org.altlaw.jobs.graph
-;;    org.altlaw.jobs.graph-map
-;;    org.altlaw.jobs.link.linkincites
-;;    org.altlaw.jobs.link.linkincites-mapred
-;;    org.altlaw.jobs.link.linkoutcites
-;;    org.altlaw.jobs.link.linkoutcites-mapred
-;;    org.altlaw.jobs.link.mergedocs
-;;    org.altlaw.jobs.link.mergedocs-mapred
-;;    org.altlaw.jobs.procfiles.altcrawl
-   org.altlaw.jobs.procfiles.ohm1
-;;    org.altlaw.jobs.procfiles.ohm1-map
-   org.altlaw.jobs.procfiles.profed
-;;    org.altlaw.jobs.procfiles.profed-map
-;;    org.altlaw.jobs.uploadpages
+   org.altlaw.jobs.pre.ohm1
+   org.altlaw.jobs.pre.profed
+   org.altlaw.jobs.analyze.graph
+   org.altlaw.jobs.analyze.cite_fields
+   org.altlaw.jobs.analyze.merge
+   org.altlaw.jobs.post.distindex

    org.altlaw.test.run
    org.altlaw.test.www


Correct docstring

Correct docstring

--- src/overtone/libs/event.clj
+++ src/overtone/libs/event.clj
@@ -146,16 +146,16 @@
   (handlers/add-one-shot-sync-handler! handler-pool event-type key handler))

 (defn remove-handler
-  "Remove an event handler previously registered to handle events of
-  event-type.  Removes both sync and async handlers with a given key
-  for a particular event type.
+  "Remove an event handler previously registered with specified
+   key. Removes both sync and async handlers with a given key for a
+   particular event type.

   (defn my-foo-handler [event] (do-stuff (:val event))

   (on-event :foo my-foo-handler ::bar-key)
   (event :foo :val 200) ; my-foo-handler gets called with:
                         ; {:event-type :foo :val 200}
-  (remove-handler :foo ::bar-key)
+  (remove-handler ::bar-key)
   (event :foo :val 200) ; my-foo-handler no longer called"
   [key]
   (let [[old new] (swap-returning-prev! lossy-workers* dissoc key)]


use JS .split instead of clojure split to respect empty lines

--- src/parinfer/formatter.cljs
+++ src/parinfer/formatter.cljs
@@ -1,6 +1,6 @@
 (ns parinfer.formatter
   (:require
-    [clojure.string :refer [split-lines join]]))
+    [clojure.string :refer [join]]))

 (def matching-delim
   {"{" "}", "}" "{"
@@ -373,7 +373,8 @@
   ([text] (process-text initial-state text))
   ([state text]
    (let [state (merge initial-state state)
-         state (reduce process-line state (split-lines text))
+         lines (.split text "\n") ;; different from clojure.string/split (respects empty lines)
+         state (reduce process-line state lines)
          stack (:stack state)
          close? (and (seq stack)
                      (not (in-str? stack)))


tolerate the notifications api missing

tolerate the notifications api missing

as is the case on iOS safari

--- src/pomo/notifications.cljs
+++ src/pomo/notifications.cljs
@@ -1,8 +1,14 @@
 (ns pomo.notifications)

-(defonce notifications (atom (= "granted" (.-permission js/Notification))))
+(defn get-permission []
+  (or (if-let [Notification (.-Notification js/window)]
+        (.-permission Notification)))
+  "denied")

-(when (= "default" (.-permission js/Notification))
+(defonce notifications
+  (atom (= "granted" (get-permission)))
+
+(when (= "default" (get-permission))
   "default" (.requestPermission js/Notification #(reset! notifications (= % "granted"))))

 (defn notify


Update controller.clj

Update controller.clj

--- src/formula1/controller.clj
+++ src/formula1/controller.clj
@@ -16,6 +16,9 @@

 (defn drivers []
   (render-template "drivers" {:drivers (drivers/all)}))
+
+(defn index []
+  (render-template "index" {}))

 (defn new []
   (render-template "new_driver" {:teams (teams/all)


CMR-3687: Fixed dependency problem

CMR-3687: Fixed dependency problem

--- system-int-test/test/cmr/system_int_test/search/tagging/enable_disable_test.clj
+++ system-int-test/test/cmr/system_int_test/search/tagging/enable_disable_test.clj
@@ -4,7 +4,6 @@
     [clojure.test :refer :all]
     [clojure.string :as str]
     [cmr.common.util :refer [are2] :as util]
-    [cmr.metadata-db.int-test.utility :as mdb-util]
     [cmr.system-int-test.utils.ingest-util :as ingest]
     [cmr.system-int-test.utils.search-util :as search]
     [cmr.system-int-test.utils.index-util :as index]
@@ -88,7 +87,11 @@
       (is (= 200 (:status (tags/delete-tag token tag3-key)))))))

 (deftest tag-association-test
-  (let [tag-collection (mdb-util/create-and-save-collection "PROV1" 1)
+  (let [tag-collection (ingest/ingest-concept (dc/collection-concept {:native-id "native1"
+                                                                      :entry-title "coll1"
+                                                                      :entry-id "coll1"
+                                                                      :version-id "V1"
+                                                                      :short-name "short1"}))
         tag1-key "tag1"
         tag1 (tags/make-tag {:tag-key tag1-key})
         tag2-key "tag2"


Fix - Impossible to receive multipart/form-data with multiple parts having the same name

Fix for issue #277

Now accumulate parts with same name in a vector.

--- ext/multipart/src/yada/multipart.clj
+++ ext/multipart/src/yada/multipart.clj
@@ -646,9 +646,16 @@
          ;; Content-Disposition headers.
          (let [schemas (get-in ctx [:resource :methods (:method ctx) :parameters])
                parts-by-name (reduce
-                              (fn [acc part] (cond-> acc
-                                               (= (:type part) :part)
-                                               (assoc (get-in part [:content-disposition :params "name"]) part)))
+                              (fn [acc part]
+                                (let [name (get-in part [:content-disposition :params "name"])
+                                      [_ already-occupied?] (find acc name)
+                                      result (case [(= (:type part) :part) (not (nil? already-occupied?)) (vector? already-occupied?)]
+                                               [true true true]  (update acc name conj part)
+                                               [true true false] (assoc acc name [already-occupied? part])
+                                               [true false false]  (assoc acc name part)
+                                               [false false false] acc
+                                               )]
+                                  result))
                               {} parts)]

            (cond->


compiles, with serious namespace warnings


PLD: fix numbering

PLD: fix numbering

--- src/hatti/views/photos.cljs
+++ src/hatti/views/photos.cljs
@@ -27,7 +27,7 @@
              "fit-in"
              (str edge-px "x" edge-px)
              "smart"
-             (format "filters:fill(000)" fill-color)
+             "filters:fill(000)"
              image-url)))

 (defn- make-url
@@ -124,7 +124,7 @@
    directly to the submission."
   [data photo-columns]
   (let [data-with-attachments (keep #(extract-images % photo-columns) data)
-        total (reduce #(+ %1 (count (get %2 constants/_attachments)))
+        total (reduce #(+ %1 (count (get %2 :attachments)))
                       0 data-with-attachments)]
     (loop [data-left data-with-attachments
            result []


[#6956] fix possible `message` and `user-status` duplicates

There is a tiny chance that without this fix some users which had message
duplicates because of issues with `message-id` calculation **BEFORE** `0.9.31`
still have duplicates in their DB and migrations will not pass without
this change. It only checks if the message with a new `message-id` has been
added and removes duplicate. The same way it removes duplicates from
`user-status` entity.

--- src/status_im/data_store/realm/schemas/account/migrations.cljs
+++ src/status_im/data_store/realm/schemas/account/migrations.cljs
@@ -266,9 +266,15 @@
             message-id      (transport.utils/message-id from raw-payload)
             raw-payload-hash (transport.utils/sha3 raw-payload)]
         (vswap! old-ids->new-ids assoc prev-message-id message-id)
-        (aset message "message-id" message-id)
-        (aset message "raw-payload-hash" raw-payload-hash)
-        (aset message "old-message-id" old-message-id)))
+        (if (.objectForPrimaryKey
+             new-realm
+             "message"
+             message-id)
+          (.delete new-realm message)
+          (do
+            (aset message "message-id" message-id)
+            (aset message "raw-payload-hash" raw-payload-hash)
+            (aset message "old-message-id" old-message-id)))))

     (dotimes [i (.-length user-statuses)]
       (let [user-status (aget user-statuses i)
@@ -276,6 +282,11 @@
             new-message-id (get @old-ids->new-ids message-id)
             public-key     (aget user-status "public-key")
             new-status-id (str new-message-id "-" public-key)]
-        (when (contains? @old-ids->new-ids message-id)
-          (aset user-status "status-id" new-status-id)
-          (aset user-status "message-id" new-message-id))))))
+        (if (.objectForPrimaryKey
+             new-realm
+             "user-status"
+             new-status-id)
+          (.delete new-realm user-status)
+          (when (contains? @old-ids->new-ids message-id)
+            (aset user-status "status-id" new-status-id)
+            (aset user-status "message-id" new-message-id)))))))


Add tighter constraints to foil shapes in rand-indivdual and new-individual

--- src/hydrofoil/evolution.clj
+++ src/hydrofoil/evolution.clj
@@ -29,9 +29,9 @@
         p-exp-factor 1
         t-exp-factor 10
         ;;; the numerical values of the upper limits
-        m-upper-bound (upper-bound-check (+ m-exp-factor (parent :max-camber)) 100)
-        p-upper-bound (upper-bound-check (+ p-exp-factor (parent :positon-camber)) 10)
-        t-upper-bound (upper-bound-check (+ t-exp-factor (parent :thickness)) 100)
+        m-upper-bound (upper-bound-check (+ m-exp-factor (parent :max-camber)) 9.5)
+        p-upper-bound (upper-bound-check (+ p-exp-factor (parent :positon-camber)) 9)
+        t-upper-bound (upper-bound-check (+ t-exp-factor (parent :thickness)) 40)
         ;;; the numerical value of the lower limits
         m-lower-bound (lower-bound-check (- (parent :max-camber) m-exp-factor) 0)
         ;p-lower-bound (lower-bound-check (- (parent :positon-camber) p-exp-factor) 0)
@@ -47,9 +47,9 @@

 (defn rand-individual
   []
-  (let [t-value (rand-double 0 100)]
-    (NACA-design (rand-double 0 100)
-                 (rand-double (p-min t-value) 10)
+  (let [t-value (rand-double 0 40)]
+    (NACA-design (rand-double 0 9.5)
+                 (rand-double (p-min t-value) 9)
                  t-value)))


deal with auto-shutter properly

deal with auto-shutter properly

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

--- clojure/acq_engine.clj
+++ clojure/acq_engine.clj
@@ -97,6 +97,7 @@
 (def start-time 0)
 (declare interrupt-requests)
 (declare z-corrections)
+(declare init-auto-shutter)

 ;; metadata

@@ -186,16 +187,20 @@
   (.. gui getAutofocusManager getDevice fullFocus))

 (defn snap-image [open-before close-after]
+  (. mmc setAutoShutter false)
   (if open-before
     (. mmc setShutterOpen true)
     (. mmc waitForDevice (. mmc getShutterDevice)))
   (. mmc snapImage)
   (if close-after
     (. mmc setShutterOpen false))
-    (. mmc waitForDevice (. mmc getShutterDevice)))
+    (. mmc waitForDevice (. mmc getShutterDevice))
+  (. mmc setAutoShutter init-auto-shutter))

 (defn init-burst [length]
-  (. mmc startSequenceAcquisition length 0 false))
+  (. mmc setAutoShutter init-auto-shutter)
+  (. mmc startSequenceAcquisition length 0 false)
+  (. mmc setAutoShutter false))

 (defn expose [event]
   (do (condp = (:task event)
@@ -265,10 +270,12 @@
   (binding [interrupt-requests (ref {:pause false :stop false})
             z-corrections (ref nil)
             last-wake-time (atom (clock-ms))
-            start-time (clock-ms)]
+            start-time (clock-ms)
+            init-auto-shutter (. mmc getAutoShutter)]
     (let [acq-seq (generate-acq-sequence settings)]
        (def acq-sequence acq-seq)
-       (execute (mapcat #(make-event-fns % out-queue) acq-seq)))))
+       (execute (mapcat #(make-event-fns % out-queue) acq-seq))
+       (. mmc setAutoShutter init-auto-shutter))))

 (defn convert-settings [^SequenceSettings settings]
   (-> settings


Rename some webui variables to distinguish between the way query window is managed.

--- metlog-vault/src-client/metlog_client/metlog.cljs
+++ metlog-vault/src-client/metlog_client/metlog.cljs
@@ -9,7 +9,7 @@
             [cljs-time.coerce :as time-coerce]
             [metlog-client.tsplot :as tsplot]))

-(defonce query-window-secs (reagent/atom (* 3600 24)))
+(defonce query-window (reagent/atom (* 3600 24)))

 (def dashboard-state (reagent/atom {:series [] :text ""}))

@@ -51,7 +51,7 @@
     channel))

 (defn range-ending-at [ end-t ]
-  (let [begin-t (time/minus end-t (time/seconds @query-window-secs))]
+  (let [begin-t (time/minus end-t (time/seconds @query-window))]
     {:begin-t (time-coerce/to-long begin-t)
      :end-t (time-coerce/to-long end-t)}))

@@ -101,21 +101,19 @@
                     {:width (.-clientWidth node)
                      :height (.-clientHeight node)})]])})))

-(defn series-pane [ series-name query-window-secs ]
+(defn series-pane [ series-name query-window ]
   [:div.series-pane
    [:div.series-pane-header
     [:span.series-name series-name]]
-   [series-tsplot series-name query-window-secs]])
+   [series-tsplot series-name query-window]])

 (defn series-list [ ]
-  (let [ query-window-secs @query-window-secs]
-    [:div
-     (for [ series (:series @dashboard-state) ]
-       ^{ :key series } [series-pane series query-window-secs])]))
+  [:div
+   (for [ series (:series @dashboard-state) ]
+     ^{ :key series } [series-pane series @query-window])])

 (defn end-edit [ text state ]
-  (let [ qws (js/parseInt text) ]
-    (reset! query-window-secs qws)))
+  (reset! query-window (js/parseInt text)))

 (defn input-field [ initial-text on-enter ]
   (let [ state (reagent/atom { :text initial-text }) ]
@@ -129,7 +127,7 @@
   [:div.header
    [:span#app-name
     "Metlog"]
-   [input-field @query-window-secs #(end-edit % dashboard-state)]])
+   [input-field @query-window #(end-edit % dashboard-state)]])

 (defn dashboard [ ]
   [:div
@@ -148,3 +146,4 @@
     (swap! dashboard-state assoc :series (<! (<<< fetch-series-names)))))

 (run)
+


Comment did not make sense to me. Now it does.

--- src/midje/midje_forms/recognizing.clj
+++ src/midje/midje_forms/recognizing.clj
@@ -37,8 +37,8 @@
   (and (zip/branch? loc)
        (namespacey-match '(expect) (zip/down loc))))

-;; A problem with not using namespacey-match for this is that
-;; it will then match quoted Midje forms in a zillion tests.
+;; The reason for not using namespacey-match for this is that
+;; it would then match quoted Midje forms in a zillion tests.
 (defn loc-is-start-of-check-sequence? [loc]
   (and (zip/right loc)
        (namespacey-match expect-arrows (zip/right loc))))


Add some passing tests.

Add some passing tests.

--- test/beicon/core_spec.cljs
+++ test/beicon/core_spec.cljs
@@ -5,432 +5,206 @@

 ;; --- helpers for testing

-;; (def no-op (fn [& args]))
-
-;; (defmacro with-timeout
-;;   [ms & body]
-;;   `(js/setTimeout
-;;     (fn []
-;;       (do
-;;         ~@body))
-;;     ~ms))
-
-;; (defn drain!
-;;   ([obs cb]
-;;    (drain! obs cb #(println "Error: " %)))
-;;   ([obs cb errb]
-;;    (let [values (volatile! [])]
-;;      (s/on-value obs #(vswap! values conj %))
-;;      (s/on-error obs #(errb %))
-;;      (s/on-end obs #(cb @values)))))
-
-;; (defn tick
-;;   [interval]
-;;   (s/from-poll interval #(s/next (.getTime (js/Date.)))))
-
-;; ---
+(def no-op (fn [& args]))
+
+(defmacro with-timeout
+  [ms & body]
+  `(js/setTimeout
+    (fn []
+      (do
+        ~@body))
+    ~ms))
+
+(defn drain!
+  ([obs cb]
+   (drain! obs cb #(println "Error: " %)))
+  ([obs cb errb]
+   (let [values (volatile! [])]
+     (s/on-value obs #(vswap! values conj %))
+     (s/on-error obs #(errb %))
+     (s/on-end obs #(cb @values)))))
+
+(defn tick
+  [interval]
+  (s/from-poll interval #(.getTime (js/Date.))))

 ;; event stream

-;; - TODO: startWith
-
-;; (t/deftest event-stream-from-vector
-;;   (t/async done
-;;     (let [coll [1 2 3]
-;;           s (s/from-coll coll)]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % coll)))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-from-set
-;;   (t/async done
-;;     (let [coll #{1 2 3}
-;;           s (s/from-coll coll)]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= (set %) coll)))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-from-map
-;;   (t/async done
-;;     (let [coll #{:a "a" :b "b"}
-;;           s (s/from-coll coll)]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= (set %) #{:a "a" :b "b"})))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-from-callback
-;;   (t/async done
-;;     (let [s (s/from-callback (fn [sink]
-;;                                (with-timeout 10
-;;                                  (sink 1)
-;;                                  no-op)))]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [1])))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-from-binder
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (with-timeout 10
-;;                                (sink (s/next 1))
-;;                                (sink (s/next 2))
-;;                                (sink (s/next 3))
-;;                                (sink (s/end)))
-;;                              no-op))]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [1 2 3])))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-errors-from-binder
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (with-timeout 10
-;;                                (sink (s/next 1))
-;;                                (sink (s/error "oh noes"))
-;;                                (sink (s/end)))
-;;                              no-op))]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [1]))
-;;                      #(t/is (= % "oh noes")))
-;;              (s/on-end s done))))
-
-;; (t/deftest event-stream-no-more-from-binder
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (with-timeout 10
-;;                                (sink (s/next 1))
-;;                                (sink s/no-more)
-;;                                (sink (s/end)))
-;;                              no-op))]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [1 s/no-more])))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-more-from-binder
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (with-timeout 10
-;;                                (sink (s/next 1))
-;;                                (sink s/more)
-;;                                (with-timeout 3
-;;                                  (sink 2)
-;;                                  (sink (s/end))))
-;;                              no-op))]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [1 s/more 2])))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-repeat
-;;   (t/async done
-;;     (let [s (s/repeat (fn [i]
-;;                         (when (< i 3)
-;;                           (s/once i))))]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [0 1 2])))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-once
-;;   (t/async done
-;;     (let [s (s/once 1)]
-;;       (t/is (s/event-stream? s))
-;;       (drain! s #(t/is (= % [1])))
-;;       (s/on-end s done))))
-
-;; (t/deftest event-stream-never
-;;   (t/async done
-;;     (let [n (s/never)]
-;;       (s/on-end n done))))
-
-;; (t/deftest event-stream-interval
+(t/deftest observable-from-vector
+  (t/async done
+    (let [coll [1 2 3]
+          s (s/from-coll coll)]
+      (t/is (s/observable? s))
+      (drain! s #(t/is (= % coll)))
+      (s/on-end s done))))
+
+(t/deftest observable-from-set
+  (t/async done
+    (let [coll #{1 2 3}
+          s (s/from-coll coll)]
+      (t/is (s/observable? s))
+      (drain! s #(t/is (= (set %) coll)))
+      (s/on-end s done))))
+
+(t/deftest observable-from-callback
+  (t/async done
+    (let [s (s/from-callback (fn [sink]
+                               (with-timeout 10
+                                 (sink 1)
+                                 nil)))]
+      (t/is (s/observable? s))
+      (drain! s #(t/is (= % [1])))
+      (s/on-end s done))))
+
+(t/deftest observable-from-create
+  (t/async done
+    (let [s (s/create (fn [sink]
+                        (with-timeout 10
+                          (sink 1)
+                          (sink 2)
+                          (sink 3)
+                          (sink nil))))]
+      (t/is (s/observable? s))
+      (drain! s #(t/is (= % [1 2 3])))
+      (s/on-end s done))))
+
+(t/deftest observable-errors-from-binder
+  (t/async done
+    (let [s (s/create (fn [sink]
+                        (with-timeout 10
+                          (sink 1)
+                          (sink (ex-info "oh noes" {})))))]
+      (t/is (s/observable? s))
+      (drain! s
+              #(t/is (= % [1]))
+              #(t/is (= (ex-message %) "oh noes")))
+      (s/on-error s done))))
+
+(t/deftest observable-repeat
+  (t/async done
+    (let [s (s/repeat 1 2)]
+      (t/is (s/observable? s))
+      (drain! s #(t/is (= % [1 1])))
+      (s/on-end s done))))
+
+(t/deftest observable-once
+  (t/async done
+    (let [s (s/once 1)]
+      (t/is (s/observable? s))
+      (drain! s #(t/is (= % [1])))
+      (s/on-end s done))))
+
+(t/deftest observable-never
+  (t/async done
+    (let [n (s/never)]
+      (s/on-end n done))))
+
+;; (t/deftest observable-interval
 ;;   (t/async done
 ;;     (let [i (s/interval 10)
 ;;           sample (s/take 4 i)]
 ;;       (drain! sample #(t/is (apply = %)))
 ;;       (s/on-end sample done))))

-;; (t/deftest event-stream-later
+;; (t/deftest observable-later
 ;;   (t/async done
 ;;     (let [s (s/later 10 42)]
 ;;       (drain! s #(t/is (= % [42])))
 ;;       (s/on-end s done))))

-;; (t/deftest event-stream-sequentially
+;; (t/deftest observable-sequentially
 ;;   (t/async done
 ;;     (let [s (s/sequentially 10 [1 2 3])
 ;;           sample (s/take 6 s)]
 ;;       (drain! sample #(t/is (= % [1 2 3])))
 ;;       (s/on-end sample done))))

-;; (t/deftest event-stream-repeatedly
+;; (t/deftest observable-repeatedly
 ;;   (t/async done
 ;;     (let [s (s/repeatedly 10 [1 2 3])
 ;;           sample (s/take 6 s)]
 ;;       (drain! sample #(t/is (= % [1 2 3 1 2 3])))
 ;;       (s/on-end sample done))))

-;; (t/deftest event-stream-on-value
-;;   (t/async done
-;;     (let [s (s/from-coll [1 2 3])
-;;           vacc (volatile! [])]
-;;       (s/on-value s #(vswap! vacc conj %))
-;;       (s/on-end s #(do (t/is (= @vacc [1 2 3]))
-;;                        (done))))))
-
-;; (t/deftest event-stream-on-error
-;;   (t/async done
-;;     (let [s (s/from-coll [1 2 3 (s/error :oh) (s/error :noes)])
-;;           vacc (volatile! [])]
-;;       (s/on-error s #(vswap! vacc conj %))
-;;       (s/on-end s #(do (t/is (= @vacc [:oh :noes]))
-;;                        (done))))))
-
-;; (t/deftest event-stream-initial
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (sink (s/initial 1))))]
-;;       (s/subscribe s (fn [ev]
-;;                        (t/is (s/initial? ev))
-;;                        (t/is (= @ev 1))
-;;                        (done))))))
-
-;; (t/deftest event-stream-next
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (sink (s/next 1))))]
-;;       (s/subscribe s (fn [ev]
-;;                        (t/is (s/next? ev))
-;;                        (t/is (= @ev 1))
-;;                        (done))))))
-
-;; (t/deftest event-stream-error
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (sink (s/error :oh-no))))]
-;;       (s/subscribe s (fn [ev]
-;;                        (t/is (s/error? ev))
-;;                        (t/is (= @ev :oh-no))
-;;                        (done))))))
-
-;; (t/deftest event-stream-end
-;;   (t/async done
-;;     (let [s (s/from-binder (fn [sink]
-;;                              (sink (s/end))
-;;                              no-op))]
-;;       (s/subscribe s (fn [ev]
-;;                        (t/is (s/end? ev))
-;;                        (done))))))
-
-;; (t/deftest event-stream-concat
-;;   (t/async done
-;;     (let [b1 (s/bus)
-;;           b2 (s/bus)
-;;           s1 (s/to-event-stream b1)
-;;           s2 (s/to-event-stream b2)
-;;           cs (s/concat s1 s2)]
-;;       (drain! cs #(t/is (= % [1 2 3 4])))
-;;       (s/on-end cs done)
-;;       (s/push! b1 1)
-;;       (s/push! b1 2)
-;;       (s/push! b2 :discarded)
-;;       (s/push! b2 :discarded)
-;;       (s/end! b1)
-;;       (s/push! b2 3)
-;;       (s/push! b2 4)
-;;       (s/end! b2))))
-
-;; (t/deftest event-stream-merge
-;;   (t/async done
-;;     (let [s1 (s/sequentially 10 [1 2 3])
-;;           s2 (s/sequentially 10 [:1 :2 :3])
-;;           ms (s/merge s1 s2)]
-;;       (drain! ms #(t/is (= % [1 :1 2 :2 3 :3])))
-;;       (s/on-end ms done))))
-
-;; (t/deftest event-stream-hold-when
-;;   (t/async done
-;;     (let [b (s/bus)
-;;           s (s/to-event-stream b)
-;;           pb (s/bus)
-;;           valve (s/to-property pb)
-;;           hs (s/hold-when s valve)]
-;;       (drain! hs #(t/is (= % [1 2 3])))
-;;       (s/on-end hs done)
-;;       ;; open valve
-;;       (s/push! pb false)
-;;       ;; push values onto stream
-;;       (s/push! b 1)
-;;       (s/push! b 2)
-;;       ;; close valve
-;;       (s/push! pb true)
-;;       ;; push some more
-;;       (s/push! b 3)
-;;       ;; reopen valve
-;;       (s/push! pb false)
-;;       ;; end
-;;       (s/end! b)
-;;       (s/end! pb))))
-
-;; (t/deftest event-stream-skip-while
-;;   (t/async done
-;;     (let [nums (s/from-coll [1 1 1 2 3 4 5])
-;;           sample (s/skip-while nums odd?)]
-;;       (drain! sample #(t/is (= % [2 3 4 5])))
-;;       (s/on-end sample done))))
-
-;; (t/deftest event-stream-skip-until
-;;   (t/async done
-;;     (let [b (s/bus)
-;;           s (s/to-event-stream b)
-;;           bv (s/bus)
-;;           switch (s/to-event-stream bv)
-;;           sample (s/skip-until s switch)]
-;;       (drain! sample #(t/is (= % [3 4 5])))
-;;       (s/on-end sample done)
-;;       ;; push values onto stream
-;;       (s/push! b 1)
-;;       (s/push! b 2)
-;;       ;; open switch
-;;       (s/push! bv :value)
-;;       ;; push some more
-;;       (s/push! b 3)
-;;       (s/push! b 4)
-;;       (s/push! b 5)
-;;       ;; end
-;;       (s/end! b)
-;;       (s/end! bv))))
+(t/deftest observable-on-value
+  (t/async done
+    (let [s (s/from-coll [1 2 3])
+          vacc (volatile! [])]
+      (s/on-value s #(vswap! vacc conj %))
+      (s/on-end s #(do (t/is (= @vacc [1 2 3]))
+                       (done))))))
+
+(t/deftest observable-concat
+  (t/async done
+    (let [s1 (s/bus)
+          s2 (s/bus)
+          cs (s/concat s1 s2)]
+      (drain! cs #(t/is (= % [1 2 3 4])))
+      (s/on-end cs done)
+      (s/push! s1 1)
+      (s/push! s1 2)
+      (s/push! s2 :discarded)
+      (s/push! s2 :discarded)
+      (s/end! s1)
+      (s/push! s2 3)
+      (s/push! s2 4)
+      (s/end! s2))))
+
+(t/deftest event-stream-merge
+  (t/async done
+    (let [s1 (s/from-coll [1 2 3])
+          s2 (s/from-coll [:1 :2 :3])
+          ms (s/merge s1 s2)]
+      (drain! ms #(t/is (= % [1 :1 2 :2 3 :3])))
+      (s/on-end ms done))))
+
+(t/deftest event-stream-skip-while
+  (t/async done
+    (let [nums (s/from-coll [1 1 1 2 3 4 5])
+          sample (s/skip-while odd? nums)]
+      (drain! sample #(t/is (= % [2 3 4 5])))
+      (s/on-end sample done))))
+
+(t/deftest event-stream-skip-until
+  (t/async done
+    (let [s (s/bus)
+          sv (s/bus)
+          sample (s/skip-until sv s)]
+      (drain! sample #(t/is (= % [3 4 5])))
+      (s/on-end sample done)
+      ;; push values onto stream
+      (s/push! s 1)
+      (s/push! s 2)
+      ;; open switch
+      (s/push! sv :value)
+      ;; push some more
+      (s/push! s 3)
+      (s/push! s 4)
+      (s/push! s 5)
+      ;; end
+      (s/end! s)
+      (s/end! sv))))

 ;; ;; - bufferWithTime
 ;; ;; - bufferWithCount
 ;; ;; - bufferWithTimeOrCount
 ;; ;; - toProperty

-;; ;; property
-
-;; (t/deftest property-constant
-;;   (t/async done
-;;     (let [p (s/constant 42)]
-;;       (t/is (s/property? p))
-;;       (s/on-value p #(do (t/is (= % 42))
-;;                          (done))))))
-
-;; (t/deftest property-sample
-;;   (t/async done
-;;     (let [ep (s/sample 1000 (s/constant 42))]
-;;       (t/is (s/event-stream? ep))
-;;       (s/on-value (s/take 1 ep) #(do
-;;                                    (t/is (= % 42))
-;;                                    (done))))))
-
-;; (t/deftest property-sampled-by
-;;   (t/async done
-;;     (let [clock (s/to-property (tick 10))
-;;           ep (s/sampled-by clock (tick 2))
-;;           epsamples (s/take 2 ep)
-;;           ep2 (s/sampled-by clock (tick 20))
-;;           ep2samples (s/take 2 ep2)]
-;;       (t/is (s/property? clock))
-;;       (t/is (s/event-stream? ep))
-;;       (t/is (s/event-stream? ep2))
-
-;;       (drain! epsamples (fn [[x y]]
-;;                           (t/is (= x y))))
-;;       (drain! ep2samples (fn [[x y]]
-;;                            (t/is (not= x y))))
-
-;;       (s/on-end (s/zip epsamples ep2samples)
-;;                 done))))
-
-;; #_(t/deftest property-sampled-by-combining-function
-;;   (t/async done
-;;     (let [clock (s/to-property (tick 10))
-;;           same-time? (fn [t1 t2]
-;;                        (if (= t1 t2)
-;;                          :same
-;;                          :different))
-;;           ep (s/sampled-by clock
-;;                            clock
-;;                            same-time?)
-;;           epsamples (s/take 2 ep)
-;;           ep2 (s/sampled-by clock
-;;                             (tick 20)
-;;                             same-time?)
-;;           ep2samples (s/take 2 ep2)]
-;;       (drain! epsamples
-;;               #(t/is (= % [:same :same])))
-;;       (drain! ep2samples
-;;               #(t/is (= % [:different :different])))
-;;       (s/on-end (s/zip epsamples ep2samples) #(done)))))
-
-;; (t/deftest property-changes
-;;   (t/async done
-;;     (let [p (s/constant 42)
-;;           sp (s/to-property (s/sample 10 p))
-;;           cp (s/changes sp)
-;;           cs (s/take 2 cp)]
-;;       (t/is (s/event-stream? cp))
-;;       (drain! cs
-;;               #(t/is (= % [42 42])))
-;;       (s/on-end cs done))))
-
-;; (t/deftest property-and
-;;   (t/async done
-;;     (let [t  (s/constant true)
-;;           f  (s/not t)
-
-;;           tf (s/and t f)
-;;           tt (s/and t t)
-;;           ft (s/and f t)
-;;           ff (s/and f f)
-
-;;           ttt (s/and t t t)
-;;           ttf (s/and t t f)]
-
-;;       (s/on-value tt #(t/is (true? %)))
-;;       (s/on-value tf #(t/is (false? %)))
-;;       (s/on-value ft #(t/is (false? %)))
-;;       (s/on-value ff #(t/is (false? %)))
-
-;;         (s/on-value ttt #(t/is (true? %)))
-;;         (s/on-value ttf #(do
-;;                           (t/is (false? %))
-;;                           (done))))))
-
-;; (t/deftest property-or
-;;   (t/async done
-;;     (let [t  (s/constant true)
-;;           f  (s/not t)
-
-;;           tf (s/or t f)
-;;           tt (s/or t t)
-;;           ft (s/or f t)
-;;           ff (s/or f f)
-
-;;           fff (s/or f f f)
-;;           fft (s/or f f t)]
-
-;;       (s/on-value tt #(t/is (true? %)))
-;;       (s/on-value tf #(t/is (true? %)))
-;;       (s/on-value ft #(t/is (true? %)))
-;;       (s/on-value ff #(t/is (false? %)))
-
-;;       (s/on-value fff #(t/is (false? %)))
-;;       (s/on-value fft #(do
-;;                         (t/is (true? %))
-;;                         (done))))))
-
 ;; ;; bus

-;; (t/deftest bus-push
-;;   (t/async done
-;;     (let [b (s/bus)]
-;;       (t/is (s/bus? b))
-;;       (drain! b #(t/is (= % [1 2 3])))
-;;       (s/push! b 1)
-;;       (s/push! b 2)
-;;       (s/push! b 3)
-;;       (s/end! b)
-;;       (s/on-end b done))))
-
+(t/deftest bus-push
+  (t/async done
+    (let [b (s/bus)]
+      (t/is (s/bus? b))
+      (drain! b #(t/is (= % [1 2 3])))
+      (s/push! b 1)
+      (s/push! b 2)
+      (s/push! b 3)
+      (s/end! b)
+      (s/on-end b done))))
+
+
+;; TODO:
 ;; (t/deftest bus-erro
 ;;   (t/async done
 ;;     (let [b (s/bus)]
@@ -438,9 +212,8 @@
 ;;       (drain! b #(t/is (= % [1]))
 ;;                 #(t/is (= % :oh-no)))
 ;;       (s/push! b 1)
-;;       (s/error! b :oh-no)
-;;       (s/end! b)
-;;       (s/on-end b done))))
+;;       (s/error! b (ex-info "oh noes" {})
+;;       (s/on-error b done))))

 ;; (t/deftest bus-plug
 ;;   (t/async done
@@ -453,13 +226,13 @@
 ;;       (s/end! b)
 ;;       (s/on-end b done))))

-;; (t/deftest filter-with-predicate
-;;   (t/async done
-;;     (let [s (s/from-coll [1 2 3 4 5])
-;;           fs (s/filter #{3 5} s)]
-;;       (drain! fs #(t/is (= %
-;;                           [3 5])))
-;;       (s/on-end fs done))))
+(t/deftest filter-with-predicate
+  (t/async done
+    (let [s (s/from-coll [1 2 3 4 5])
+          fs (s/filter #{3 5} s)]
+      (drain! fs #(t/is (= % [3 5])))
+      (s/on-end fs done))))
+
 ;; ;; ::todo decomplect
 ;; ;; - filter (pred, property)
 ;; ;; - map
@@ -563,8 +336,8 @@
 ;;  (t/async done
 ;;    (let [s (s/from-coll [0 1 2])
 ;;          s2 (m/fmap inc s)]
-;;      (t/is (s/event-stream? s))
-;;      (t/is (s/event-stream? s2))
+;;      (t/is (s/observable? s))
+;;      (t/is (s/observable? s2))
 ;;      (drain! s2 #(do (t/is (= % [1 2 3]))
 ;;                       (done))))))

@@ -573,7 +346,7 @@
 ;;    (let [pinc (m/pure s/event-stream-context inc)
 ;;          pval (m/pure s/event-stream-context 41)
 ;;          life (m/fapply pinc pval)]
-;;      (t/is (s/event-stream? life))
+;;      (t/is (s/observable? life))
 ;;      (drain! life #(do (t/is (= % [42]))
 ;;                        (done))))))

@@ -584,7 +357,7 @@
 ;;                         k (s/from-coll (map (comp keyword str) (range 1 (inc n))))]
 ;;                  (m/return [n k]))
 ;;           sample (s/take 6 snks)]
-;;       (t/is (s/event-stream? snks))
+;;       (t/is (s/observable? snks))
 ;;       (drain! sample #(t/is (= % [[1 :1]
 ;;                                   [2 :1]
 ;;                                   [2 :2]


Fixes to scrypt assertions

Fixes to scrypt assertions

--- src/spaceheater/scrypt.cljs
+++ src/spaceheater/scrypt.cljs
@@ -176,15 +176,15 @@
   p -- CPU parallelization parameter
   dkLen -- Intended output length of derived key, in octets"
   [passwd salt N r p dkLen]
-  (assert (>= (* r p) (js/Math.pow 2 30))
-    (format "The parameters r and p must satisfy r * p < 2^30;
-     current value: %s" (* r p)))
-  (assert (or (< N 2) (not= 0 (b& N (dec N))))
+  (assert (<= (* r p) (js/Math.pow 2 30))
+    (str "The parameters r and p must satisfy r * p < 2^30;
+     current value: " (* r p)))
+  (assert (or (> N 2) (= 0 (b& N (dec N))))
     "Ther parameter N must be a power of 2.")
   (let [max (dec (js/Math.pow 2 32))]
-    (assert (> N (/ max (/ 128 r)))
+    (assert (<= N (/ max (/ 128 r)))
       "N too big")
-    (assert (> r (/ map (/ 128 p)))
+    (assert (<= r (/ max (/ 128 p)))
       "r too big"))
   (let [B (p/deriveKeySha256 passwd salt 1 (* p 128 r 8))
         V (make-array 16)


:lipstick: Minor cosmetic changes.

:lipstick: Minor cosmetic changes.

--- frontend/src/uxbox/worker/snaps.cljs
+++ frontend/src/uxbox/worker/snaps.cljs
@@ -39,8 +39,7 @@
 (defn- initialize-snap-data
   "Initialize the snap information with the current workspace information"
   [objects]
-  (let [shapes (vals objects)
-        frame-shapes (->> (vals objects)
+  (let [frame-shapes (->> (vals objects)
                           (filter :frame-id)
                           (group-by :frame-id))
         frame-shapes (->> (cp/select-frames objects)


upsert, log when done saving

upsert, log when done saving

--- clojure/src/dnd/db.cljs
+++ clojure/src/dnd/db.cljs
@@ -29,7 +29,11 @@
   (async
     (->
       (await (levels))
-      (.findOneAndUpdate #js {} #js {"$set" #js {:blocks (clj->js @level)}}))))
+      (.findOneAndUpdate
+        #js {}
+        #js {"$set" #js {:blocks (clj->js @level)}}
+        #js {:upsert true})
+      (.then #(prn "Level saved.")))))

 (defn load []
   (async


Remove stray print statement

Remove stray print statement

--- test/midje/ideas/reporting/t_string_format_map_translation.clj
+++ test/midje/ideas/reporting/t_string_format_map_translation.clj
@@ -98,7 +98,6 @@
                      :position ["foo.clj" 3]
                      :var odd?}
         raw-report (with-identity-renderer (clojure.test/old-report failure-map))]
-    (prn raw-report)
     (nth raw-report 0) => #"FAIL.*some description.* at .*foo.clj:3"
     (nth raw-report 1) => #"never said .*odd.* would be needed"
     (nth raw-report 1) =future=> #"never said odd\? would be needed"


Failing test for archived topic ressurection.

--- test/open_company/integration/section/section_manipulation.clj
+++ test/open_company/integration/section/section_manipulation.clj
@@ -9,7 +9,8 @@
             [open-company.resources.common :as common-res]
             [open-company.resources.company :as company]
             [open-company.resources.section :as section]
-            [open-company.representations.company :as company-rep]))
+            [open-company.representations.company :as company-rep]
+            [open-company.representations.section :as section-rep]))

 ;; ----- Test Cases -----

@@ -206,7 +207,7 @@
               db-company (company/get-company conn r/slug)
               get-response (mock/api-request :get (company-rep/url r/slug))
               get-body (mock/body-from-response get-response)]
-          ;; verify the response status
+          ;; verify the response statuses
           (doseq [response [patch-response get-response]]
             (:status response) => 200)
           ;; verify the DB data and API responses
@@ -230,7 +231,7 @@
               db-company (company/get-company conn r/slug)
               get-response (mock/api-request :get (company-rep/url r/slug))
               get-body (mock/body-from-response get-response)]
-          ;; verify the response status
+          ;; verify the response statuses
           (doseq [response [patch-response get-response]]
             (:status response) => 200)
           ;; verify the DB data and API responses
@@ -256,7 +257,7 @@
               db-company (company/get-company conn r/slug)
               get-response (mock/api-request :get (company-rep/url r/slug))
               get-body (mock/body-from-response get-response)]
-          ;; verify the response status
+          ;; verify the response statuses
           (doseq [response [patch-response get-response]]
             (:status response) => 200)
           ;; verify the DB data and API responses
@@ -280,7 +281,7 @@
               db-company (company/get-company conn r/slug)
               get-response (mock/api-request :get (company-rep/url r/slug))
               get-body (mock/body-from-response get-response)]
-          ;; verify the response status
+          ;; verify the response statuses
           (doseq [response [patch-response get-response]]
             (:status response) => 200)
           ;; verify the DB data and API responses
@@ -325,27 +326,34 @@
           (:placeholder db-highlights) => true
           db-highlights => (contains placeholder)))

-      (future-fact "that used to exist"
-        (let [new-sections {:company [] :progress []}
-              response (mock/api-request :patch (company-rep/url r/slug) {:body {:sections new-sections}})
-              body (mock/body-from-response response)
-              db-company (company/get-company conn r/slug)]
-          (:status response) => 200
-          (:sections body) => new-sections
-          ; verify update is not in the response
-          (:update body) => nil
-          ; verify update not in the DB
-          (:update db-company) => nil)
-        (let [new-sections {:company [] :progress ["update"]}
-              response (mock/api-request :patch (company-rep/url r/slug) {:body {:sections new-sections}})
-              body (mock/body-from-response response)
-              db-company (company/get-company conn r/slug)]
-          (:status response) => 200
-          (:sections body) => new-sections
-          ; verify update is not in the response
-          (:update body) => (contains r/text-section-1)
-          ; verify update not in the DB
-          (:update db-company) => (contains r/text-section-1))))
+      (fact "that used to exist"
+        ; First, update the content using another user to create a newer revision
+        (let [new-content {:title "Update" :headline "Headline #2" :body "Update #2."}
+              patch1-response (mock/api-request :patch (section-rep/url r/slug "update") {:auth mock/jwtoken-camus
+                                                                                :body new-content})
+              ; Then remove the content
+              new-sections {:company [] :progress []}
+              patch2-response (mock/api-request :patch (company-rep/url r/slug) {:body {:sections new-sections}})
+              patch2-body (mock/body-from-response patch2-response)
+              db1-company (company/get-company conn r/slug)
+              ; Now add the section again
+              newer-sections {:company [] :progress ["update"]}
+              patch3-response (mock/api-request :patch (company-rep/url r/slug) {:body {:sections newer-sections}})
+              patch3-body (mock/body-from-response patch3-response)
+              db2-company (company/get-company conn r/slug)]
+          ;; verify the response statuses
+          (doseq [response [patch1-response patch2-response patch3-response]]
+            (:status response) => 200)
+          ;; verify update is not in the removal response
+          (:sections patch2-body) => new-sections
+          (:update patch2-body) => nil
+          ;; verify update is not in the DB
+          (:update db1-company) => nil
+          ;; verify update is in the re-add response AND contains the latest content
+          (:sections patch3-body) => newer-sections
+          (:update patch3-body) => (contains new-content)
+          ; verify update is in the DB AND contains the latest content
+          (:update db2-company) => (contains new-content))))

     (facts "with section content"


- Use more descriptive names for locals

- Use more descriptive names for locals

- Introduce mapify to decrease indenting some more

- Remove some intermediate values that were just obscuring the goal

- Group gensyms together

--- src/useful/experimental.clj
+++ src/useful/experimental.clj
@@ -85,46 +85,49 @@
                (print-stub "open" this (list) (jiraph.layer/open (:impl this))))})))

-(letfn [(symbol ([ns sym]
+(letfn [(mapify [coll] (into {} coll)) ;; just for less-deep indenting
+        (symbol ([ns sym]              ;; annoying that (symbol 'x 'y) fails
                    (clojure.core/symbol (name ns) (name sym))))
         (behavior ([name default exceptions]
-                     (if (exceptions name)
-                       ({:forward :stub, :stub :forward} default)
-                       default)))
+                     (= :forward
+                        (if (exceptions name)
+                          ({:forward :stub, :stub :forward} default)
+                          default))))
         (analyze-var [v]
           (let [{:keys [ns name]} (meta v)
                 ns (ns-name ns)
                 sigs (:sigs @v)]
             (keyed [ns name sigs])))]
+
   (defmacro protocol-stub
     [name trace-fn proto-specs]
-    (let [trace-fn-name (gensym 'trace-fn)
-          impl-field-name (gensym 'impl)
-          proto-fns (into {}
-                          (for [[name opts] proto-specs
-                                :let [default-behavior (:default opts :stub)
-                                      exceptions (set (:exceptions opts))
-                                      proto-var (resolve name)
-                                      {:keys [ns name sigs]} (analyze-var proto-var)]]
-                            {(symbol ns name)
-                             (into {}
-                                   (for [[fn-key {:keys [arglists name]}] sigs
-                                         :let [behave (behavior name default-behavior exceptions)
-                                               should-forward (= :forward behave)
-                                               impl-sym (symbol ns name)]]
-                                     {fn-key
-                                      (cons `fn
-                                            (for [[this & args :as sig] arglists]
-                                              `(~sig (let [~'ret ~(when should-forward
-                                                                    (list* impl-sym `(~(keyword impl-field-name) ~this) args))]
-                                                       (~trace-fn-name
-                                                        '~name
-                                                        (list ~@sig)
-                                                        ~@(when should-forward
-                                                            ['ret]))
-                                                       ~'ret))))}))}))]
+    (let [[trace impl-field ret] (map gensym '(trace impl ret))
+          impl-kw (keyword impl-field)
+
+          proto-fns
+          (mapify
+           (for [[name opts] proto-specs
+                 :let [default-behavior (:default opts :stub)
+                       exceptions (set (:exceptions opts))
+                       proto-var (resolve name)
+                       {:keys [ns name sigs]} (analyze-var proto-var)]]
+             {(symbol ns name)
+              (mapify
+               (for [[fn-key {arglists :arglists, short-name :name}] sigs
+                     :let [forward? (behavior short-name default-behavior exceptions)
+                           fn-name (symbol ns short-name)]]
+                 {fn-key
+                  (cons `fn
+                        (for [[this & args :as argvec] arglists]
+                          `([~@argvec]
+                            (let [~ret ~(when forward?
+                                           `(~fn-name (~impl-kw ~this) ~@args))]
+                              (~trace '~short-name (list ~@argvec)
+                                      ~@(when forward?
+                                          [ret]))
+                              ~ret))))}))}))]
       `(do
-         (defrecord ~name [~impl-field-name])
-         (let [~trace-fn-name ~trace-fn]
+         (defrecord ~name [~impl-field])
+         (let [~trace ~trace-fn]
            (extend ~name
              ~@(apply concat proto-fns)))))))


Add exists? and get functions to layouts core.

--- src/incise/layouts/core.clj
+++ src/incise/layouts/core.clj
@@ -1,6 +1,15 @@
-(ns incise.layouts.core)
+(ns incise.layouts.core
+  (:refer-clojure :exclude [get]))

 (def layouts (atom {}))
+
+(defn exists?
+  "Check for the existance of a layout with the given name."
+  [layout-with-name]
+  (contains? @layouts layout-with-name))
+
+(defn get [& args]
+  (apply clojure.core/get @layouts args))

 (defn register
   "Register a layout function to a shortname"


adding user db test

adding user db test

--- resources/leiningen/new/closp/project.clj
+++ resources/leiningen/new/closp/project.clj
@@ -39,7 +39,6 @@
                  [korma "0.4.2"]
                  [com.h2database/h2 "1.4.187"]
                  [org.xerial/sqlite-jdbc "3.8.10.1"]
-                 [joplin.core "0.2.11"]

                  [com.draines/postal "1.11.3"]

@@ -107,7 +106,9 @@

                        :dependencies [[ring-mock "0.1.5"]
                                       [ring/ring-devel "1.4.0"]
-                                      [pjstadig/humane-test-output "0.7.0"]]
+                                      [pjstadig/humane-test-output "0.7.0"]
+                                      [joplin.core "0.2.11"]
+                                      [joplin.jdbc "0.2.11"]]

                        :injections   [(require 'pjstadig.humane-test-output)
                                       (pjstadig.humane-test-output/activate!)]


Added Expires attribute to the set-cookie-attrs variable for IE support.

--- ring-core/src/ring/middleware/cookies.clj
+++ ring-core/src/ring/middleware/cookies.clj
@@ -24,7 +24,7 @@
 (defvar- set-cookie-attrs
   {:comment "Comment", :comment-url "CommentURL", :discard "Discard",
    :domain "Domain", :max-age "Max-Age", :path "Path", :port "Port",
-   :secure "Secure", :version "Version"}
+   :secure "Secure", :version "Version", :expires "Expires"}
   "Attributes defined by RFC2109 and RFC2965 that apply to the Set-Cookie
   header.")


added test case for erroneous hashtag linkification

failed to find a solution so far - experimenting with variations of the
pattern for the hashtag `replace` call in `linkify` led nowhere

couldn't get difftest[1] to work, so using `compare` as a poor man's
version

clearly I have no idea what I'm doing...

[1] https://github.com/brentonashworth/lein-difftest

--- test/linkification.clj
+++ test/linkification.clj
@@ -1,6 +1,18 @@
 (ns linkification
   (:use clojure.test
         [statuses.views.common :only [linkify]]))
+
+(defn compare [actual expected]
+  (cond (not= actual expected)
+    (str ; XXX: unecessary hack
+        (println actual)
+        (println "        ^")
+        (println "        |")
+        (println "---- actual vs. expected ----")
+        (println "                    |")
+        (println "                    v")
+        (println expected)))
+  (is (= actual expected)))

 (deftest linkify-basic []
   (is (= (linkify "lorem ipsum") "lorem ipsum")))
@@ -26,3 +38,11 @@
   (is (=
       (linkify "lipsum #hashtag")
       "lipsum #hashtag")))
+
+(deftest linkify-uris-with-fragment-identifier []
+  (compare
+      (linkify "lorem http://example.org#anchor ipsum")
+      "lorem http://example.org#anchor ipsum")
+  (compare
+      (linkify "lorem ipsum http://example.org#anchor-name #hashtag")
+      "lorem http://example.org#anchor-name ipsum #hashtag"))


fix subdomain on read-only docs

fix subdomain on read-only docs

--- src-cljs/frontend/urls.cljs
+++ src-cljs/frontend/urls.cljs
@@ -5,5 +5,6 @@
 (defn absolute-doc-url [doc-id]
   (str (url/map->URL {:protocol config/scheme
                       :port config/port
-                      :host config/hostname
+                      :host (str (when config/subdomain (str config/subdomain "."))
+                                 config/hostname)
                       :path (str "/document/" doc-id)})))


fix new message selector

fix new message selector

--- frontend/intercom.cljs
+++ frontend/intercom.cljs
@@ -9,7 +9,7 @@
     (try
       (.click (jq "#IntercomTab"))
       (when-not (.is (jq "#IntercomNewMessageContainer") ":visible")
-        (.click (jq ".new_message")))
+        (.click (jq "[href=IntercomNewMessageContainer]")))
       (.focus (jq "#newMessageBody"))
       (when message
         (.text (jq "#newMessageBody") (str message "\n\n")))