CMR-3931: Addressed more PR comment from Duncan: Breaking the parse-collection-citations into multiple functions.

--- umm-spec-lib/src/cmr/umm_spec/xml_to_umm_mappings/iso_shared/collection_citation.clj
+++ umm-spec-lib/src/cmr/umm_spec/xml_to_umm_mappings/iso_shared/collection_citation.clj
@@ -94,6 +94,72 @@
   (str "gmd:contactInfo/gmd:CI_Contact"
        "/gmd:onlineResource/gmd:CI_OnlineResource/gmd:function/gmd:CI_OnLineFunctionCode/@codeListValue"))

+(defn- get-creator-editor
+  "Get creator, editor from the creator-editor-parties.
+   They share the same structure except that editor contains additional position-name."
+  [creator-editor-parties]
+  (into (sorted-map)
+    (for [creator-editor-party creator-editor-parties
+          :let [idname (value-of creator-editor-party individual-name-xpath)
+                osname (value-of creator-editor-party organisation-name-xpath)
+                osname (when osname
+                         (str " " osname))
+                psname (value-of creator-editor-party position-name-xpath)
+                idosname (str idname osname)]]
+      (if (= psname "editor")
+        {:editor (when idosname (str/trim idosname))}
+        {:creator (when idosname (str/trim idosname))}))))
+
+(defn- get-publisher-release-place
+  "Get publisher, release place from the pub-rel-pl-parties.
+   They share the same structure except that release place contains additional position-name."
+  [pub-rel-pl-parties]
+  (into (sorted-map)
+    (for [pub-rel-pl-party pub-rel-pl-parties
+          :let [idname (value-of pub-rel-pl-party individual-name-xpath)
+                osname (value-of pub-rel-pl-party organisation-name-xpath)
+                osname (when osname
+                         (str " " osname))
+                psname (value-of pub-rel-pl-party position-name-xpath)
+                idosname (str idname osname)
+                del-pt (value-of pub-rel-pl-party delivery-point-xpath)
+                city (value-of pub-rel-pl-party city-xpath)
+                city (when city
+                       (str " " city))
+                state (value-of pub-rel-pl-party state-xpath)
+                state (when state
+                        (str " " state))
+                zip (value-of pub-rel-pl-party zip-xpath)
+                zip (when zip
+                      (str " " zip))
+                country (value-of pub-rel-pl-party country-xpath)
+                country (when country
+                          (str " " country))
+                email (value-of pub-rel-pl-party email-xpath)
+                email (when email
+                        (str " " email))
+                release-place (str del-pt city state zip country email)]]
+      (if (= psname "release place")
+        {:release-place (when release-place (str/trim release-place))}
+        {:publisher (when idosname (str/trim idosname))}))))
+
+(defn- get-online-resources
+  "Get the online resources."
+  [online-resource-parties]
+  (for [online-resource-party online-resource-parties
+        :let [linkage (value-of online-resource-party linkage-xpath)
+              protocol (value-of online-resource-party protocal-xpath)
+              app-profile (value-of online-resource-party application-profile-xpath)
+              name (value-of online-resource-party name-xpath)
+              description (value-of online-resource-party description-xpath)
+              function (value-of online-resource-party function-xpath)]]
+    {:Linkage linkage
+     :Protocol protocol
+     :ApplicationProfile app-profile
+     :Name name
+     :Description description
+     :Function function}))
+
 (defn parse-collection-citation
   "Parse the Collection Citation from XML resource citation"
   [doc collection-citation-xpath sanitize?]
@@ -104,60 +170,11 @@
                 creator-editor-parties (seq (select resource-citation creator-editor-xpath))
                 pub-rel-pl-parties (seq (select resource-citation publisher-release-place-xpath))
                 online-resource-parties (seq (select resource-citation online-resource-xpath))
-                creator-editor (for [creator-editor-party creator-editor-parties
-                                     :let [idname (value-of creator-editor-party individual-name-xpath)
-                                           osname (value-of creator-editor-party organisation-name-xpath)
-                                           osname (when osname
-                                                    (str " " osname))
-                                           psname (value-of creator-editor-party position-name-xpath)
-                                           idosname (str idname osname)]]
-                                 (if (= psname "editor")
-                                   {:editor (when idosname (str/trim idosname))}
-                                   {:creator (when idosname (str/trim idosname))}))
-                creator (:creator (into (sorted-map) creator-editor))
-                editor (:editor (into (sorted-map) creator-editor))
-                pub-rel-place (for [pub-rel-pl-party pub-rel-pl-parties
-                                    :let [idname (value-of pub-rel-pl-party individual-name-xpath)
-                                          osname (value-of pub-rel-pl-party organisation-name-xpath)
-                                          osname (when osname
-                                                    (str " " osname))
-                                          psname (value-of pub-rel-pl-party position-name-xpath)
-                                          idosname (str idname osname)
-                                          del-pt (value-of pub-rel-pl-party delivery-point-xpath)
-                                          city (value-of pub-rel-pl-party city-xpath)
-                                          city (when city
-                                                    (str " " city))
-                                          state (value-of pub-rel-pl-party state-xpath)
-                                          state (when state
-                                                    (str " " state))
-                                          zip (value-of pub-rel-pl-party zip-xpath)
-                                          zip (when zip
-                                                    (str " " zip))
-                                          country (value-of pub-rel-pl-party country-xpath)
-                                          country (when country
-                                                    (str " " country))
-                                          email (value-of pub-rel-pl-party email-xpath)
-                                          email (when email
-                                                    (str " " email))
-                                          release-place (str del-pt city state zip country email)]]
-                                 (if (= psname "release place")
-                                   {:release-place (when release-place (str/trim release-place))}
-                                   {:publisher (when idosname (str/trim idosname))}))
-                 publisher (:publisher (into (sorted-map) pub-rel-place))
-                 release-place (:release-place (into (sorted-map) pub-rel-place))
-                 online-res (for [online-resource-party online-resource-parties
-                                  :let [linkage (value-of online-resource-party linkage-xpath)
-                                        protocol (value-of online-resource-party protocal-xpath)
-                                        app-profile (value-of online-resource-party application-profile-xpath)
-                                        name (value-of online-resource-party name-xpath)
-                                        description (value-of online-resource-party description-xpath)
-                                        function (value-of online-resource-party function-xpath)]]
-                              {:Linkage linkage
-                               :Protocol protocol
-                               :ApplicationProfile app-profile
-                               :Name name
-                               :Description description
-                               :Function function})]]
+                creator (:creator (get-creator-editor creator-editor-parties))
+                editor (:editor (get-creator-editor creator-editor-parties))
+                publisher (:publisher (get-publisher-release-place pub-rel-pl-parties ))
+                release-place (:release-place (get-publisher-release-place pub-rel-pl-parties))
+                online-resources (get-online-resources online-resource-parties)]]
       (util/remove-nil-keys
         {:Creator creator
          :Editor editor
@@ -173,6 +190,6 @@
          :IssueIdentification (value-of resource-citation issue-identification-xpath)
          :DataPresentationForm (value-of resource-citation data-presentation-form-xpath)
          :OtherCitationDetails (value-of resource-citation other-citation-details-xpath)
-         :OnlineResource (util/remove-nil-keys (first online-res))}))))
+         :OnlineResource (util/remove-nil-keys (first online-resources))}))))


Help command.

Help command.

--- src/mash_commander/nix/filesystem.cljs
+++ src/mash_commander/nix/filesystem.cljs
@@ -8,17 +8,32 @@
 (defn fs-cursor []
   (om/ref-cursor (get-in (om/root-cursor state/app-state) [:characters :nix :fs])))

-(declare files)
+(defn commands [dir]
+  (let [files (seq (:files dir))]
+    (apply concat
+           ;; Flattened list of lists of command structures
+           (map #(cond
+                   (= :dir (:type (second %))) (commands (second %))
+                   (and (= :file (:type (second %))) (contains? (:mod (second %)) :x)) [(assoc (second %) :name (first %))]
+                   :default [])
+                files))))
+
+(defn command-trie []
+  (let [c (map :name (commands (:root @(fs-cursor))))]
+    (trie/build c)))
+
+(defn command-map []
+  (reduce #(assoc %1 (:name %2) %2) {} (commands (:root @(fs-cursor)))))

 (defn ls []
   (let [fs @(fs-cursor)
         dir (get-in (:root fs) (interleave (repeat :files) (:cwd fs)))]
     (str/join "\t" (keys (:files dir)))))

-(defn cd [dir]
-  (if (= [".."] dir)
+(defn cd [param]
+  (if (= [".."] param)
     (om/transact! (fs-cursor) #(assoc % :cwd (drop-last (:cwd %))))
-    (let [path (str/split dir "/")
+    (let [path (str/split param "/")
           cwd (:cwd @(fs-cursor))
           new-cwd (concat cwd path)]
       (om/transact! (fs-cursor) #(assoc % :cwd new-cwd))))
@@ -32,6 +47,17 @@
       (assoc-in c [:active] (mode/initial-line-state {:mode :nix}))))
   nil)

+(defn help [param]
+  (let [cmd (get (command-map) param)]
+    (print (str ">" param "<"))
+    (cond
+      (and cmd (:help cmd))
+      (:help cmd)
+      cmd
+      (str (:args cmd))
+      :default
+      (str param " is not a command"))))
+
 (defn init []
   (om/update!
    (fs-cursor)
@@ -42,15 +68,23 @@
                           :files {"ls" {:mod #{:x}
                                         :type :file
                                         :fn ls
-                                        :args []}
+                                        :args []
+                                        :help "`ls` tells you what in your current directory."}
                                   "cd" {:mod #{:x}
                                         :type :file
                                         :fn cd
-                                        :args [:file]}
+                                        :args [:file]
+                                        :help "`cd` changes your current directory."}
                                   "clear" {:mod #{:x}
                                            :type :file
                                            :fn clear
-                                           :args []}}}
+                                           :args []
+                                           :help "`clear` clears the screen."}
+                                  "help" {:mod #{:x}
+                                          :type :file
+                                          :fn help
+                                          :args [:cmd]
+                                          :help "`help` teaches you about other commands."}}}
                    "usr" {:mod #{:r}
                           :type :dir
                           :files {}}}}
@@ -72,23 +106,6 @@
                     [(str/join "/" new-path)]))
                (seq (:files cwd))))))

-(defn commands [dir]
-  (let [files (seq (:files dir))]
-    (apply concat
-           ;; Flattened list of lists of command structures
-           (map #(cond
-                   (= :dir (:type (second %))) (commands (second %))
-                   (and (= :file (:type (second %))) (contains? (:mod (second %)) :x)) [(assoc (second %) :name (first %))]
-                   :default [])
-                files))))
-
-(defn command-trie []
-  (let [c (map :name (commands (:root @(fs-cursor))))]
-    (trie/build c)))
-
-(defn command-map []
-  (reduce #(assoc %1 (:name %2) %2) {} (commands (:root @(fs-cursor)))))
-
 (defn args-trie [args-spec]
   (cond
     ;; Looking for a valid filename
@@ -98,6 +115,9 @@
       (if (empty? cwd)
         (trie/build (cons ".." (files cwd)))
         (trie/build (files cwd))))
+    ;; Looking for a valid command
+    (= :cmd args-spec)
+    (trie/build (keys (command-map)))
     ;; Pre-specified parameters
     :default
     (trie/build args-spec)))


replace hardcoded wav path with freesound asset. Fixes #36.

--- examples/basic.clj
+++ examples/basic.clj
@@ -91,12 +91,11 @@
 ;; (play-chords (now))
 ;; (stop)

-
-(def kick (sample "/home/rosejn/studio/samples/kit/boom.wav"))
-;(kick)
+(def kick-d (sample (freesound-path 41155)))
+;(kick-d)

 (defn looper [t dur notes]
-  (at t (kick))
+  (at t (kick-d))
   (at (+ t 350) (doseq [note (chord-notes)] (overpad (first notes) 0.3 0.1)))
   (at t (overpad (- (first notes) 36) 0.3 (/ dur 1000)))
   (apply-at (+ t dur) #'looper (+ t dur) dur (next notes) []))


Fix whitespace

Fix whitespace

--- examples/leinproj/clj/stormlocal.clj
+++ examples/leinproj/clj/stormlocal.clj
@@ -11,21 +11,21 @@
   (:gen-class :main true))

 (defn run-local! [topology-file debug sleep]
-  (try
+  (try
     (let [cluster (LocalCluster.)]
       ;; submit the topology configured above
-      (.submitTopology cluster
+      (.submitTopology cluster
                       ;; topology name (arbitrary)
                       "stormlocal"
                       ;; topology settings
-                      {TOPOLOGY-DEBUG debug}
+                      {TOPOLOGY-DEBUG debug}
                       ;; topology configuration
                       (apply topology (var-get (load-file topology-file))))
       ;; sleep for 5 seconds before...
       (Thread/sleep sleep)
       ;; shutting down the cluster
       (.shutdown cluster)
-      )
+      )
     (catch RuntimeException rte (str "caught exception: " (.getMessage rte)))))

 (defn run


CMR-2868: Refactored existing tests.

CMR-2868: Refactored existing tests.

--- system-int-test/test/cmr/system_int_test/search/collection_concept_retrieval_test.clj
+++ system-int-test/test/cmr/system_int_test/search/collection_concept_retrieval_test.clj
@@ -14,7 +14,7 @@
             [cmr.system-int-test.data2.kml :as dk]
             [cmr.system-int-test.utils.url-helper :as url]
             [cmr.umm.echo10.collection :as c]
-            [cmr.common.util :refer [are2] :as util]
+            [cmr.common.util :refer [are3] :as util]
             [cmr.transmit.config :as transmit-config]
             [cmr.common.mime-types :as mt]
             [cheshire.core :as json]
@@ -170,116 +170,57 @@
         (is (= (:entry-title umm-coll) (:EntryTitle parsed-collection)))))))

 (defn- expected-umm-json
-  "Returns the expected umm json for the given umm json, target mime type and source schema version"
-  [metadata mime-type source-version]
+  "Returns the expected umm json in the expected-version for the given metadata whose umm
+  json version is source-version."
+  [metadata expected-version source-version]
   (umm-spec/generate-metadata
     test-context
-    (umm-spec/parse-metadata test-context :collection {:format :umm-json :version source-version} metadata)
-    mime-type ver/current-version))
+    (umm-spec/parse-metadata
+      test-context :collection {:format :umm-json :version source-version} metadata)
+    (format "%s;version=%s" mt/umm-json expected-version)))

 (deftest umm-json-version-retrieval-test
   (e/grant-registered-users (s/context) (e/coll-catalog-item-id "provguid1" ["The entry title V5"]))
   (let [user1-token (e/login (s/context) "user1")
-        coll        expected-conversion/example-collection-record
-        mime-type   "application/vnd.nasa.cmr.umm+json;version=1.0"
-        json        (umm-spec/generate-metadata test-context coll mime-type)
-        result      (d/ingest-concept-with-metadata {:provider-id  "PROV1"
-                                                     :concept-type :collection
-                                                     :format       mime-type
-                                                     :metadata     json})
-        concept-id  (:concept-id result)
-        ;; Defines function to retrieve a specific revision of the collection in the format of the accept header
-        retrieve    (fn [revision-id accept-header]
-                      (search/retrieve-concept concept-id
-                                               revision-id
-                                               {:query-params {:token user1-token}
-                                                :accept accept-header}))]
+        coll expected-conversion/example-collection-record
+        original-umm-version "1.0"
+        original-mime-type (format "%s;version=%s" mt/umm-json original-umm-version)
+        json (umm-spec/generate-metadata test-context coll original-mime-type)
+        ;; ingest the collection with umm json metadata in version 1.0
+        {:keys [concept-id]} (d/ingest-concept-with-metadata {:provider-id  "PROV1"
+                                                              :concept-type :collection
+                                                              :format original-mime-type
+                                                              :metadata json})]
     (index/wait-until-indexed)

-    (are2 [revision-id accept-header expected-version]
-          (let [response     (retrieve revision-id accept-header)
-                content-type (get-in response [:headers "Content-Type"])]
-            (and (= 200 (:status response))
-                 ;; retrieved result matches the expected umm json which is in version 1.0
-                 (= (expected-umm-json json accept-header "1.0") (:body response))
-                 (= "application/vnd.nasa.cmr.umm+json" (mt/base-mime-type-of content-type))
-                 (= expected-version (mt/version-of content-type))))
-
-          "without revision id, default accept header"
-          nil "application/vnd.nasa.cmr.umm+json" ver/current-version
-
-          "without revision id, accept header 1.0"
-          nil "application/vnd.nasa.cmr.umm+json;version=1.0" "1.0"
-
-          "without revision id, accept header 1.2"
-          nil "application/vnd.nasa.cmr.umm+json;version=1.2" "1.2"
-
-          "without revision id, accept header latest version"
-          nil (str "application/vnd.nasa.cmr.umm+json;version=" ver/current-version) ver/current-version
-
-          "with revision id, default accept header"
-          1 "application/vnd.nasa.cmr.umm+json" ver/current-version
-
-          "with revision id, accept header 1.0"
-          1 "application/vnd.nasa.cmr.umm+json;version=1.0" "1.0"
-
-          "with revision id, accept header 1.2"
-          1 "application/vnd.nasa.cmr.umm+json;version=1.2" "1.2"
-
-          "with revision id, accept header latest version"
-          1 (str "application/vnd.nasa.cmr.umm+json;version=" ver/current-version) ver/current-version)))
-
-
-(deftest umm-json-version-retrieval-test-with-no-version
-  (e/grant-registered-users (s/context) (e/coll-catalog-item-id "provguid1" ["The entry title V5"]))
-  (let [user1-token (e/login (s/context) "user1")
-        coll        expected-conversion/example-collection-record
-        mime-type   "application/vnd.nasa.cmr.umm+json"
-        json        (umm-spec/generate-metadata test-context coll mime-type)
-        result      (d/ingest-concept-with-metadata {:provider-id  "PROV1"
-                                                     :concept-type :collection
-                                                     :format       mime-type
-                                                     :metadata     json})
-        concept-id  (:concept-id result)
-        retrieve    (fn [revision-id accept-header]
-                      (search/retrieve-concept concept-id
-                                               revision-id
-                                               {:query-params {:token user1-token}
-                                                :accept accept-header}))]
-    (index/wait-until-indexed)
-
-    (are2 [revision-id accept-header expected-version]
-          (let [response     (retrieve revision-id accept-header)
-                content-type (get-in response [:headers "Content-Type"])]
-            (and (= 200 (:status response))
-                 (= (expected-umm-json json accept-header nil) (:body response))
-                 (= "application/vnd.nasa.cmr.umm+json" (mt/base-mime-type-of content-type))
-                 (= expected-version (mt/version-of content-type))))
-
-          "without revision id, default accept header"
-          nil "application/vnd.nasa.cmr.umm+json" ver/current-version
-
-          "without revision id, accept header 1.0"
-          nil "application/vnd.nasa.cmr.umm+json;version=1.0" "1.0"
-
-          "without revision id, accept header 1.2"
-          nil "application/vnd.nasa.cmr.umm+json;version=1.2" "1.2"
-
-          "without revision id, accept header latest version"
-          nil (str "application/vnd.nasa.cmr.umm+json;version=" ver/current-version) ver/current-version
-
-          "with revision id, default accept header"
-          1 "application/vnd.nasa.cmr.umm+json" ver/current-version
-
-          "with revision id, accept header 1.0"
-          1 "application/vnd.nasa.cmr.umm+json;version=1.0" "1.0"
-
-          "with revision id, accept header 1.2"
-          1 "application/vnd.nasa.cmr.umm+json;version=1.2" "1.2"
-
-          "with revision id, accept header latest version"
-          1 (str "application/vnd.nasa.cmr.umm+json;version=" ver/current-version) ver/current-version)))
-
+    (are3 [requested-version expected-version]
+          (let [accept-header (if requested-version
+                                (format "%s;version=%s" mt/umm-json requested-version)
+                                mt/umm-json)
+                ;; retrieve the collection by concept id and the given umm json version in accept header
+                response (search/retrieve-concept concept-id nil
+                                                  {:query-params {:token user1-token}
+                                                   :accept accept-header})
+                response-concept-type (get-in response [:headers "Content-Type"])]
+
+            (is (= 200 (:status response)))
+            ;; retrieved result matches the expected umm json which is converted from the original
+            ;; umm json version to the expected version
+            (is (= (expected-umm-json json expected-version original-umm-version) (:body response)))
+            (is (= mt/umm-json (mt/base-mime-type-of response-concept-type)))
+            (is (= expected-version (mt/version-of response-concept-type))))
+
+          "default version"
+          nil ver/current-version
+
+          "original umm version, 1.0"
+          original-umm-version original-umm-version
+
+          "an intermediate version, 1.2"
+          "1.2" "1.2"
+
+          "specific latest version"
+          ver/current-version ver/current-version)))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -378,28 +319,28 @@
       (testing "native format direct retrieval"
         ;; Native format can be specified using application/xml, application/metadata+xml,
         ;; .native extension, or not specifying any format.
-        (util/are2 [concept format-key extension accept]
-                   (let [options (-> {:accept nil}
-                                     (merge (when extension {:url-extension extension}))
-                                     (merge (when accept {:accept accept})))
-                         response (search/retrieve-concept (:concept-id concept) nil options)]
-                     (is (= (umm/umm->xml concept format-key) (:body response))))
-                   "ECHO10 no extension" c1-echo :echo10 nil nil
-                   "DIF no extension" c3-dif :dif nil nil
-                   "ISO MENDS no extension" c5-iso :iso19115 nil nil
-                   "SMAP ISO no extension" c7-smap :iso-smap nil nil
-                   "ECHO10 .native extension" c1-echo :echo10 "native" nil
-                   "DIF .native extension" c3-dif :dif "native" nil
-                   "ISO MENDS .native extension" c5-iso :iso19115 "native" nil
-                   "SMAP ISO .native extension" c7-smap :iso-smap "native" nil
-                   "ECHO10 accept application/xml" c1-echo :echo10 nil "application/xml"
-                   "DIF accept application/xml" c3-dif :dif nil "application/xml"
-                   "ISO MENDS accept application/xml" c5-iso :iso19115 nil "application/xml"
-                   "SMAP ISO accept application/xml" c7-smap :iso-smap nil "application/xml"
-                   "ECHO10 accept application/metadata+xml" c1-echo :echo10 nil "application/metadata+xml"
-                   "DIF accept application/metadata+xml" c3-dif :dif nil "application/metadata+xml"
-                   "ISO MENDS accept application/metadata+xml" c5-iso :iso19115 nil "application/metadata+xml"
-                   "SMAP ISO accept application/metadata+xml" c7-smap :iso-smap nil "application/metadata+xml"))
+        (are3 [concept format-key extension accept]
+              (let [options (-> {:accept nil}
+                                (merge (when extension {:url-extension extension}))
+                                (merge (when accept {:accept accept})))
+                    response (search/retrieve-concept (:concept-id concept) nil options)]
+                (is (= (umm/umm->xml concept format-key) (:body response))))
+              "ECHO10 no extension" c1-echo :echo10 nil nil
+              "DIF no extension" c3-dif :dif nil nil
+              "ISO MENDS no extension" c5-iso :iso19115 nil nil
+              "SMAP ISO no extension" c7-smap :iso-smap nil nil
+              "ECHO10 .native extension" c1-echo :echo10 "native" nil
+              "DIF .native extension" c3-dif :dif "native" nil
+              "ISO MENDS .native extension" c5-iso :iso19115 "native" nil
+              "SMAP ISO .native extension" c7-smap :iso-smap "native" nil
+              "ECHO10 accept application/xml" c1-echo :echo10 nil "application/xml"
+              "DIF accept application/xml" c3-dif :dif nil "application/xml"
+              "ISO MENDS accept application/xml" c5-iso :iso19115 nil "application/xml"
+              "SMAP ISO accept application/xml" c7-smap :iso-smap nil "application/xml"
+              "ECHO10 accept application/metadata+xml" c1-echo :echo10 nil "application/metadata+xml"
+              "DIF accept application/metadata+xml" c3-dif :dif nil "application/metadata+xml"
+              "ISO MENDS accept application/metadata+xml" c5-iso :iso19115 nil "application/metadata+xml"
+              "SMAP ISO accept application/metadata+xml" c7-smap :iso-smap nil "application/metadata+xml"))

       (testing "unsupported formats"
         (are [mime-type xml?]
@@ -453,7 +394,7 @@

     (testing "retrieve metadata from search by concept-id/revision-id"
       (testing "collections and granules"
-        (are2 [item format-key accept concept-id revision-id]
+        (are3 [item format-key accept concept-id revision-id]
               (let [response (search/retrieve-concept
                                concept-id
                                revision-id


update docker content

update docker content

--- frontend/components/integrations.cljs
+++ frontend/components/integrations.cljs
@@ -41,103 +41,115 @@
   (reify
     om/IInitState
     (init-state [_]
-      {:email ""
-       :use-case ""
-       :notice nil
-       :loading? false})
+                {:email ""
+                 :use-case ""
+                 :notice nil
+                 :loading? false})
     om/IRenderState
     (render-state [_ {:keys [email use-case notice loading?]}]
-      (let [controls-ch (om/get-shared owner [:comms :controls])
-            clear-notice! #(om/set-state! owner [:notice] nil)
-            clear-form! (fn [& [notice]]
-                          (om/update-state! owner (fn [s]
-                                                    (merge s
-                                                           (when notice {:notice notice})
-                                                           {:email ""
-                                                            :use-case ""
-                                                            :loading? false}))))]
-        (html
-         [:form
-          [:input {:name "Email",
-                   :required true
-                   :value email
-                   :on-change #(do (clear-notice!) (om/set-state! owner [:email] (.. % -target -value)))
-                   :type "text"}]
-          [:label {:alt "Email (required)", :placeholder "Email"}]
-          [:textarea
-           {:name "docker_use__c",
-            :required true
-            :value use-case
-            :on-change #(do (clear-notice!) (om/set-state! owner [:use-case] (.. % -target -value)))
-            :type "text"}]
-          [:label {:placeholder "How do you want to use it?"}]
-          [:div.notice
-           (when notice
-             [:span {:class (:type notice)} (:message notice)])]
-          [:div.submit
-           [:input
-            {:value (if loading? "Submitting.." "Submit"),
-             :class (when loading? "disabled")
-             :on-click #(do (if (or (empty? email) (not (utils/valid-email? email)))
-                              (om/set-state! owner [:notice] {:type "error"
-                                                              :message "Please enter a valid email address."})
-                              (do
-                                (om/set-state! owner [:loading?] true)
-                                (go (let [resp (<! (marketo/submit-munchkin-form 1036 {:Email email
-                                                                                :docker_use__c use-case}))]
-                                      (if-not (= :success (:status resp))
-                                        (om/update-state! owner (fn [s]
-                                                                  (merge s {:loading? false
-                                                                            :notice {:type "error"
-                                                                                :message "Sorry! There was an error submitting the form. Please try again or email sayhi@circleci.com."}})))
-                                        (clear-form! {:type "success"
-                                                      :message "Thanks! We will be in touch soon."}))))))
-                            false)
-             :type "submit"}]]])))))
+                  (let [controls-ch (om/get-shared owner [:comms :controls])
+                        clear-notice! #(om/set-state! owner [:notice] nil)
+                        clear-form! (fn [& [notice]]
+                                      (om/update-state! owner (fn [s]
+                                                                (merge s
+                                                                       (when notice {:notice notice})
+                                                                       {:email ""
+                                                                        :use-case ""
+                                                                        :loading? false}))))]
+                    (html
+                      [:form
+                       [:input {:name "Email",
+                                :required true
+                                :value email
+                                :on-change #(do (clear-notice!) (om/set-state! owner [:email] (.. % -target -value)))
+                                :type "text"}]
+                       [:label {:alt "Email (required)", :placeholder "Email"}]
+                       [:textarea
+                        {:name "docker_use__c",
+                         :required true
+                         :value use-case
+                         :on-change #(do (clear-notice!) (om/set-state! owner [:use-case] (.. % -target -value)))
+                         :type "text"}]
+                       [:label {:placeholder "How do you want to use it?"}]
+                       [:div.notice
+                        (when notice
+                          [:span {:class (:type notice)} (:message notice)])]
+                       [:div.submit
+                        [:input
+                         {:value (if loading? "Submitting.." "Submit"),
+                          :class (when loading? "disabled")
+                          :on-click #(do (if (or (empty? email) (not (utils/valid-email? email)))
+                                           (om/set-state! owner [:notice] {:type "error"
+                                                                           :message "Please enter a valid email address."})
+                                           (do
+                                             (om/set-state! owner [:loading?] true)
+                                             (go (let [resp (<! (marketo/submit-munchkin-form 1036 {:Email email
+                                                                                :docker_use__c use-case}))]
+                                                   (if-not (= :success (:status resp))
+                                                     (om/update-state! owner (fn [s]
+                                                                               (merge s {:loading? false
+                                                                                :notice {:type "error"
+                                                                                :message "Sorry! There was an error submitting the form. Please try again or email sayhi@circleci.com."}})))
+                                                     (clear-form! {:type "success"
+                                                                   :message "Thanks! We will be in touch soon."}))))))
+                                       false)
+                          :type "submit"}]]])))))

 (defn docker [app owner]
   (reify
     om/IRender
     (render [_]
-      (let [controls-ch (om/get-shared owner [:comms :controls])
-            ab-tests (:ab-tests app)]
-        (html
-         [:div#integrations.docker
-          [:div.section-container
-           [:section.integrations-hero-wrapper
-            [:article.integrations-hero-title
-             [:h1 "CircleCI is Supporting Docker!"]]
-            [:article.integrations-hero-units
-             [:div.integrations-hero-unit
-              circle-logo
-              [:p "CircleCI makes modern continous integration and deployment easy."]]
-             [:div.integrations-hero-unit
-              docker-logo
-              [:p "Docker makes it easy to build, run, and ship applications anywhere.  "]]]
-            [:h3.message
-             "Together they make it easy to test and ship your entire cloud in one place. "]]]
-          [:div.section-container
-           [:section.integrations-hero-wrapper
-            [:div.docker-features
-             [:h4
-              "Here are some ideas we're working on, but we would love to hear your thoughts too!"]
-             [:div.feature-container
-              [:div.feature
-               [:h3 "Continous Delivery for your Docker Images"]
-               [:p
-                "CircleCI will automate the building of your docker images, test that they work, and Continuously Deliver them to the Docker registry."]]
-              [:div.feature
-               [:h3 "Dev-production parity"]
-               [:p
-                "Run your application's testing and Continuous Integration directly on your own Docker image. Never have a test fail because the test environment is different from your development environment."]]
-              [:div.feature
-               [:h3 "Specify your own image on CircleCI"]
-               [:p
-                "CircleCI will run your tests against a default image, tuned to be maximally compatible with all of our customers. Optionally, you can run your tests against your own image, tuned for your application."]]]]]]
-          [:div.section-container
-           [:section.integrations-hero-wrapper
-            [:p.center-text
-             "Let us know how you would like to use CircleCI with Docker to move to top of the beta queue!"]
-            [:div.docker-cta
-             [:h3 "Sign Up For Beta"]
-             (om/build cta-form app)]]]])))))
+            (let [controls-ch (om/get-shared owner [:comms :controls])
+                  ab-tests (:ab-tests app)]
+              (html
+                [:div#integrations.docker
+                 [:div.section-container
+                  [:section.integrations-hero-wrapper
+                   [:article.integrations-hero-title
+                    [:h1 "Build and deploy Docker containers on CircleCI."]]
+                   [:article.integrations-hero-units
+                    [:div.integrations-hero-unit
+                     circle-logo
+                     [:p "CircleCI makes modern continous integration and deployment easy."]]
+                    [:div.integrations-hero-unit
+                     docker-logo
+                     [:p "Docker makes it easy to build, run, and ship applications anywhere.  "]]]
+                   [:h3.message
+                    "Together they let you achieve development-production parity. At last.
+                    "]]]
+                 [:div.section-container
+                  [:section.integrations-hero-wrapper
+                   [:div.docker-features
+                    [:div.feature-container
+                     [:div.feature
+                      [:img {:src "/icons/cloud-circle.png"}]
+                      [:h3 "Continous Deployment of your Docker images"]
+                      [:p
+                       "CircleCI makes it easy to deploy images to Docker Hub as well as to continously deploy applications to AWS Elastic Beanstalk, Kubernetes on Google Compute Engine, and others."]
+                      [:a {:href "/docs/docker"} "docs"]]
+                     [:div.feature
+                      [:img {:src "/icons/scale-circle.png"}]
+                      [:h3 "Dev-production parity"]
+                      [:p
+                       "Docker containers let you remove almost all of the variables that differ between your test and production environments. You can specify everything from your Linux distro to what executables run at startup in a Dockerfile, build all of that information into a Docker image, test it, and deploy the exact same image byte-for-byte to production. You can now run this entire process on CircleCI."]
+                      [:a {:href "/docs/docker"} "docs"]]
+                     [:div.feature
+                      [:img {:src "/icons/wrench-circle.png"}]
+                      [:h3 "Full Docker functionality"]
+                      [:p
+                       "You can now use all Docker functionality within the CircleCI build environment. All of the usual Docker command line commands work as expected, so you can build and run Docker containers to your heart's content."]
+                      [:a {:href "/docs/docker"} "docs"]]]]]]
+                 [:div.section-container
+                  [:section.integrations-hero-wrapper
+                   [:p.center-text
+                    "Docker is enabled for all current CircleCI users, everyone else can sign up below!"]
+                   [:div.docker-cta
+                    [:div.ctabox {:class "line"}
+                     [:div
+                      [:p "Plans start at $19 per month. All plans include a free 14 day trial."]]
+                     (shared/home-button {:source "integrations/docker"} controls-ch)
+                     [:div
+                      [:p
+                       [:i "CircleCI keeps your code safe. "
+                        [:a {:href "/security" :title "Security"} "Learn how."]]]]]
+                    ]]]])))))


Refactor icons page.

Refactor icons page.

--- src/uxbox/main/ui/dashboard/icons.cljs
+++ src/uxbox/main/ui/dashboard/icons.cljs
@@ -9,148 +9,357 @@
   (:require [sablono.core :refer-macros [html]]
             [rum.core :as rum]
             [lentes.core :as l]
+            [cuerdas.core :as str]
             [uxbox.main.state :as st]
-            [uxbox.util.rstore :as rs]
-            [uxbox.util.schema :as sc]
-            [uxbox.util.i18n :refer (tr)]
             [uxbox.main.library :as library]
-            [uxbox.main.data.dashboard :as dd]
             [uxbox.main.data.lightbox :as udl]
+            [uxbox.main.data.icons :as di]
             [uxbox.main.ui.icons :as i]
             [uxbox.main.ui.shapes.icon :as icon]
             [uxbox.main.ui.lightbox :as lbx]
-            [uxbox.util.mixins :as mx]
             [uxbox.main.ui.dashboard.header :refer (header)]
+            [uxbox.main.ui.keyboard :as kbd]
+            [uxbox.util.i18n :as t :refer (tr)]
+            [uxbox.util.data :refer (read-string)]
+            [uxbox.util.mixins :as mx :include-macros true]
+            [uxbox.util.rstore :as rs]
+            [uxbox.util.schema :as sc]
+            [uxbox.util.lens :as ul]
+            [uxbox.util.i18n :refer (tr)]
             [uxbox.util.dom :as dom]))

-;; --- Lenses
-
-(def dashboard-ref
-  (as-> (l/in [:dashboard]) $
-    (l/derive $ st/state)))
+;; --- Helpers & Constants
+
+(def +ordering-options+
+  {:name "ds.project-ordering.by-name"
+   :created "ds.project-ordering.by-creation-date"})
+
+(defn- sort-icons-by
+  [ordering icons]
+  (case ordering
+    :name (sort-by :name icons)
+    :created (reverse (sort-by :created-at icons))
+    icons))
+
+(defn- contains-term?
+  [phrase term]
+  (let [term (name term)]
+    (str/includes? (str/lower phrase) (str/trim (str/lower term)))))
+
+(defn- filter-icons-by
+  [term icons]
+  (if (str/blank? term)
+    icons
+    (filter #(contains-term? (:name %) term) icons)))
+
+;; --- Refs
+
+(def ^:private dashboard-ref
+  (-> (l/in [:dashboard :icons])
+      (l/derive st/state)))
+
+(def ^:private collections-map-ref
+  (-> (comp (l/key :icon-colls-by-id)
+            (ul/merge library/+icon-collections-by-id+))
+      (l/derive st/state)))
+
+(def ^:private collections-ref
+  (-> (l/lens vals)
+      (l/derive collections-map-ref)))
+
+(defn- focus-collection
+  [id]
+  (-> (l/key id)
+      (l/derive collections-map-ref)))

 ;; --- Page Title

-(defn- page-title-render
-  [own coll]
-  (let [dashboard (mx/react dashboard-ref)
-        own? (:builtin coll false)]
-    (html
-     [:div.dashboard-title {}
-      [:h2 {}
-       [:span (tr "ds.library-title")]
-       [:span {:content-editable ""
-               :on-key-up (constantly nil)}
-        (:name coll)]]
-      (if (and (not own?) coll)
-        [:div.edition {}
-         [:span {:on-click (constantly nil)}
-          i/trash]])])))
-
-(def ^:private page-title
-  (mx/component
-   {:render page-title-render
-    :name "page-title"
-    :mixins [mx/static mx/reactive]}))
+(mx/defcs page-title
+  {:mixins [(mx/local {}) mx/static mx/reactive]}
+  [own {:keys [id] :as coll}]
+  (let [local (:rum/local own)
+        dashboard (mx/react dashboard-ref)
+        own? (= :builtin (:type coll))
+        edit? (:edit @local)]
+    (letfn [(on-save [e]
+              (let [dom (mx/ref-node own "input")
+                    name (.-innerText dom)]
+                #_(rs/emit! (di/rename-collection id (str/trim name)))
+                (swap! local assoc :edit false)))
+            (on-cancel [e]
+              (swap! local assoc :edit false))
+            (on-edit [e]
+              (swap! local assoc :edit true))
+            (on-input-keydown [e]
+              (cond
+                (kbd/esc? e) (on-cancel e)
+                (kbd/enter? e)
+                (do
+                  (dom/prevent-default e)
+                  (dom/stop-propagation e)
+                  (on-save e))))
+
+            (delete []
+              #_(rs/emit! (di/delete-collection (:id coll))))
+            (on-delete []
+              (udl/open! :confirm {:on-accept delete}))]
+      [:div.dashboard-title
+       [:h2
+        (if edit?
+          [:div.dashboard-title-field
+           [:span.edit
+            {:content-editable true
+             :ref "input"
+             :on-key-down on-input-keydown}
+            (:name coll)]
+           [:span.close {:on-click on-cancel} i/close]]
+          [:span.dashboard-title-field
+           {:on-double-click on-edit}
+           (:name coll)])]
+       (if (and (not own?) coll)
+         [:div.edition
+          (if edit?
+            [:span {:on-click on-save} i/save]
+            [:span {:on-click on-edit} i/pencil])
+          [:span {:on-click on-delete} i/trash]])])))

 ;; --- Nav

-(defn nav-render
+(mx/defc nav-item
+  {:mixins [mx/static]}
+  [collection selected?]
+  (letfn [(on-click [event]
+            (let [type (:type collection)
+                  id (:id collection)]
+              (rs/emit! (di/select-collection type id))))]
+    (let [icons (count (:icons collection))]
+      [:li {:on-click on-click
+            :class-name (when selected? "current")}
+       [:span.element-title (:name collection)]
+       [:span.element-subtitle
+        (tr "ds.num-elements" (t/c icons))]])))
+
+(mx/defc nav-section
+  {:mixins [mx/static mx/reactive]}
+  [type selected]
+  (let [own? (= type :own)
+        builtin? (= type :builtin)
+        collections (cond->> (mx/react collections-ref)
+                      own? (filter #(= :own (:type %)))
+                      builtin? (filter #(= :builtin (:type %)))
+                      own? (sort-by :id))]
+    [:ul.library-elements
+     (when own?
+       [:li
+        [:a.btn-primary
+         #_{:on-click #(rs/emit! (di/create-collection))}
+         "+ New library"]])
+     (for [coll collections
+           :let [selected? (= (:id coll) selected)
+                 key (str (:id coll))]]
+       (-> (nav-item coll selected?)
+           (mx/with-key key)))]))
+
+(mx/defc nav
+  {:mixins [mx/static]}
+  [state]
+  (let [selected (:id state)
+        type (:type state)
+        own? (= type :own)
+        builtin? (= type :builtin)]
+    (letfn [(select-tab [type]
+              (let [xf (filter #(= type (:type %)))
+                    colls (sequence xf @collections-ref)]
+                (if-let [item (first colls)]
+                  (rs/emit! (di/select-collection type (:id item)))
+                  (rs/emit! (di/select-collection type)))))]
+      [:div.library-bar
+       [:div.library-bar-inside
+        [:ul.library-tabs
+         [:li {:class-name (when builtin? "current")
+               :on-click (partial select-tab :builtin)}
+          "STANDARD"]
+         [:li {:class-name (when own? "current")
+               :on-click (partial select-tab :own)}
+          "YOUR LIBRARIES"]]
+        (nav-section type selected)]])))
+
+;; --- Grid
+
+;; (defn grid-render
+;;   [own]
+;;   (let [dashboard (mx/react dashboard-ref)
+;;         coll-type (:collection-type dashboard)
+;;         coll-id (:collection-id dashboard)
+;;         own? (= coll-type :own)
+;;         coll (get library/+icon-collections-by-id+ coll-id)]
+;;     (when coll
+;;       (html
+;;        [:section.dashboard-grid.library
+;;         (page-title coll)
+;;         [:div.dashboard-grid-content
+;;           [:div.dashboard-grid-row
+;;            (for [icon (:icons coll)]
+;;              [:div.grid-item.small-item.project-th {}
+;;               [:span.grid-item-icon (icon/icon-svg icon)]
+;;               [:h3 (:name icon)]
+;;               #_[:div.project-th-actions
+;;                [:div.project-th-icon.edit i/pencil]
+;;                [:div.project-th-icon.delete i/trash]]])]]]))))
+
+;; (def grid
+;;   (mx/component
+;;    {:render grid-render
+;;     :name "grid"
+;;     :mixins [mx/static mx/reactive]}))
+
+(mx/defc grid-options
+  [coll]
+  (let [own? (= (:type coll) :own)]
+    (letfn [(delete []
+              #_(rs/emit! (di/delete-selected)))
+            (on-delete [event]
+              (udl/open! :confirm {:on-accept delete}))]
+      ;; MULTISELECT OPTIONS BAR
+      [:div.multiselect-bar
+       (if own?
+         [:div.multiselect-nav
+          #_[:span.move-item.tooltip.tooltip-top
+             {:alt "Move to"}
+             i/organize]
+          [:span.delete.tooltip.tooltip-top
+           {:alt "Delete"
+            :on-click on-delete}
+           i/trash]]
+         [:div.multiselect-nav
+          [:span.move-item.tooltip.tooltip-top
+           {:alt "Copy to"}
+           i/organize]])])))
+
+(mx/defc grid-item
+  [{:keys [id] :as icon} selected?]
+  (letfn [(toggle-selection [event]
+            (rs/emit! (di/toggle-icon-selection id)))
+          (toggle-selection-shifted [event]
+            (when (kbd/shift? event)
+              (toggle-selection event)))]
+    [:div.grid-item.small-item.project-th
+     {:on-click toggle-selection-shifted}
+     [:span.grid-item-image (icon/icon-svg icon)]
+     [:h3 (:name icon)]
+     #_[:div.project-th-actions
+        [:div.project-th-icon.edit i/pencil]
+        [:div.project-th-icon.delete i/trash]]]))
+
+(mx/defc grid
+  {:mixins [mx/static]}
+  [state selected {:keys [id type icons] :as coll}]
+  (let [own? (= type :own)
+        ordering (:order state)
+        filtering (:filter state)
+        icons (->> icons
+                    (remove nil?)
+                    (filter-icons-by filtering)
+                    (sort-icons-by ordering))]
+    [:div.dashboard-grid-content
+     [:div.dashboard-grid-row
+      #_(when own?
+        (grid-form id))
+      (for [icon icons
+            :let [id (:id icon)
+                  selected? (contains? selected id)]]
+        (-> (grid-item icon selected?)
+            (mx/with-key (str id))))]]))
+
+(mx/defc content
+  {:mixins [mx/static]}
+  [state coll]
+  (let [selected (:selected state)
+        coll-type (:type coll)
+        own? (= coll-type :own)]
+    (when coll
+      [:section.dashboard-grid.library
+       (page-title coll)
+       (grid state selected coll)
+       (when (seq selected)
+         (grid-options coll))])))
+
+;; --- Menu
+
+(mx/defc menu
+  {:mixins [mx/static]}
+  [state coll]
+  (let [ordering (:order state :name)
+        filtering (:filter state "")
+        icount (count (:icons coll))]
+    (letfn [(on-term-change [event]
+              (let [term (-> (dom/get-target event)
+                             (dom/get-value))]
+                (rs/emit! (di/update-opts :filter term))))
+            (on-ordering-change [event]
+              (let [value (dom/event->value event)
+                    value (read-string value)]
+                (rs/emit! (di/update-opts :order value))))
+            (on-clear [event]
+              (rs/emit! (di/update-opts :filter "")))]
+      [:section.dashboard-bar.library-gap
+       [:div.dashboard-info
+
+        ;; Counter
+        [:span.dashboard-icons (tr "ds.num-icons" (t/c icount))]
+
+        ;; Sorting
+        [:div
+         [:span (tr "ds.project-ordering")]
+         [:select.input-select
+          {:on-change on-ordering-change
+           :value (pr-str ordering)}
+          (for [[key value] (seq +ordering-options+)
+                :let [ovalue (pr-str key)
+                      olabel (tr value)]]
+            [:option {:key ovalue :value ovalue} olabel])]]
+        ;; Search
+        [:form.dashboard-search
+         [:input.input-text
+          {:key :icons-search-box
+           :type "text"
+           :on-change on-term-change
+           :auto-focus true
+           :placeholder (tr "ds.project-search.placeholder")
+           :value (or filtering "")}]
+         [:div.clear-search {:on-click on-clear} i/close]]]])))
+
+;; --- Icons Page
+
+(defn- icons-page-will-mount
   [own]
-  (let [dashboard (mx/react dashboard-ref)
-        collid (:collection-id dashboard)
-        own? (= (:collection-type dashboard) :own)
-        builtin? (= (:collection-type dashboard) :builtin)
-        collections (if own?
-                      [] #_(sort-by :id (vals colors))
-                      library/+icon-collections+)]
-    (html
-     [:div.library-bar
-      [:div.library-bar-inside
-       [:ul.library-tabs
-        [:li {:class-name (when builtin? "current")
-              :on-click #(rs/emit! (dd/set-collection-type :builtin))}
-         (tr "ds.standard-title")]
-        [:li {:class-name (when own? "current")
-              :on-click #(rs/emit! (dd/set-collection-type :own))}
-         (tr "ds.your-libraries-title")]]
-       [:ul.library-elements
-        (when own?
-          [:li
-           [:a.btn-primary
-            {:on-click (constantly nil)}
-            "+ New library"]])
-        (for [props collections]
-          [:li {:key (str (:id props))
-                :on-click #(rs/emit! (dd/set-collection (:id props)))
-                :class-name (when (= (:id props) collid) "current")}
-           [:span.element-title (:name props)]
-           [:span.element-subtitle
-            (str (count (:icons props)) " elements")]])]]])))
-
-(def ^:private nav
-  (mx/component
-   {:render nav-render
-    :name "nav"
-    :mixins [mx/reactive]}))
-
-;; --- Grid
-
-(defn grid-render
-  [own]
-  (let [dashboard (mx/react dashboard-ref)
-        coll-type (:collection-type dashboard)
-        coll-id (:collection-id dashboard)
-        own? (= coll-type :own)
-        coll (get library/+icon-collections-by-id+ coll-id)]
-    (when coll
-      (html
-       [:section.dashboard-grid.library
-        (page-title coll)
-        [:div.dashboard-grid-content
-          [:div.dashboard-grid-row
-           (for [icon (:icons coll)]
-             [:div.grid-item.small-item.project-th {}
-              [:span.grid-item-image (icon/icon-svg icon)]
-              [:h3 (:name icon)]
-              #_[:div.project-th-actions
-               [:div.project-th-icon.edit i/pencil]
-               [:div.project-th-icon.delete i/trash]]])]]]))))
-
-(def grid
-  (mx/component
-   {:render grid-render
-    :name "grid"
-    :mixins [mx/static mx/reactive]}))
-
-;; --- Icons Page
-
-(defn icons-page-render
-  [own]
-  (html
-   [:main.dashboard-main
-    (header)
-    [:section.dashboard-content
-     (nav)
-     (grid)]]))
-
-(defn icons-page-will-mount
-  [own]
-  (rs/emit! (dd/initialize :dashboard/icons))
-  own)
-
-(defn icons-page-did-remount
-  [old-state state]
-  (rs/emit! (dd/initialize :dashboard/icons))
-  state)
-
-(def icons-page
-  (mx/component
-   {:render icons-page-render
-    :will-mount icons-page-will-mount
-    :did-remount icons-page-did-remount
-    :name "icons-page"
-    :mixins [mx/static]}))
+  (let [[type id] (:rum/args own)]
+    (rs/emit! (di/initialize type id))
+    own))
+
+(defn- icons-page-did-remount
+  [old-own own]
+  (let [[old-type old-id] (:rum/args old-own)
+        [new-type new-id] (:rum/args own)]
+    (when (or (not= old-type new-type)
+              (not= old-id new-id))
+      (rs/emit! (di/initialize new-type new-id)))
+    own))
+
+(mx/defc icons-page
+  {:will-mount icons-page-will-mount
+   :did-remount icons-page-did-remount
+   :mixins [mx/static mx/reactive]}
+  []
+  (let [state (mx/react dashboard-ref)
+        coll-id (:id state)
+        coll (mx/react (focus-collection coll-id))]
+    [:main.dashboard-main
+     (header)
+     [:section.dashboard-content
+      (nav state)
+      (menu state coll)
+      (content state coll)]]))

 ;; --- New Icon Lightbox (TODO)


Cleaned up rule formatting

Cleaned up rule formatting

--- 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
@@ -3,22 +3,20 @@
 ;; ------------------------------------------------------------------------
 ;; create id denotes concept triple for every ontology concept
 `{:name "ontology-id-denotes-concept-gen-obo"
-  :description "This rule generates an ontology concept identifier for every non-root ontology concept with the OBO namespace.
-  The Protein Ontology references some classes that use non-OBO namespaces. Source-specific rules have been written for those
-  namespaces and these rules can be found in the same directory as this more general OBO rule."
-  :head ((?/id obo/IAO_0000219 ?/ontology_concept) ; denotes
-         (?/id rdf/type ccp/IAO_EXT_0000088)) ; ontology concept identifier
+  :description "This rule generates an ontology concept identifier for every non-root ontology concept with the OBO namespace. The Protein Ontology references some classes that use non-OBO namespaces. Source-specific rules have been written for those namespaces and these rules can be found in the same directory as this more general OBO rule."
+  :head ((?/id obo/IAO_0000219 ?/ontology_concept) ; IAO:denotes
+         (?/id rdf/type ccp/IAO_EXT_0000088)) ; CCP:ontology_concept_identifier
   :reify ([?/id {:ln (:localname ?/ontology_concept)
                  :ns "ccp" :prefix "" :suffix ""}])
   :sparql-string "prefix franzOption_chunkProcessingAllowed: <franz:yes>
                   prefix ccp: <http://ccp.ucdenver.edu/obo/ext/>
                   prefix obo: <http://purl.obolibrary.org/obo/>
                   select ?ontology_concept {
-                  ?root_id rdf:type ccp:IAO_EXT_0000190 . # ccp:ontology root concept identifier
-                  ?root_id obo:IAO_0000219 ?root_class . # obo:denotes
+                  ?root_id rdf:type ccp:IAO_EXT_0000190 . # CCP:ontology root concept identifier
+                  ?root_id obo:IAO_0000219 ?root_class . # IAO:denotes
                   ?ontology_concept rdfs:subClassOf* ?root_class .
                   minus {?ontology_concept owl:deprecated true} .
-                  minus {?ontology_concept rdf:type ccp:IAO_EXT_0000190} . # ccp:ontology root concept identifier
+                  minus {?ontology_concept rdf:type ccp:IAO_EXT_0000190} . # CCP:ontology_root_concept_identifier
                   # include only concepts with the OBO namespace
                   filter (contains (str(?ontology_concept), 'http://purl.obolibrary.org/obo/'))
                   # exclude ICE world concepts (IAO, CCP extension ontology, OA ontology)


Add error handling

Add error handling

--- frontend/src/cruncher/utils/lib.cljs
+++ frontend/src/cruncher/utils/lib.cljs
@@ -7,7 +7,8 @@
          (atom
            {:pokemon []
             :user {:view :default
-                   :logged-in? false}}))
+                   :logged-in? false}
+            :error {:message nil}}))

 ;;;; React compatibility
@@ -44,9 +45,9 @@
   [{:keys [state]} _ {:keys [view]}]
   {:action (fn [] (swap! state update-in [:user :view] (fn [] view)))})

-(defmethod mutate 'increment
-    [{:keys [state]} _ {:keys [pokemon]}]
-    {:action (fn [] (swap! state update-in [:count] inc))})
+(defmethod mutate 'update/error
+    [{:keys [state]} _ {:keys [message]}]
+    {:action (fn [] (swap! state update-in [:error :message] (fn [] message)))})

 (defonce reconciler
          (om/reconciler
@@ -81,6 +82,29 @@
   [key]
   (om/transact! reconciler `[(change/view {:view ~key})]))

+
+;;;; Error messages
+(defn error?
+  "Return boolean if there is an error message."
+  []
+  (let [message (get-in @app-state [:error :message])]
+    (pos? (count message))))
+
+(defn error!
+  "Set error message."
+  [message]
+  (om/transact! reconciler `[(update/error {:message ~message})]))
+
+(defn no-error!
+  "Reset error message."
+  []
+  (error! nil))
+
+(defn get-error
+  "Return error message."
+  []
+  (get-in @app-state [:error :message]))
+
 ;;;; State transitions
 (defn update-pokemon!
   "Update pokemon based on API response."


parameterized multi-path test

parameterized multi-path test

--- test/com/rpl/specter/core_test.cljc
+++ test/com/rpl/specter/core_test.cljc
@@ -489,5 +489,37 @@
            ))
     ))

-;; TODO: test multi-path with params
-
+(defspec param-multi-path-test
+  (for-all+
+    [k1 gen/keyword
+     k2 gen/keyword
+     k3 gen/keyword
+     m (limit-size 5
+         (gen-map-with-keys
+           gen/keyword
+           gen/int
+           k1
+           k2
+           k3
+           ))
+     pred1 (gen/elements [odd? even?])
+     pred2 (gen/elements [odd? even?])
+     updater (gen/elements [inc dec])
+     ]
+     (let [paths [((s/multi-path [s/keypath pred1] [s/keypath pred2] k3) k1 k2)
+                  ((s/multi-path [k1 pred1] [s/keypath pred2] s/keypath) k2 k3)
+                  ((s/multi-path [s/keypath pred1] [s/keypath pred2] s/keypath) k1 k2 k3)
+                  (s/multi-path [k1 pred1] [k2 pred2] k3)
+                  ((s/multi-path [k1 pred1] [s/keypath pred2] k3) k2)
+                  ]]
+      (and
+        (apply =
+          (for [p paths]
+            (s/select p m)
+            ))
+        (apply =
+          (for [p paths]
+            (s/transform p updater m)
+            ))
+        ))))
+


unit tests for splitting

unit tests for splitting

--- test/adventofcode1/twentyfour_test.clj
+++ test/adventofcode1/twentyfour_test.clj
@@ -56,7 +56,24 @@
   (is (= [ {:from [1 1], :to [1 9]} ] (horizontal-paths board-4 1))))

 (deftest vertical-paths-tests
-  (is (= [ {:from [1 1], :to [1 3]} ] (vertical-paths board-4 1)))
+  (is (= [ {:from [1 1], :to [3 1]} ] (vertical-paths board-4 1)))
   (is (= [  ]                         (vertical-paths board-4 3)))
-  (is (= [ {:from [5 1], :to [5 3]} ] (vertical-paths board-4 5)))
-  (is (= [ {:from [9 1], :to [9 3]} ] (vertical-paths board-4 9))))
+  (is (= [ {:from [1 5], :to [3 5]} ] (vertical-paths board-4 5)))
+  (is (= [ {:from [1 9], :to [3 9]} ] (vertical-paths board-4 9))))
+
+(deftest split-horizontal-path-at-test
+  ;; path: ({:from [1 1], :to [1 9]} {:from [3 1], :to [3 9]})
+  (let [path (horizontal-paths board-4)]
+    ;; first row
+    (is (= '((101 1 1) (101 1 3) (3 1 5) (101 1 9))
+           (split-horizontal-path-at board-4 (first path))))
+    ;; 3rd row, since no path on 2nd row and exactly one path on first
+    (is (= '((101 3 1) (3 3 5) (101 3 9))
+           (split-horizontal-path-at board-4 (second path))))))
+
+(deftest split-vertical-path-at-test
+  ;; path: ({:from [1 1], :to [3 1]} {:from [1 5], :to [3 5]} {:from [1 9], :to [3 9]})
+  (let [path (vertical-paths board-4)
+        _ (println path)]
+    (is (= '((101 1 1) (101 3 1))
+           (split-vertical-path-at board-4 (first path))))))


Swapped latlons for MODIS coordinates, started latlon calc

--- test/forma/postprocess/select_test.clj
+++ test/forma/postprocess/select_test.clj
@@ -7,7 +7,8 @@
         [forma.matrix.utils :only (transpose)]
         [forma.utils :only (positions)]
         [forma.date-time :only (period->datetime datetime->period)]
-        [forma.trends.data :only (ndvi rain reli)])
+        [forma.trends.data :only (ndvi rain reli)]
+        [forma.reproject :only (modis->latlon)])
   (:require [incanter.core :as i]
             [incanter.charts :as chart]
             [forma.testing :as t]
@@ -33,59 +34,105 @@
 (def sample-output-map
   [{:cntry       "IDN"
     :admin       23456
-    :lat         45
-    :lon         90
-    :pixel       5
+    :modh 28
+    :modv 7
+    :line 5
+    :sample 10
     :prob-series (schema/timeseries-value
                   (end-training "16")
                   [0.1 0.2 0.4 0.7 0.9])
     :tres        "16"
-    :sres        500
+    :sres        "500"
     :hansen      0}
    {:cntry       "IDN"
     :admin       23456
-    :lat         46
-    :lon         91
-    :pixel       6
+    :modh 28
+    :modv 7
+    :line 5
+    :sample 9
     :prob-series (schema/timeseries-value
                   (end-training "16")
                   [0.1 0.1 0.1 0.1 0.1])
     :tres        "16"
-    :sres        500
+    :sres        "500"
     :hansen      1}
    {:cntry       "IDN"
     :admin       23456
-    :lat         45.2
-    :lon         90.1
-    :pixel       7
+    :modh 28
+    :modv 7
+    :line 4
+    :sample 10
     :prob-series (schema/timeseries-value
                   (end-training "16")
                   [0.1 0.2 0.4 0.7 0.9])
     :tres        "16"
-    :sres        500
+    :sres        "500"
     :hansen      0}
    {:cntry       "IDN"
     :admin       23456
-    :lat         45.3
-    :lon         90.2
-    :pixel       8
+    :modh 28
+    :modv 7
+    :line 5
+    :sample 11
     :prob-series (schema/timeseries-value
                   (end-training "16")
                   [0.1 0.6 0.6 0.65 0.9])
     :tres         "16"
-    :sres         500
+    :sres        "500"
     :hansen       1}
    {:cntry       "MYS"
     :admin       12345
-    :lat         32
-    :lon         89
-    :pixel       5
+    :modh 28
+    :modv 7
+    :line 4
+    :sample 9
     :prob-series (schema/timeseries-value
                   (end-training "16")
                   [0.1 0.2 0.4 0.7 0.9])
     :tres        "16"
-    :sres        500
+    :sres        "500"
     :hansen      1}])
+
+
+;; (defn latlon-series
+;;   [res out-m]
+;;   (modis->latlon  ))
+
+(defn grab-modis-coords
+  [m]
+  (vec (map #(get m %) [:sres :modh :modv :sample :line])))
+
+(defn grab-series
+  [m]
+  (:series (:prob-series m)))
+
+(defn convert-to-latlon
+  [out-m]
+  (let [series (grab-series out-m)
+        [res modh modv sample line] (grab-modis-coords out-m)]
+    (modis->latlon res modh modv sample line)))
+
+(def latlon-series-tap
+  (<- [?lat ?lon ?series]
+      (sample-output-map ?m)
+      (convert-to-latlon ?m :> ?lat ?lon ?series)))
+
+(fact
+  (grab-modis-coords (first sample-output-map)) => [500 28 7 10 5])
+
+(fact
+  (grab-series (first sample-output-map)) => [0.1 0.2 0.4 0.7 0.9])
+
+(fact
+  (convert-to-latlon (first sample-output-map)) => [5])
+
+;; (deftest adding-latlon
+;;   (fact
+;;     (get-latlon-series sample-output-map) => (produces [{:lat 1 :lon 1 }])))
+
+;; (def sample-pixel-map
+;;   (schema/pixel-location "500" 28 7 5 10)
+;;   (modis->latlon ))

 (defmapcatop grab-sig-pixels
   "return a vector of three-tuples, with the country iso code, the
@@ -93,7 +140,7 @@
   the alert.  If the probability of clearing never exceeds the
   threshold, then a stand-in three-tuple is returned."
   [res out-m thresh]
-  (let [series (:series (:prob-series out-m))
+  (let [series (grab-series out-m)
         idx (positions #(> % thresh) series)
         offset (end-training res)]
     (if (empty? idx)
@@ -120,7 +167,3 @@
                          ["MYS" 830 0.7]
                          ["MYS" 831 0.9]
                          ["nil" 0 0]])))
-
-
-
-


Improve test comment

Improve test comment

--- test/onyx/plugin/input_resume_test.clj
+++ test/onyx/plugin/input_resume_test.clj
@@ -108,7 +108,7 @@
   {:lifecycle/before-batch
    (fn [event lifecycle]
      ; give the peer a bit of time to write the chunks out and ack the batches,
-     ; since we want to ensure that the batches aren't re-read on restart
+     ; since we want to ensure that the batches aren't re-read on restart for ease of testing
      (Thread/sleep 7000)
      (when (= (swap! batch-num inc) 2)
        (throw (ex-info "Restartable" {:restartable? true}))))})


CW |13| user cannot sign in with invalid client-secret or invalid password

--- test/stonecutter/integration/oauth.clj
+++ test/stonecutter/integration/oauth.clj
@@ -36,6 +36,7 @@
 (def client (client/register-client "myclient" "myclient.com"))
 (def client-id (:client-id client))
 (def client-secret (:client-secret client))
+(def invalid-client-secret (str/reverse client-secret))

 (def user (user/register-user "email@server.com" "valid-password"))

@@ -85,3 +86,32 @@
            (client-sends-token-request client-id client-secret)
            ;; return 200 with new access_token
            (kh/response-has-access-token)))
+
+(facts "no access token will be issued with invalid credentials"
+       (facts "user cannot sign in with invalid client secret"
+              (-> (k/session h/app)
+                  (client-sends-authorisation-request client-id)
+                  (k/follow-redirect)
+                  ;; login
+                  (kh/page-uri-is "/login")
+                  (k/fill-in :.func--email__input "email@server.com")
+                  (k/fill-in :.func--password__input "valid-password")
+                  (k/press :.func--sign-in__button)
+                  ;; check redirect - should have auth_code
+                  (k/follow-redirect)
+                  (kh/location-contains "callback?code=")
+                  (client-sends-token-request client-id invalid-client-secret)
+                  :response
+                  :status) => 400)
+
+       (facts "user cannot sign in with invalid password"
+              (-> (k/session h/app)
+                  (client-sends-authorisation-request client-id)
+                  (k/follow-redirect)
+                  ;; login
+                  (kh/page-uri-is "/login")
+                  (k/fill-in :.func--email__input "email@server.com")
+                  (k/fill-in :.func--password__input "invalid-password")
+                  (k/press :.func--sign-in__button)
+                  :response
+                  :status) => 400))


Bring tests in accordance with new api

Bring tests in accordance with new api

--- test/clojure/clojurewerkz/cassaforte/new_query_api_test.clj
+++ test/clojure/clojurewerkz/cassaforte/new_query_api_test.clj
@@ -19,7 +19,6 @@

   (is (=  "SELECT * FROM foo WHERE foo='bar' AND moo>3 AND meh>4 AND baz IN (5,6,7);"
           (select :foo
-                  (all)
                   (where [[= :foo "bar"]
                           [> :moo 3]
                           [:> :meh 4]
@@ -28,20 +27,17 @@

   (is (=  "SELECT * FROM foo WHERE foo='bar' ORDER BY foo ASC;"
           (select :foo
-                  (all)
                   (order-by [(asc :foo)])
                   (where [[= :foo "bar"]]))))

   (is (=  "SELECT * FROM foo WHERE foo='bar' ORDER BY foo ASC LIMIT 10;"
           (select :foo
-                  (all)
                   (order-by [(asc :foo)])
                   (limit 10)
                   (where [[= :foo "bar"]]))))

   (is (=  "SELECT * FROM foo WHERE foo='bar' ORDER BY foo ASC LIMIT 10 ALLOW FILTERING;"
           (select :foo
-                  (all)
                   (where [[= :foo "bar"]])
                   (order-by [(asc :foo)])
                   (limit 10)
@@ -50,19 +46,22 @@

   (is (=  "SELECT * FROM foo WHERE k=4 AND c>'a' AND c<='z';";
           (select :foo
-                  (all)
                   (where [[= :k 4]
                           [> :c "a"]
                           [<= :c "z"]])
                   )))
-  (println (select :foo
-                   (columns [(-> "asd"
-                                 distinct*
-                                 (as "bsd"))]

-                            )))
+  (is (= "SELECT DISTINCT asd AS bsd FROM foo;")
+      (select :foo
+              (columns [(-> "asd"
+                            distinct*
+                            (as "bsd"))])))
+
+
+
+
   ;; "SELECT DISTINCT longName AS a,ttl(longName) AS ttla FROM foo LIMIT :limit;";
-;; select().distinct().column("longName").as("a").ttl("longName").as("ttla").from("foo").limit(bindMarker("limit"));
+  ;; select().distinct().column("longName").as("a").ttl("longName").as("ttla").from("foo").limit(bindMarker("limit"));

   )


uppercase projects

uppercase projects

--- app/src/cljs/app/components.cljs
+++ app/src/cljs/app/components.cljs
@@ -69,7 +69,7 @@
   [:div#projects
    [section-component
     [:div.mdl-grid--no-spacing
-     [:h3.projectsheader.mdl-cell.mdl-cell--12-col "projects"]
+     [:h3.projectsheader.mdl-cell.mdl-cell--12-col "Projects"]
      [:div
       (into [:div.project.mdl-grid]
             (map #(single-project-component %) projects))]]]])
@@ -98,11 +98,13 @@

 (defn single-education-component
   [education]
-  [:div.education.mdl-card
-   [:div.education--period--institution.
-    [:div.mdl-card__title-text
+  [:div.education
+   [:div.education--period--institution.mdl-grid
+    [:div.mdl-cell-mdl-cell--4-col.eduperiod
      [:h4 (:period education)]]
-    [:div.mdl-card__title-text
+    [:div.mdl-cell-mdl-cell--4-col-offset
+     [:span ""]]
+    [:div.mdl-cell-mdl-cell--8-col.eduinstitution
      [:h4 (:institution education)]]]
    [:div.education--degree
     [:div.degree


Fix --disable-metric-store

Fix --disable-metric-store

--- src/whisper2cyanite/core.clj
+++ src/whisper2cyanite/core.clj
@@ -38,7 +38,7 @@
             ttl (calc-ttl time retention)]
         (when (> ttl min-ttl)
           (log-point "Migrating point" rollup period path time value ttl)
-          (when (and run mstore)
+          (when run
             (mstore/insert mstore tenant rollup period path time value
                            ttl)))))))

@@ -62,28 +62,27 @@
 (defn- validate-points
   "Validate points."
   [mstore options tenant rollup period retention path series]
-  (when mstore
-    (let [series (whisper/sort-series series)
-          from (first (first series))
-          to (first (last series))
-          min-ttl (:min-ttl options default-min-ttl)
-          mstore-series (mstore/fetch-series mstore tenant rollup period path
-                                             from to)
-          error-reported? (atom false)
-          validators [[#(not= %2 nil) "Point not found"]
-                      [#(sequential? %2) "Value is not an array"]
-                      [#(= (count %2) 1) "Array size is not equal to 1"]
-                      [#(= %1 (first %2)) "Values are not equal"]]]
-      (doseq [point series]
-        (let [time (first point)
-              w-value (last point)
-              ttl (calc-ttl time retention)]
-          (when (> ttl min-ttl)
-            (log-point "Validating point" rollup period path time w-value ttl)
-            (let [s-value (get mstore-series time)]
-              (every? #(validate-value rollup period path time w-value s-value
-                                       (first %) (second %) error-reported?)
-                      validators))))))))
+  (let [series (whisper/sort-series series)
+        from (first (first series))
+        to (first (last series))
+        min-ttl (:min-ttl options default-min-ttl)
+        mstore-series (mstore/fetch-series mstore tenant rollup period path
+                                           from to)
+        error-reported? (atom false)
+        validators [[#(not= %2 nil) "Point not found"]
+                    [#(sequential? %2) "Value is not an array"]
+                    [#(= (count %2) 1) "Array size is not equal to 1"]
+                    [#(= %1 (first %2)) "Values are not equal"]]]
+    (doseq [point series]
+      (let [time (first point)
+            w-value (last point)
+            ttl (calc-ttl time retention)]
+        (when (> ttl min-ttl)
+          (log-point "Validating point" rollup period path time w-value ttl)
+          (let [s-value (get mstore-series time)]
+            (every? #(validate-value rollup period path time w-value s-value
+                                     (first %) (second %) error-reported?)
+                    validators)))))))

 (defn- process-archive
   "Process an archive."
@@ -116,21 +115,22 @@
   (let [path (whisper/file-to-name file dir)]
     (when path-fn
       (path-fn pstore tenant path))
-    (let [ra-file (RandomAccessFile. file "r")
-          rollups (:rollups options)]
-      (try
-        (let [info (whisper/read-info-ra ra-file file)
-              archives (:archives info)]
-          (doseq [archive archives]
-            (let [seconds-per-point (:seconds-per-point archive)]
-              (when (or (not (> (count rollups) 0))
-                        (contains? rollups seconds-per-point))
-                (let [retention (get rollups seconds-per-point
-                                     (:retention archive))]
-                  (process-archive ra-file file archive mstore tenant path
-                                   from to retention options points-fn))))))
-        (finally
-          (.close ra-file))))))
+    (when mstore
+      (let [ra-file (RandomAccessFile. file "r")
+            rollups (:rollups options)]
+        (try
+          (let [info (whisper/read-info-ra ra-file file)
+                archives (:archives info)]
+            (doseq [archive archives]
+              (let [seconds-per-point (:seconds-per-point archive)]
+                (when (or (not (> (count rollups) 0))
+                          (contains? rollups seconds-per-point))
+                  (let [retention (get rollups seconds-per-point
+                                       (:retention archive))]
+                    (process-archive ra-file file archive mstore tenant path
+                                     from to retention options points-fn))))))
+          (finally
+            (.close ra-file)))))))

 (defn- get-paths
   "Get paths."


CMR-4239 - Fixed variable association test.

--- system-int-test/test/cmr/system_int_test/search/variable/variable_association_test.clj
+++ system-int-test/test/cmr/system_int_test/search/variable/variable_association_test.clj
@@ -15,9 +15,7 @@
 (use-fixtures
  :each
  (join-fixtures
-  [(ingest/reset-fixture {"provguid1" "PROV1"
-                          "provguid2" "PROV2"
-                          "provguid3" "PROV3"}
+  [(ingest/reset-fixture {"provguid1" "PROV1" "provguid2" "PROV2" "provguid3" "PROV3"}
                          {:grant-all-search? false})
    vu/grant-all-variable-fixture]))

@@ -30,24 +28,19 @@
   ;; Create 4 collections in each provider that are identical.
   ;; The first collection will have data:
   ;; {:entry-id "S1_V1", :entry_title "ET1", :short-name "S1", :version-id "V1"}
-  (let [{token :token} (vu/setup-update-acl
-                        (s/context) "PROV1" "user1" "update-group")
-        [c1-p1 c2-p1 c3-p1 c4-p1
+  (let [[c1-p1 c2-p1 c3-p1 c4-p1
          c1-p2 c2-p2 c3-p2 c4-p2
          c1-p3 c2-p3 c3-p3 c4-p3] (for [p ["PROV1" "PROV2" "PROV3"]
                                         n (range 1 5)]
                                     (:concept-id (d/ingest p (dc/collection
                                                               {:short-name (str "S" n)
                                                                :version-id (str "V" n)
-                                                               :entry-title (str "ET" n)}
-                                                              {:token token}))))
+                                                               :entry-title (str "ET" n)}))))
         all-prov1-colls [c1-p1 c2-p1 c3-p1 c4-p1]
         all-prov2-colls [c1-p2 c2-p2 c3-p2 c4-p2]
+        token (e/login (s/context) "user1")
         variable-name "variable1"
-        variable (vu/make-variable-concept {:Name variable-name})
-        {:keys [concept-id] :as response} (vu/ingest-variable
-                                           variable
-                                           (vu/token-opts token))]
+        {:keys [concept-id]} (vu/ingest-variable-with-attrs {:Name variable-name})]
     (index/wait-until-indexed)

     (testing "Associate variable with collections by concept-ids"
@@ -114,12 +107,8 @@
 (deftest associate-variable-failure-test
   (e/grant-registered-users (s/context) (e/coll-catalog-item-id "PROV1"))
   (let [variable-name "variable1"
-        variable (vu/make-variable-concept {:Name variable-name})
-        {token :token} (vu/setup-update-acl
-                        (s/context) "PROV1" "user1" "update-group")
-        {:keys [concept-id revision-id]} (vu/create-variable token variable)
-        ;; The stored updated variable would have user1 in the originator id
-        variable (assoc variable :originator-id "user1")
+        token (e/login (s/context) "user1")
+        {:keys [concept-id revision-id]} (vu/ingest-variable-with-attrs {:Name variable-name})
         coll-concept-id (:concept-id (d/ingest "PROV1" (dc/collection)))]
     (testing "Associate variable using query sent with invalid content type"
       (are [associate-variable-fn request-json]
@@ -185,13 +174,9 @@
         all-prov3-colls [c1-p3 c2-p3 c3-p3 c4-p3]
         all-colls (concat all-prov1-colls all-prov2-colls all-prov3-colls)
         variable-name "variable1"
-        variable (vu/make-variable-concept {:Name variable-name})
-        {token :token} (vu/setup-update-acl
-                        (s/context) "PROV1" "user1" "update-group")
+        token (e/login (s/context) "user1")
         prov3-token (e/login (s/context) "prov3-user" [group1-concept-id])
-        {:keys [concept-id]} (vu/ingest-variable
-                              variable
-                              (vu/token-opts token))
+        {:keys [concept-id]} (vu/ingest-variable-with-attrs {:Name variable-name})
         assert-variable-associated (partial vu/assert-variable-associated-with-query
                                             prov3-token {:variable-name "variable1"})]
     (index/wait-until-indexed)
@@ -241,14 +226,8 @@
 (deftest dissociate-variable-failure-test
   (e/grant-registered-users (s/context) (e/coll-catalog-item-id "PROV1"))
   (let [variable-name "variable1"
-        variable (vu/make-variable-concept {:Name variable-name})
-        {token :token} (vu/setup-update-acl
-                        (s/context) "PROV1" "user1" "update-group")
-        {:keys [concept-id revision-id]} (vu/ingest-variable
-                                          variable
-                                          (vu/token-opts token))
-        ;; The stored updated variable would have user1 in the originator id
-        variable (assoc variable :originator-id "user1")
+        token (e/login (s/context) "user1")
+        {:keys [concept-id revision-id]} (vu/ingest-variable-with-attrs {:Name variable-name})
         coll-concept-id (:concept-id (d/ingest "PROV1" (dc/collection)))]

     (testing "Dissociate variable using query sent with invalid content type"
@@ -297,12 +276,11 @@
     (let [coll1 (d/ingest "PROV1" (dc/collection {:entry-title "ET1"}))
           coll2 (d/ingest "PROV1" (dc/collection {:entry-title "ET2"}))
           coll3 (d/ingest "PROV1" (dc/collection {:entry-title "ET3"}))
-          {token :token} (vu/setup-update-acl
-                        (s/context) "PROV1" "user1" "update-group")
+          token (e/login (s/context) "user1")
           variable-name "variable1"
           assert-variable-associated (partial vu/assert-variable-associated-with-query
                                               token {:variable-name "variable1"})]
-      (vu/create-variable token (vu/make-variable {:Name variable-name}))
+      (vu/ingest-variable-with-attrs {:Name variable-name})
       (index/wait-until-indexed)
       (vu/associate-by-concept-ids token variable-name [{:concept-id (:concept-id coll1)}
                                                         {:concept-id (:concept-id coll2)
@@ -390,10 +368,9 @@
   (let [[coll1 coll2 coll3] (for [n (range 1 4)]
                               (d/ingest "PROV1" (dc/collection)))
         [coll1-id coll2-id coll3-id] (map :concept-id [coll1 coll2 coll3])
-        {token :token} (vu/setup-update-acl
-                        (s/context) "PROV1" "user1" "update-group")]
-    (vu/create-variable token (vu/make-variable {:Name "variable1"}))
-    (vu/create-variable token (vu/make-variable {:Name "variable2"}))
+        token (e/login (s/context) "user1")]
+    (vu/ingest-variable-with-attrs {:Name "variable1"})
+    (vu/ingest-variable-with-attrs {:Name "variable2"})
     (index/wait-until-indexed)

     ;; associate variable1 to coll1, variable2 to coll2


Improved tests

Improved tests

--- test/buddy/hashers_tests.clj
+++ test/buddy/hashers_tests.clj
@@ -16,6 +16,8 @@
   (:require [clojure.test :refer :all]
             [buddy.core.codecs :refer :all]
             [buddy.core.nonce :as nonce]
+            [buddy.core.bytes :as bytes]
+            [buddy.core.codecs :as codecs]
             [buddy.hashers :as hashers]))

 (deftest buddy-hashers
@@ -25,6 +27,7 @@
           (hashers/check pwd result))
       :pbkdf2+sha1
       :pbkdf2+sha256
+      :pbkdf2+sha512
       :pbkdf2+sha3_256
       :pbkdf2+blake2b-512
       :bcrypt+sha512
@@ -41,6 +44,7 @@
           (hashers/check pwd result))
       :pbkdf2+sha1
       :pbkdf2+sha256
+      :pbkdf2+sha512
       :pbkdf2+sha3_256
       :pbkdf2+blake2b-512
       :bcrypt+sha512
@@ -58,6 +62,7 @@
           (not (hashers/check pwd-bad result)))
       :pbkdf2+sha1
       :pbkdf2+sha256
+      :pbkdf2+sha512
       :pbkdf2+sha3_256
       :pbkdf2+sha3-256
       :pbkdf2+blake2b-512
@@ -82,6 +87,7 @@
             (.startsWith (name alg)))
       :pbkdf2+sha1
       :pbkdf2+sha256
+      :pbkdf2+sha512
       :pbkdf2+sha3_256
       :pbkdf2+sha3-256
       :pbkdf2+blake2b-512
@@ -104,6 +110,7 @@
             (.startsWith (str (name alg) "$" ( bytes->hex salt))))
       :pbkdf2+sha1
       :pbkdf2+sha256
+      :pbkdf2+sha512
       :pbkdf2+sha3_256
       :pbkdf2+sha3-256
       :pbkdf2+blake2b-512
@@ -127,26 +134,54 @@
     (is (hashers/check "hello" pwd {:setter #(deliver p %)}))
     (is (= (deref p 10 nil) "hello"))))

+(deftest update-policy-for-pbkdf2+sha256
+  (let [pwd-legacy "pbkdf2+sha256$7d0994313982465d82372493$100000$98c4b3043b30622917516e97d1c6bd9936337e8c"
+        pwd-new1 "pbkdf2+sha256$b676896c5e9ab9e21b7feafb0d1b8a1b$100000$7af67cae17babcf5cfc20f4f95878b9477023b2797a0e6942aeef567cd4bf1b2"
+        pwd-new2 (hashers/encrypt "test" {:alg :pbkdf2+sha256})
+        p1 (promise)
+        p2 (promise)
+        p3 (promise)]
+    (is (hashers/check "test" pwd-legacy {:setter #(deliver p1 %)}))
+    (is (hashers/check "test" pwd-new1 {:setter #(deliver p2 %)}))
+    (is (hashers/check "test" pwd-new2 {:setter #(deliver p3 %)}))
+    (is (= (deref p1 10 nil) "test"))
+    (is (= (deref p2 10 nil) nil))
+    (is (= (deref p3 10 nil) nil))))
+
+(deftest update-policy-for-bcrypt+sha512
+  (let [pwd-legacy "bcrypt+sha512$680bf9ad0bf9f8249bfebb85$12$243261243132244b4e2e4e456650704558323964686e6c64644f4b73656a6879584f635a4f6b7778596132475036772e6c2e784f49596631556f7679"
+        pwd-new "bcrypt+sha512$b932bf208c7f3ecb563eebe89c39115b$12$bc3633d1f07c47edd91f0e7cf5649b040ea868cec63cda31"
+        p1 (promise)
+        p2 (promise)]
+    (is (hashers/check "test" pwd-legacy {:setter #(deliver p1 %)}))
+    (is (hashers/check "test" pwd-new {:setter #(deliver p2 %)}))
+    (is (= (deref p1 10 nil) "test"))
+    (is (= (deref p2 10 nil) nil))))
+
 (deftest possible-regressions-checker
   (let [pbkdf2+sha1 "pbkdf2+sha1$fcf7c2e5848193f91d8a5a40$100000$b499843df692e02be67e534f8592a0785927843a"
-        pbkdf2+sha256b "pbkdf2+sha256b$7d0994313982465d82372493$100000$98c4b3043b30622917516e97d1c6bd9936337e8c"
-        pbkdf2+sha256 "pbkdf2+sha256$d4043ce1e9e1f9eb9a198b54$100000$71526da5155651ed0eea37d13f728e802c54cf2a3e205b0dbbbfd1f2f169d5a3"
+        pbkdf2+sha256-legacy "pbkdf2+sha256$7d0994313982465d82372493$100000$98c4b3043b30622917516e97d1c6bd9936337e8c"
+        pbkdf2+sha256 "pbkdf2+sha256$092c7d26206ae9641d225ca432a9efcf$100000$76417ba855c352750319ae649141082bfa83e18ba3a4937580ae7d0226168c6a"
+        pbkdf2+sha512 "pbkdf2+sha512$50577ebbbe53552a270598fd$100000$ee0b82c8887fc4bac8e8a28a785e2c7d679fc87a4c42478302ae40acad84aae77fdd2bce57b75595250c1a0226dbbdc4b94954ec61c7d2188d82ea15bce67af5"
         pbkdf2+sha3_256 "pbkdf2+sha3_256$1278c96b4e68b98c633041dc$5000$d89f67636fec62cdd8379f8ff9305bece38f09b20659916d41cf91eacd91a85b"
         pbkdf2+sha3-256 "pbkdf2+sha3-256$1278c96b4e68b98c633041dc$5000$d89f67636fec62cdd8379f8ff9305bece38f09b20659916d41cf91eacd91a85b"
         pbkdf2+blake2b-512 "pbkdf2+blake2b-512$1a26daa54a09150de9f5a053$5000$2fe5dde2355a179f88969218466cd587681af2ce7d6de07080d94efab7cec9e091b7b1c3a34311ff72a3a883f261619b67583c1742f661bb3ab65bc4402fd4c1"
         scrypt "scrypt$f54d4b5a1e8d8e63c82e1553$65536$8$1$24733024313030383031246850416d5378645243726664336350546b5a4c7330413d3d243448376945454c47395155492f2b477a42735a582f76554f3345495248656c6939734a73516c356e6571413d"
         sha256 "sha256$bbac53106f8ce4f8c2d78f86$2182339b43ed1546b21488922c2516b64917025084577b33fc49357d9dd2c673"
         bcrypt+blake2b-512 "bcrypt+blake2b-512$95d0488b2b69c79d4f48ab39338c322e$12$40a4ef31b6dd390b27bd6fc3c2fdeabfb1db85c9bef25c22"
-        bcrypt+sha512 "bcrypt+sha512$680bf9ad0bf9f8249bfebb85$12$243261243132244b4e2e4e456650704558323964686e6c64644f4b73656a6879584f635a4f6b7778596132475036772e6c2e784f49596631556f7679"
+        bcrypt+sha512-legacy "bcrypt+sha512$680bf9ad0bf9f8249bfebb85$12$243261243132244b4e2e4e456650704558323964686e6c64644f4b73656a6879584f635a4f6b7778596132475036772e6c2e784f49596631556f7679"
+        bcrypt+sha512 "bcrypt+sha512$b932bf208c7f3ecb563eebe89c39115b$12$bc3633d1f07c47edd91f0e7cf5649b040ea868cec63cda31"
         bcrypt+sha384 "bcrypt+sha384$5c3b8cc880e0dd91520a900a8c8c6223$12$fa6e0a810b81b04634b19311e77eb00ba1d0f12c570adafa"]
     (is (hashers/check "test" pbkdf2+sha1))
-    (is (hashers/check "test" pbkdf2+sha256b))
     (is (hashers/check "test" pbkdf2+sha256))
+    (is (hashers/check "test" pbkdf2+sha256-legacy))
+    (is (hashers/check "test" pbkdf2+sha512))
     (is (hashers/check "test" pbkdf2+sha3_256))
     (is (hashers/check "test" pbkdf2+sha3-256))
     (is (hashers/check "test" scrypt))
     (is (hashers/check "test" sha256))
     (is (hashers/check "test" pbkdf2+blake2b-512))
+    (is (hashers/check "test" bcrypt+sha512-legacy))
     (is (hashers/check "test" bcrypt+sha512))
     (is (hashers/check "test" bcrypt+sha384))
     (is (hashers/check "test" bcrypt+blake2b-512))
@@ -161,13 +196,14 @@
           true)
       :pbkdf2+sha1
       :pbkdf2+sha256
-      :pbkdf2+sha3_256
-      :pbkdf2+sha3-256
-      :pbkdf2+blake2b-512
-      :bcrypt+sha512
-      :bcrypt+sha384
-      :bcrypt+blake2b-512
-      :scrypt
-      :sha256
-      :md5)))
-
+      :pbkdf2+sha512
+      :pbkdf2+sha3_256
+      :pbkdf2+sha3-256
+      :pbkdf2+blake2b-512
+      :bcrypt+sha512
+      :bcrypt+sha384
+      :bcrypt+blake2b-512
+      :scrypt
+      :sha256
+      :md5)))
+


Fix test name

Fix test name

--- test/build_mon/test/core.clj
+++ test/build_mon/test/core.clj
@@ -51,7 +51,7 @@
                successful-build-html => (contains "<link rel=\"shortcut icon\" href=\"favicon_green.ico\" />"))
          (fact "body has a green background"
                successful-build-html => (contains "<body style=\"background-color:green;\">"))
-         (fact "font colour is black"
+         (fact "font colour is white"
                successful-build-html => (contains "<h1 style=\"color:white;font-size:400%;text-align:center;\">")))

        (fact "refresh line is generated when refresh value is passed"


Fix test

Fix test

--- test/expound/alpha_test.cljc
+++ test/expound/alpha_test.cljc
@@ -1534,7 +1534,8 @@
   (st/instrument `test-instrument-adder)
   #?(:cljs
      (is (=
-          "Call to #'expound.alpha-test/test-instrument-adder did not conform to spec:
+          (if (spec-error-in-ex-msg?)
+            "Call to #'expound.alpha-test/test-instrument-adder did not conform to spec:
 <filename missing>:<line number missing>

 -- Spec failed --------------------
@@ -1550,6 +1551,8 @@

 -------------------------
 Detected 1 error\n"
+            "Call to #'expound.alpha-test/test-instrument-adder did not conform to spec.")
+
           (.-message (try
                        (binding [s/*explain-out* (expound/custom-printer {:show-valid-values? true})]
                          (test-instrument-adder "" :x))


ARM: EXYNOS: add dts files to dtbs target

Add the currently in-tree device tree sources to the dtbs target.

Signed-off-by: Olof Johansson <8c69ee23f3f44f8162a64d579c1fa25c2f55298a@lixom.net>
Signed-off-by: Kukjin Kim <3fc711f4e08bc570a586748633ff7c76d0e1e253@samsung.com>

--- arch/arm/mach-exynos/Makefile.boot
+++ arch/arm/mach-exynos/Makefile.boot
@@ -1,2 +1,5 @@
    zreladdr-y	+= 0x40008000
 params_phys-y	:= 0x40000100
+
+dtb-$(CONFIG_MACH_EXYNOS4_DT) += exynos4210-origen.dtb exynos4210-smdkv310.dtb
+dtb-$(CONFIG_MACH_EXYNOS5_DT) += exynos5250-smdk5250.dtb


Add initial round of tests.

Add initial round of tests.

--- test/multihash/core_test.clj
+++ test/multihash/core_test.clj
@@ -4,6 +4,44 @@
     [multihash.core :as multihash]))

-(deftest a-test
-  (testing "FIXME, I fail."
-    (is (= 0 1))))
+(deftest app-specific-codes
+  (is (false? (multihash/app-code? 0x00)))
+  (doseq [code (range 0x01 0x10)]
+    (is (true? (multihash/app-code? code))
+        (str "Algorithm code " code " is app-specific")))
+  (doseq [code (range 0x10 0x100)]
+    (is (false? (multihash/app-code? code))
+        (str "Algorithm code " code " is not app-specific"))))
+
+
+(def examples
+  "Test case examples."
+  {"11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
+   [0x11 :sha1 20 "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"]
+
+   "11040beec7b8"
+   [0x11 :sha1 4 "0beec7b8"]
+
+   "12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"
+   [0x12 :sha2-256 32 "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"]
+
+   "12042c26b46b"
+   [0x12 :sha2-256 4 "2c26b46b"]
+
+   "40042c26b46b"
+   [0x40 :blake2b 4 "2c26b46b"]})
+
+
+(deftest example-decoding
+  (doseq [[encoded [code algorithm length digest]] examples]
+    (let [mhash (multihash/decode encoded)]
+      (is (= code (:code mhash)))
+      (is (= algorithm (:algorithm mhash)))
+      (is (= length (:length mhash)))
+      (is (= digest (:digest mhash))))))
+
+
+(deftest example-encoding
+  (doseq [[encoded [code algorithm length digest]] examples]
+    (let [mhash (multihash/create algorithm digest)]
+      (is (= encoded (multihash/encode mhash))))))


Tests for add

Tests for add

--- test/ts_layout/core_test.clj
+++ test/ts_layout/core_test.clj
@@ -3,13 +3,13 @@
             [ts-layout.core :refer :all]))

 (defn request [resource web-app method & params]
-   (web-app {:request-method method :uri resource :params (first params)}))
+   )

 (defn get-it [resource web-app & params]
-  (apply (partial request resource web-app :get) params))
+  (web-app {:request-method :get :uri resource :params (first params)}))

-(defn post-it [resource web-app & params]
-  (apply (partial request resource web-app :post) params))
+(defn post-it [resource web-app body]
+  (web-app {:request-method :post :uri resource :body (java.io.ByteArrayInputStream. (.getBytes body))}))

 (deftest root
   (let [response (get-it "/" app)]
@@ -34,3 +34,8 @@
   (let [response (get-it "/boxes/0/delete" app)]
     (is (= 302 (:status response)))
     (is (= {"Location" "/boxes"} (:headers response)))))
+
+(deftest add
+  (let [response (post-it "/boxes/add" app "url=floop")]
+    (is (= 302 (:status response)))
+    (is (= {"Location" "/boxes"} (:headers response)))))


Fixed silent logging in tests

Fixed silent logging in tests

--- test/varjocafe/core_test.clj
+++ test/varjocafe/core_test.clj
@@ -115,10 +115,10 @@
               (core/enrich-exceptions today [{:from "24.12.2014-28.12.2014", :to nil, :closed true, :open "", :close nil}])
               => [{:from (t/local-date 2014 12 24), :to (t/local-date 2014 12 28), :closed true}])

-        (fact ":from contains freeform text"
-              (with-silent-logger
-                (core/enrich-exceptions today [{:from "Avaamme Ravintolan 7.1.2015", :to nil, :closed false, :open "08:00", :close nil}]))
-              => [])))
+        (with-silent-logger
+          (fact ":from contains freeform text"
+                (core/enrich-exceptions today [{:from "Avaamme Ravintolan 7.1.2015", :to nil, :closed false, :open "08:00", :close nil}])
+                => []))))

 (fact "Enriched restaurant data"
       ; XXX: Date and food constants must be updated when test data is updated.


:sparkles: Improve random-path transformer perfornace (storages).

--- backend/src/uxbox/util/storage.clj
+++ backend/src/uxbox/util/storage.clj
@@ -155,21 +155,23 @@
       base-uri (assoc ::base-uri (uri base-uri))
       xf (assoc ::xf xf))))

-(defn- bytes->sha256
-  [^bytes data]
-  (let [^MessageDigest md (MessageDigest/getInstance "SHA-256")]
-    (.update md data)
-    (.digest md)))
+;; This is don't need to be secure and we dont need to reseed it; the
+;; security guarranties of this prng instance are very low (we only
+;; use it for generate a random path where store the file).

-(defn hash-path
+(def ^:private prng
+  (delay
+    (doto (java.security.SecureRandom/getInstance "SHA1PRNG")
+      (.setSeed (sodi.prng/random-bytes 64)))))
+
+(defn random-path
   [^Path path]
   (let [name (str (.getFileName path))
-        hash (-> (sodi.prng/random-nonce 64)
-                 (bytes->sha256)
+        hash (-> (sodi.prng/random-bytes @prng 10)
                  (sodi.util/bytes->b64s))
-        tokens (re-seq #"[\w\d\-\_]{3}" hash)
-        path-tokens (take 6 tokens)
-        rest-tokens (drop 6 tokens)
+        tokens (re-seq #"[\w\d\-\_]{2}" hash)
+        path-tokens (take 3 tokens)
+        rest-tokens (drop 3 tokens)
         path (fs/path path-tokens)
         frest (apply str rest-tokens)]
     (fs/path (list path frest name))))