update issue subscribers when name changes

--- src/pc/http/sente.clj
+++ src/pc/http/sente.clj
@@ -600,14 +600,19 @@
       (log/infof "updating self for %s" (:cust/uuid cust))
       (when (:cust/color-name ?data)
         (assert (contains? (schema/color-enums) (:cust/color-name ?data))))
-      (let [new-cust (cust/update! cust (select-keys ?data [:cust/name :cust/color-name]))]
-        (doseq [uid (reduce (fn [acc subs]
-                              (if (first (filter #(= (:cust/uuid (second %)) (:cust/uuid new-cust))
-                                                 subs))
-                                (concat acc (keys subs))
-                                acc))
-                            () (vals @document-subs))]
-          ((:send-fn @sente-state) uid [:frontend/custs {:uuid->cust {(:cust/uuid new-cust) (cust/public-read-api new-cust)}}]))))))
+      (let [new-cust (cust/update! cust (select-keys ?data [:cust/name :cust/color-name]))
+            collab-uuids (reduce (fn [acc subs]
+                                   (if (first (filter #(= (:cust/uuid (second %)) (:cust/uuid new-cust))
+                                                      subs))
+                                     (concat acc (keys subs))
+                                     acc))
+                                 () (vals @document-subs))
+            msg [:frontend/custs {:uuid->cust {(:cust/uuid new-cust) (cust/public-read-api new-cust)}}]]
+        (doseq [uid collab-uuids]
+          ((:send-fn @sente-state) uid msg))
+        (when (contains? @issues-http/issue-subs client-id)
+          (doseq [uid (set/difference @issues-http/issue-subs (set collab-uuids))]
+            ((:send-fn @sente-state) uid msg)))))))

 (defmethod ws-handler :frontend/send-invite [{:keys [client-id ?data ?reply-fn] :as req}]
   ;; This may turn out to be a bad idea, but error handling is done through creating chats


Remove confusing stack trace when loading props

--- src/photon/config.clj
+++ src/photon/config.clj
@@ -29,6 +29,5 @@
                 (log/info "Properties" (pr-str props))
                 (merge default-config props))
               (catch Exception e
-                (log/error "Configuration was not loaded due to " e)
-                (.printStackTrace e)
+                (log/error "Falling back to default config. Configuration was not loaded due to " e)
                 default-config)))


Add config file

Add config file

--- src/clojure/com/flashlightdb/ceilingbounce/common.clj
+++ src/clojure/com/flashlightdb/ceilingbounce/common.clj
@@ -14,6 +14,7 @@
 (defn do-nothing [])

 (def storage-dir "/storage/emulated/0/ceilingbounce/")
+(def config-path (str storage-dir "config.edn"))

 (def main-ui-chan (chan 10))

@@ -23,3 +24,24 @@
   (keyword (str "com.flashlightdb.ceilingbounce.main/" x)))

 (def lux (atom 0))
+
+(def linear-layout-opts
+  {:orientation :vertical
+                   :layout-width :fill
+                   :layout-height :wrap})
+
+(def config (atom {}))
+
+(defn read-config
+  ([] (read-config config-path))
+  ([path] (swap! config (fn [_ replacement] replacement)
+                 (read-string (slurp path)))))
+
+(defn write-config
+  ([conf] (write-config config-path conf))
+  ([path conf]
+   (spit path conf :append true)))
+
+(add-watch config :config-write-watch
+           (fn [ _key _ref _old new]
+             (write-config new)))


by-endpoint data

by-endpoint data

--- src/provider/core.clj
+++ src/provider/core.clj
@@ -7,7 +7,8 @@
             [cheshire.core         :as chesire]
             [monger.core           :as monger]
             [monger.collection     :as collections]
-            [monger.json])
+            [monger.json]
+            [clojure.walk])
   (:import [com.mongodb MongoOptions ServerAddress])
   (:import org.bson.types.ObjectId)
   (:gen-class))
@@ -44,14 +45,26 @@
   "Gets a specific result"
   [id]
   (collections/find-one-as-map db "results" {:execution_id id}))
+(defn result-cleaner
+  "Cleans a specific result to fit with the expected data returned"
+  [result]
+  (let [value (dissoc (:value result) :_id :query_id :created_at)]
+    {:updated_at (:updated_at result)
+     :value value}))
 (defn get-visualization
   "Gets a single visualization"
   [id]
-  ; TODO: Other computations.
-  (let [unprocessed-visualization (collections/find-map-by-id db "queries" (ObjectId. id))
-        execution-ids (for [execution (:executions unprocessed-visualization)] (:_id execution))
-        executions (map get-result execution-ids)]
-    (assoc unprocessed-visualization :executions executions)))
+  (let [db-entry (collections/find-map-by-id db "queries" (ObjectId. id))
+        execution-ids (for [execution (:executions db-entry)] (:_id execution))
+        executions (filter #(= "complete" (:status %1)) (map get-result execution-ids))
+        by-endpoint (group-by :endpoint_id executions)
+        cleaned (into {} (map (fn [[k v]] [k (map result-cleaner v)]) by-endpoint))]
+    {:title (:title db-entry)
+     :description (:description db-entry)
+     :data cleaned
+     :meta {
+            :reduce (:reduce db-entry)
+            :map (:map db-entry)}}))

 (defn visualization-route
   "Responds withs a single visualization"


xml input extent changes

xml input extent changes

--- configuration/xml-input-extent.clj
+++ configuration/xml-input-extent.clj
@@ -25,11 +25,11 @@
                        (mapping [:Latitude :Latitude-text-node] :Latitude)
                        (mapping [:Longitude :Longitude-text-node] :Longitude)))

-;(foreach (as :Location [:glue:Domains :AdminDomain :Location])
-;         (in (as :AdminDomain [:glue:Domains :AdminDomain])
-;             (add-association :PrimaryLocatedAtDomainLocation
-;                              (mapping :Location :Location)
-;                              (mapping :AdminDomain :Domain))))
+(foreach (as :Location [:glue:Domains :AdminDomain :Location])
+         (in (as :AdminDomain [:glue:Domains :AdminDomain])
+             (add-association :PrimaryLocatedAtDomainLocation
+                              (mapping :Location :Location)
+                              (mapping :AdminDomain :Domain))))

 (foreach [:glue:Domains :AdminDomain :Contact]
          (add-instance :Contact
@@ -40,6 +40,12 @@
                        (mapping [:Type :Type-text-node] :Type)
                        (mapping [:URL :URL-text-node] :Detail)))

+(foreach (as :Contact [:glue:Domains :AdminDomain :Contact])
+         (in (as :AdminDomain [:glue:Domains :AdminDomain])
+             (add-association :HasContactDomain
+                              (mapping :Contact :Contact)
+                              (mapping :AdminDomain :Domain))))
+
 (foreach [:glue:Domains :AdminDomain :Services :Service]
          (add-instance :Service
                        (mapping [:ID :ID-text-node] :ID)
@@ -48,6 +54,12 @@
                        (mapping [:Type :Type-text-node] :Type)
                        (mapping [:QualityLevel :QualityLevel-text-node] :QualityLevel)
                        (mapping [:Complexity :Complexity-text-node] :Complexity)))
+
+(foreach (as :Service [:glue:Domains :AdminDomain :Services :Service])
+         (in (as :AdminDomain [:glue:Domains :AdminDomain])
+             (add-association :ManagesAdminDomainService
+                              (mapping :Service :Service)
+                              (mapping :AdminDomain :Domain))))

 (foreach [:glue:Domains :AdminDomain :Services :Service :Location]
          (add-instance :Location
@@ -60,12 +72,24 @@
                        (mapping [:Latitude :Latitude-text-node] :Latitude)
                        (mapping [:Longitude :Longitude-text-node] :Longitude)))

+(foreach (as :Location [:glue:Domains :AdminDomain :Services :Service :Location])
+         (in (as :Service [:glue:Domains :AdminDomain :Services :Service])
+             (add-association :PrimaryLocatedAtServiceLocation
+                              (mapping :Location :Location)
+                              (mapping :Service :Service))))
+
 (foreach [:glue:Domains :AdminDomain :Services :Service :Contact]
          (add-instance :Contact
                        (mapping [:LocalID :LocalID-text-node] :ID)
                        (mapping [:OtherInfo :OtherInfo-text-node] :OtherInfo)
                        (mapping [:Type :Type-text-node] :Type)
                        (mapping [:URL :URL-text-node] :Detail)))
+
+(foreach (as :Contact [:glue:Domains :AdminDomain :Services :Service :Contact])
+         (in (as :Service [:glue:Domains :AdminDomain :Services :Service])
+             (add-association :HasContactServices
+                              (mapping :Contact :Contact)
+                              (mapping :Service :Service))))

 (foreach [:glue:Domains :AdminDomain :Services :Service :Endpoint]
          (add-instance :Endpoint
@@ -94,6 +118,12 @@
                        (mapping [:DowntimeEnd :DowntimeEnd-text-node] :DowntimeEnd)
                        (mapping [:DowntimeInfo :DowntimeInfo-text-node] :DowntimeInfo)))

+(foreach (as :Endpoint [:glue:Domains :AdminDomain :Services :Service :Endpoint])
+         (in (as :Service [:glue:Domains :AdminDomain :Services :Service])
+             (add-association :ExposesServiceEndpoint
+                              (mapping :Endpoint :Endpoint)
+                              (mapping :Service :Service))))
+
 (foreach [:glue:Domains :AdminDomain :Services :Service :Endpoint :AccessPolicy]
          (add-instance :AccessPolicy
                        (mapping [:CreationTime-attribute] :CreationTime)
@@ -102,12 +132,48 @@
                        (mapping [:Scheme :Scheme-text-node] :Scheme)
                        (mapping [:Rule :Rule-text-node] :Rule)))

+(foreach (as :AccessPolicy [:glue:Domains :AdminDomain :Services :Service :Endpoint :AccessPolicy])
+         (in (as :Endpoint [:glue:Domains :AdminDomain :Services :Service :Endpoint])
+             (add-association :CanAccessAccessPolicyEndpoint
+                              (mapping :AccessPolicy :AccessPolicy)
+                              (mapping :Endpoint :Endpoint))))
+
+(foreach (as :Association [:glue:Domains :AdminDomain :Services :Service :Endpoint :Associations :ActivityID :ActivityID-text-node])
+         (in (as :Endpoint [:glue:Domains :AdminDomain :Services :Service :Endpoint])
+             (add-association :SubmittedByEndpointActivity
+                              (mapping-pk :Association :Activity)
+                              (mapping :Endpoint :Endpoint))))
+
 (foreach [:glue:Domains :AdminDomain :Services :Service :Activities :Activity]
          (add-instance :Activity
                        (mapping [:ID :ID-text-node] :ID)))

+(foreach (as :Association [:glue:Domains :AdminDomain :Services :Service :Activities :Activity :Associations :EndpointID :EndpointID-text-node])
+         (in (as :Activity [:glue:Domains :AdminDomain :Services :Service :Activities :Activity])
+             (add-association :SubmittedByEndpointActivity
+                              (mapping-pk :Association :Endpoint)
+                              (mapping :Activity :Activity))))
+
+(foreach (as :Association [:glue:Domains :AdminDomain :Services :Service :Activities :Activity :Associations :UserDomainID :UserDomainID-text-node])
+         (in (as :Activity [:glue:Domains :AdminDomain :Services :Service :Activities :Activity])
+             (add-association :CreatesActivityUserDomain
+                              (mapping-pk :Association :UserDomain)
+                              (mapping :Activity :Activity))))
+
+(foreach (as :Association [:glue:Domains :AdminDomain :Services :Service :Activities :Activity :Associations :ActivityID :ActivityID-text-node])
+         (in (as :Activity [:glue:Domains :AdminDomain :Services :Service :Activities :Activity])
+             (add-association :RelatesToActivityToActivity
+                              (mapping-pk :Association :Activity)
+                              (mapping :Activity :Activity))))
+
+(foreach (as :Association [:glue:Domains :AdminDomain :Services :Service :Associations :ServiceID :ServiceID-text-node])
+         (in (as :Service [:glue:Domains :AdminDomain :Services :Service])
+             (add-association :RelatesToServiceToService
+                              (mapping-pk :Association :Service)
+                              (mapping :Service :Service))))
+
 (foreach [:glue:Domains :AdminDomain :Services :ComputingService]
-         (add-instance :ComputingService
+         (add-instance :Service
                        (mapping [:CreationTime-attribute] :CreationTime)
                        (mapping [:Validity-attribute] :Validity)
                        (mapping [:ID :ID-text-node] :ID)
@@ -117,6 +183,12 @@
                        (mapping [:QualityLevel :QualityLevel-text-node] :QualityLevel)
                        (mapping [:StatusPage] :StatusPage)
                        (mapping [:Complexity :Complexity-text-node] :Complexity)))
+
+(foreach (as :ComputingService [:glue:Domains :AdminDomain :Services :ComputingService])
+         (in (as :AdminDomain [:glue:Domains :AdminDomain])
+             (add-association :ManagesAdminDomainService
+                              (mapping :ComputingService :Service)
+                              (mapping :AdminDomain :AdminDomain))))

 (foreach [:glue:Domains :AdminDomain :Services :ComputingService :Location]
          (add-instance :Location
@@ -131,6 +203,12 @@
                        (mapping [:Latitude :Latitude-text-node] :Latitude)
                        (mapping [:Longitude :Longitude-text-node] :Longitude)))

+(foreach (as :Location [:glue:Domains :AdminDomain :Services :ComputingService :Location])
+         (in (as :ComputingService [:glue:Domains :AdminDomain :Services :ComputingService])
+             (add-association :PrimaryLocatedAtServiceLocation
+                              (mapping :Location :Location)
+                              (mapping :ComputingService :Service))))
+
 (foreach [:glue:Domains :AdminDomain :Services :ComputingService :Contact]
          (add-instance :Contact
                        (mapping [:CreationTime-attribute] :CreationTime)
@@ -139,6 +217,12 @@
                        (mapping [:OtherInfo :OtherInfo-text-node] :OtherInfo)
                        (mapping [:Type :Type-text-node] :Type)
                        (mapping [:URL :URL-text-node] :Detail)))
+
+(foreach (as :Contact [:glue:Domains :AdminDomain :Services :ComputingService :Contact])
+         (in (as :ComputingService [:glue:Domains :AdminDomain :Services :ComputingService])
+             (add-association :HasContactServices
+                              (mapping :Contact :Contact)
+                              (mapping :ComputingService :Service))))

 (foreach [:glue:Domains :AdminDomain :Services :ComputingService :ComputingEndpoint]
          (add-instance :Endpoint
@@ -167,6 +251,12 @@
                        (mapping [:DowntimeEnd :DowntimeEnd-text-node] :DowntimeEnd)
                        (mapping [:DowntimeInfo :DowntimeInfo-text-node] :DowntimeInfo)))

+(foreach (as :Endpoint [:glue:Domains :AdminDomain :Services :ComputingService :ComputingEndpoint])
+         (in (as :ComputingService [:glue:Domains :AdminDomain :Services :ComputingService])
+             (add-association :ExposesServiceEndpoint
+                              (mapping :Endpoint :Endpoint)
+                              (mapping :ComputingService :Service))))
+
 (foreach [:glue:Domains :AdminDomain :Services :ComputingService :ComputingEndpoint :AccessPolicy]
          (add-instance :AccessPolicy
                        (mapping [:CreationTime-attribute] :CreationTime)
@@ -174,6 +264,12 @@
                        (mapping [:LocalID :LocalID-text-node] :LocalID)
                        (mapping [:Scheme :Scheme-text-node] :Scheme)
                        (mapping [:Rule-text-node :Rule] :Rule)))
+
+(foreach (as :AccessPolicy [:glue:Domains :AdminDomain :Services :ComputingService :ComputingEndpoint :AccessPolicy])
+         (in (as :ComputingEndpoint [:glue:Domains :AdminDomain :Services :ComputingService :ComputingEndpoint])
+             (add-association :CanAccessAccessPolicyEndpoint
+                              (mapping :AccessPolicy :AccessPolicy)
+                              (mapping :ComputingEndpoint :Endpoint))))

 (foreach [:glue:Domains :AdminDomain :Services :ComputingService :ComputingShares :ComputingShare]
          (add-instance :Share
@@ -184,13 +280,31 @@
                        (mapping [:MaxTotalWallTime :MaxTotalWallTime-text-node] :MaxTotalWallTime)
                        (mapping [:ServingState :ServingState-text-node] :ServingState)))

-; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+(foreach (as :ComputingShare [:glue:Domains :AdminDomain :Services :ComputingService :ComputingShares :ComputingShare])
+         (in (as :ComputingService [:glue:Domains :AdminDomain :Services :ComputingService])
+             (add-association :OffersServiceShare
+                              (mapping :ComputingShare :Share)
+                              (mapping :ComputingService :Service))))
+
+; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! cannot map Type attribute only !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ;(foreach [:glue:Domains :AdminDomain :Services :ComputingService :ComputingActivitites :ComputingActivitiy]
 ;         (add-instance :Activitiy
 ;                       (mapping [:Type :Type-text-node] :Type)))

+(foreach (as :Association [:glue:Domains :AdminDomain :Services :ComputingService :Associations :ServiceID :ServiceID-text-node])
+         (in (as :ComputingService [:glue:Domains :AdminDomain :Services :ComputingService])
+             (add-association :RelatesToServiceToService
+                              (mapping-pk :Association :Service)
+                              (mapping :ComputingService :Service))))
+
+(foreach (as :Association [:glue:Domains :AdminDomain :Associations :AdminDomainID :AdminDomainID-text-node])
+         (in (as :AdminDomain [:glue:Domains :AdminDomain])
+             (add-association :ParticipatesInAdminDomainToAdminDomain
+                              (mapping-pk :Association :AdminDomain)
+                              (mapping :AdminDomain :AdminDomain))))
+
 (foreach [:glue:Domains :UserDomain]
-         (add-instance :UserDomain (mapping [:Distributed :Distributed-text-node] :Distributed)
+         (add-instance :UserDomain
                        (mapping [:ID :ID-text-node :ID] :ID)
                        (mapping [:Name :Name-text-node] :Name)
                        (mapping [:Description :Description-text-node] :Description)
@@ -199,3 +313,9 @@
                        (mapping [:Level :Level-text-node] :Level)
                        (mapping [:UserManager :UserManager-text-node] :UserManager)
                        (mapping [:Member :Member-text-node] :Member)))
+
+(foreach (as :Association [:glue:Domains :UserDomain :Associations :UserDomainID :UserDomainID-text-node])
+         (in (as :UserDomain [:glue:Domains :UserDomain])
+             (add-association :ParticipatesInUserDomainToUserDomain
+                              (mapping-pk :Association :UserDomain)
+                              (mapping :UserDomain :UserDomain))))


Brevity is a by-product of vigor.

Brevity is a by-product of vigor.

--- src-cljs/cljsbuild_ui/pages/main.cljs
+++ src-cljs/cljsbuild_ui/pages/main.cljs
@@ -661,9 +661,9 @@
   [:div.outer-f80bb
     [:div.inner-aa3fc
       [:h4 "No active projects."]
-      [:p "Would you like to add a "
+      [:p "Would you like to "
         [:span.link-e7e58 {:on-click show-new-project-modal}
-          "new one"] "?"]]])
+          "add one"] "?"]]])

 (sablono/defhtml header []
   [:div.header-a4c14


made all tracking owner/current-state agnostic

--- src-cljs/frontend/analytics/core.cljs
+++ src-cljs/frontend/analytics/core.cljs
@@ -102,12 +102,6 @@
       (add-properties-to-track-from-owner)
       (merge props)))

-(defn- get-user-properties-from-state [current-state]
-  (let [analytics-id (get-in current-state state/user-analytics-id-path)
-        user-data (get-in current-state state/user-path)]
-    {:id analytics-id
-     :user-properties (select-keys user-data (keys common-analytics/UserProperties))}))
-
 (defn- supplement-tracking-properties-from-state [props current-state]
   "Fill in any unsuppplied property values with those supplied
   in the current app state."
@@ -144,44 +138,58 @@
   (when (frontend.config/analytics-enabled?)
     (merror-unsupported-event (:event-type data))))

+(defn- supplement-tracking-properties [{:keys [properties owner current-state]}]
+  (if owner
+    (supplement-tracking-properties-from-owner properties owner)
+    (supplement-tracking-properties-from-state properties current-state)))
+
 (s/defmethod track :event [event-data :- AnalyticsEvent]
   (let [{:keys [event-type properties owner current-state]} event-data]
-    (if owner
-      (segment/track-event event-type (supplement-tracking-properties-from-owner properties owner))
-      (segment/track-event event-type (supplement-tracking-properties-from-state properties current-state)))))
-
-;; Gotta finish this + add schema event
-(s/defmethod track :track-controller-events [event-data :- AnalyticsEvent]
-  (let [{:keys [event-type properties current-state]} event-data]
-    (segment/track-event event-type (supplement-tracking-properties-from-state properties current-state))))
+    (segment/track-event event-type (supplement-tracking-properties {:properties properties
+                                                                     :owner owner
+                                                                     :current-state current-state}))))

 (s/defmethod track :external-click [event-data :- ExternalClickEvent]
-  (let [{:keys [event properties owner]} event-data]
+  (let [{:keys [event properties owner current-state]} event-data]
     (if (supported-click-and-impression-events (:event event-data))
-      (segment/track-external-click event (supplement-tracking-properties-from-owner properties owner))
+      (segment/track-external-click event (supplement-tracking-properties {:properties properties
+                                                                           :owner owner
+                                                                           :current-state current-state}))
       (merror-unsupported-event (:event event-data)))))

 (s/defmethod track :pageview [event-data :- PageviewEvent]
-  (let [{:keys [navigation-point properties current-state]} event-data]
-    (segment/track-pageview navigation-point (supplement-tracking-properties-from-state properties current-state))))
+  (let [{:keys [navigation-point properties owner current-state]} event-data]
+    (segment/track-pageview navigation-point (supplement-tracking-properties {:properties properties
+                                                                              :owner owner
+                                                                              :current-state current-state}))))

 (s/defmethod track :build-triggered [event-data :- BuildEvent]
-  (let [{:keys [build properties owner]} event-data
+  (let [{:keys [build properties owner current-state]} event-data
         props (merge {:project (vcs-url/project-name (:vcs_url build))
                       :build-num (:build_num build)
                       :retry? true}
                      properties)]
-    (segment/track-event :build-triggered (supplement-tracking-properties-from-owner props owner))))
+    (segment/track-event :build-triggered (supplement-tracking-properties {:properties properties
+                                                                           :owner owner
+                                                                           :current-state current-state}))))

 (s/defmethod track :view-build [event-data :- BuildEvent]
-  (let [{:keys [build properties current-state]} event-data
+  (let [{:keys [build properties owner current-state]} event-data
         props (merge (build-properties build) properties)
         user (get-in current-state state/user-path)]
-    (segment/track-event :view-build (supplement-tracking-properties-from-state props current-state))
+    (segment/track-event :view-build (supplement-tracking-properties {:properties properties
+                                                                      :owner owner
+                                                                      :current-state current-state}))
     (when (and (:oss build) (build-model/owner? build user))
       (intercom/track :viewed-self-triggered-oss-build
                       {:vcs-url (vcs-url/project-name (:vcs_url build))
                        :outcome (:outcome build)}))))

+(defn- get-user-properties-from-state [current-state]
+  (let [analytics-id (get-in current-state state/user-analytics-id-path)
+        user-data (get-in current-state state/user-path)]
+    {:id analytics-id
+     :user-properties (select-keys user-data (keys common-analytics/UserProperties))}))
+
 (s/defmethod track :init-user [event-data :- AnalyticsEvent]
   (segment/identify (get-user-properties-from-state (:current-state event-data))))


Show sidebar nav when feature flag is not on

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -164,7 +164,9 @@
                (let [compassus-route (compassus/current-route owner)
                      current-route (if (= :route/legacy-page compassus-route)
                                      (:navigation-point app)
-                                     compassus-route)]))
+                                     compassus-route)]
+                 (when (not (ld/feature-on? "top-bar-ui-v-1"))
+                   (build-legacy aside/aside-nav {:user user :current-route current-route}))))

              (factory props)]]))))))


don't offset right-click tip anymore

don't offset right-click tip anymore

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -147,7 +147,7 @@
                    [:div.radial-menu-nub]])
                 (when (and (not right-click-learned?) (:mouse app))
                   [:div.radial-tip {:style {:top  (+ (get-in app [:mouse :y]) 16)
-                                            :left (+ (get-in app [:mouse :x]) (if chat-opened? (- 16 256) 16) )}}
+                                            :left (+ (get-in app [:mouse :x]) 16)}}
                    (if (= :touch (get-in app [:mouse :type]))
                      "Tap and hold to select tool"
                      "Try right-click")])]


context -> env

context -> env

--- test-cljs/frontend/test_send.cljs
+++ test-cljs/frontend/test_send.cljs
@@ -316,11 +316,11 @@
        (doto to (put! v) (close!)))))
   to)

-(defn resolve [channel context query-or-ast]
+(defn resolve [channel env query-or-ast]
   (let [ast (if (vector? query-or-ast)
               (om/query->ast query-or-ast)
               query-or-ast)
-        resolvers (:resolvers context)
+        resolvers (:resolvers env)
         children (:children ast)]
     (async/pipe
      (async/merge
@@ -328,11 +328,11 @@
             :let [read-from-key (get-in ast [:params :<] (:key ast))]]
         (if (contains? resolvers read-from-key)
           (let [resolver (get resolvers read-from-key)]
-            (pipe-values (resolver context ast)
+            (pipe-values (resolver env ast)
                          (chan 1 (map #(hash-map (:key ast) %)))))
           (if-let [[keys resolver]
                    (first (filter #(contains? (key %) read-from-key) resolvers))]
-            (pipe-values (resolver context ast)
+            (pipe-values (resolver env ast)
                          (chan 1 (comp
                                   (map #(get % read-from-key))
                                   (map #(hash-map (:key ast) %)))))
@@ -346,24 +346,24 @@

 (def resolvers
   {'do/something
-   (fn [context ast]
-     (let [do-something (get-in context [:apis :do-something])]
+   (fn [env ast]
+     (let [do-something (get-in env [:apis :do-something])]
        (do-something (:params ast))))

    :root/user
-   (fn [context ast]
+   (fn [env ast]
      (resolve (chan)
-              (assoc context :user/name (:user/name (:params ast)))
+              (assoc env :user/name (:user/name (:params ast)))
               ast))

    :user/name
-   (fn [context ast]
-     (:user/name context))
+   (fn [env ast]
+     (:user/name env))

    #{:user/favorite-color :user/favorite-number :user/vehicle}
-   (fn [context ast]
-     (p/alet [get-user (get-in context [:apis :get-user])
-              user (p/await (get-user {:name (:user/name context)}))]
+   (fn [env ast]
+     (p/alet [get-user (get-in env [:apis :get-user])
+              user (p/await (get-user {:name (:user/name env)}))]
        (-> user
            (set/rename-keys {:favorite-color :user/favorite-color
                              :favorite-number :user/favorite-number
@@ -375,9 +375,9 @@
                    #(parser {:state (atom %)} (mapv om/ast->query (:children ast)))))))

    :user/pets
-   (fn [context ast]
-     (p/alet [get-user-pets (get-in context [:apis :get-user-pets])
-              pets (p/await (get-user-pets {:name (:user/name context)}))]
+   (fn [env ast]
+     (p/alet [get-user-pets (get-in env [:apis :get-user-pets])
+              pets (p/await (get-user-pets {:name (:user/name env)}))]
        (->> pets
             (map #(set/rename-keys % {:name :pet/name
                                       :species :pet/species
@@ -385,11 +385,11 @@
             (mapv #(parser {:state (atom %)} (mapv om/ast->query (:children ast)))))))

    :user/favorite-fellow-user
-   (fn [context ast]
-     (p/alet [get-user (get-in context [:apis :get-user])
-              user (p/await (get-user {:name (:user/name context)}))]
+   (fn [env ast]
+     (p/alet [get-user (get-in env [:apis :get-user])
+              user (p/await (get-user {:name (:user/name env)}))]
        (resolve (chan)
-                (assoc context :user/name (:favorite-fellow-user-name user))
+                (assoc env :user/name (:favorite-fellow-user-name user))
                 ast)))})

 (deftest new-thing-works


Badge adverts, schema fix

Badge adverts, schema fix

--- src/clj/salava/extra/application/db.clj
+++ src/clj/salava/extra/application/db.clj
@@ -163,6 +163,7 @@
                                 :description (:description client)
                                 :url (:url client)
                                 :email (:email client)
+                                :endorsement []
                                 :image_file (if-not (string/blank? (:image client))
                                               (u/file-from-url ctx (:image client)))
                                 :revocation_list_url (:revocationList client)})


Got circles to show up in their cell on click.

--- src/cljs/clj_mini_apps/tic-tac-toe.cljs
+++ src/cljs/clj_mini_apps/tic-tac-toe.cljs
@@ -10,6 +10,7 @@

 (defn init-board []
   ;Create background and outline
+  (q/smooth)
   (q/background 209 209 210)
   (q/fill 255)
   (q/no-stroke)
@@ -23,35 +24,52 @@
   (q/rect-mode :center))

 (def board
-  [[nil nil nil]
-   [nil nil nil]
-   [nil nil nil]])
+  (atom
+    [[nil nil nil]
+     [nil nil nil]
+     [nil nil nil]]))

-(def borders
-  (map #(assoc % :w 141 :h 141)
-    [{:top-left {:x 0 :y 0}}
-     {:top-mid {:x 229 :y 0}}
-     {:top-right {:x 379 :y 0}}
-     {:mid-left {:x 0 :y 229}}
-     {:mid-mid {:x 229 :y 229}}
-     {:mid-right {:x 379 :y 229}}
-     {:btm-left {:x 0 :y 379}}
-     {:btm-mid {:x 229 :y 379}}
-     {:btm-right {:x 379 :y 379}}]))
+(def cells
+  (for [x [79 229 379]
+        y [79 229 379]
+        :let [[bx by] [(+ x 70)
+                       (+ y 70)]
+              [row col] [(dec (quot bx 141))
+                         (dec (quot by 141))]]]
+    {:x x :y y
+     :w 141 :h 141
+     :center [bx by] :tile [row col]}))
+
+(defn is-in-cell?
+  [{:keys [x y w h]} [mx my]]
+  (and (> mx x)
+       (< mx (+ x w))
+       (> my y)
+       (< my (+ y h))))
+
+(defn mouse->cell
+  [[mx my]]
+  (->> cells
+       (filter #(is-in-cell? % [mx my]))
+       (first)))

 (defn add-circle
-  []
-  (log (q/mouse-x))
-  (log (q/mouse-y))
-  (q/fill 255 0 0)
-  (q/ellipse (q/mouse-x) (q/mouse-y) 100 100)
-  (q/fill 255)
-  (q/ellipse (q/mouse-x) (q/mouse-y) 90 90))
-  ;(update-in state [:rects]
-  ;          conj {:x (q/mouse-x) :y (q/mouse-y) :w 10 :h 10}))
+  [mx my]
+  (let [[x y] (:center (mouse->cell [mx my]))]
+    (when (every? identity [x y])
+      (q/fill (q/random 255) (q/random 255) (q/random 255))
+      (q/ellipse x y 100 100)
+      (q/fill 255)
+      (q/ellipse x y 90 90))))
+
+(defn play-ttt []
+  (let [[mx my] [(q/mouse-x) (q/mouse-y)]
+        [tx ty] (:tile (mouse->cell [mx my]))]
+    (if true
+      (add-circle mx my))))

 (q/defsketch hello
   :host "canvas"
   :size [600 600]
   :setup init-board
-  :mouse-pressed add-circle)
+  :mouse-pressed play-ttt)


protect empty string

protect empty string

--- src/clojure/zensols/nlparse/feature.clj
+++ src/clojure/zensols/nlparse/feature.clj
@@ -153,7 +153,9 @@
   (->> (map :text tokens)
        (map count)
        (apply +)
-       (#(/ % (count tokens)))))
+       (#(if (> (count tokens) 0)
+           (/ % (count tokens))
+           0))))

 (defn token-features [panon tokens]
   {:utterance-length (count (:text panon))
@@ -461,13 +463,18 @@
   "See [[char-dist-features]]."
   []
   [[:char-dist-unique 'numeric]
+   [:char-dist-unique-ratio 'numeric]
    [:char-dist-variance 'numeric]
-   [:char-dist-mean 'numeric]])
+   [:char-dist-mean 'numeric]
+   [:char-dist-count 'numeric]])

 (defn char-dist-features
   "Return the number of unique characters in **text**."
   [text]
-  (let [char-dist (->> (StringUtils/uniqueCharCounts text) vals)]
+  (let [char-dist (->> (StringUtils/uniqueCharCounts text) vals)
+        len (count text)]
    {:char-dist-unique (count char-dist)
-    :char-dist-variance (->> char-dist stat/variance)
-    :char-dist-mean (->> char-dist stat/mean double)}))
+    :char-dist-unique-ratio (if (= len 0) -1 (/ (count char-dist) len))
+    :char-dist-count len
+    :char-dist-variance (if (= len 0) -1 (->> char-dist stat/variance))
+    :char-dist-mean (if (= len 0) -1 (->> char-dist stat/mean))}))


changed function name

changed function name

--- src/cmr/umm/test/generators/granule.clj
+++ src/cmr/umm/test/generators/granule.clj
@@ -35,7 +35,7 @@
                   :day-night (gen/elements ["DAY" "NIGHT" "BOTH" "UNSPECIFIED"])
                   :production-date-time ext-gen/date-time)))

-(def cloud-cover-elems
+(def cloud-cover-values
   (ext-gen/optional  (gen/frequency [[7 (ext-gen/choose-double 0.0 100.0)] [3 (ext-gen/choose-double 0.0 1.0)]])))

 (def granules
@@ -49,7 +49,7 @@
       :orbit-calculated-spatial-domains (ext-gen/nil-if-empty (gen/vector ocsd/orbit-calculated-spatial-domains 0 5))
       :project-refs (ext-gen/nil-if-empty proj-refs)
       :product-specific-attributes (ext-gen/nil-if-empty (gen/vector product-specific-attribute-refs 0 5))
-      :cloud-cover cloud-cover-elems)))
+      :cloud-cover cloud-cover-values)))

 ;; Generator that only returns collection ref with entry-title
 ;; DEPRECATED - this will go away in the future. Don't use it.


More csv uploading. Less csv downloading.

We upload lots of smaller csv files and need more threads to deal with
them.

--- src/kixi/hecuba/controller/pipeline.clj
+++ src/kixi/hecuba/controller/pipeline.clj
@@ -37,10 +37,10 @@
         sensor-status-q         (new-queue {:name "sensor-status" :queue-size 50})
         actual-annual-q         (new-queue {:name "actual-annual-q" :queue-size 50})
         store-upload-s3-q       (new-queue {:name "store-upload-s3-q" :queue-size 50})
-        upload-measurements-q   (new-queue {:name "upload-measurements-q" :queue-size 10})
+        upload-measurements-q   (new-queue {:name "upload-measurements-q" :queue-size 50 :number-of-consumer-threads 4})
         upload-images-q         (new-queue {:name "image-upload-q" :queue-size 10})
         upload-documents-q      (new-queue {:name "document-upload-q" :queue-size 10})
-        download-measurements-q (new-queue {:name "download-measurements-q" :queue-size 50 :number-of-consumer-threads 4})
+        download-measurements-q (new-queue {:name "download-measurements-q" :queue-size 50 :number-of-consumer-threads 2})
         recalculate-q           (new-queue {:name "recalculate-q" :queue-size 10})]

     (defnconsumer fanout-q [{:keys [dest type] :as item}]


:smirk: limit results to 10000 rows; add implicit limit clause for rows aggregation; return num_results_over_limit in QP response when limit is hit

--- src/metabase/driver/query_processor.clj
+++ src/metabase/driver/query_processor.clj
@@ -7,6 +7,7 @@
             [metabase.models.field :refer [Field field->fk-table]]))

 (declare add-implicit-breakout-order-by
+         add-implicit-limit
          get-special-column-info
          preprocess-cumulative-sum
          preprocess-structured
@@ -17,6 +18,10 @@
 (def ^:const empty-response
   "An empty response dictionary to return when there's no query to run."
   {:rows [], :columns [], :cols []})
+
+(def ^:const max-result-rows
+  "Maximum number of rows the QP should ever return."
+  10000)

 ;; # DYNAMIC VARS
@@ -45,6 +50,7 @@
   (let [preprocessed-query (update-in query [:query] #(->> %
                                                            remove-empty-clauses
                                                            add-implicit-breakout-order-by
+                                                           add-implicit-limit
                                                            preprocess-cumulative-sum))]
     (when-not *disable-qp-logging*
       (log/debug (colorize.core/cyan "\n******************** PREPROCESSED: ********************\n"
@@ -91,6 +97,17 @@
                          [field-id "ascending"]))
                  (apply conj (or order-by-subclauses []))
                  (assoc query :order_by)))))
+
+
+;;; ### ADD-IMPLICIT-LIMIT
+
+(defn add-implicit-limit
+  "Add an implicit limit clause to queries with `rows` aggregations."
+  [{:keys [limit aggregation] :as query}]
+  (if (and (= aggregation ["rows"])
+           (not limit))
+    (assoc query :limit max-result-rows)
+    query))

 ;; ### PREPROCESS-CUMULATIVE-SUM
@@ -161,12 +178,9 @@

 ;; ### LIMIT-MAX-RESULT-ROWS

-(def ^:const max-result-rows
-  "Maximum number of rows the QP should ever return."
-  2000)
-
 (defn limit-max-result-rows
-  "Limit the number of rows returned in RESULTS to `max-result-rows`."
+  "Limit the number of rows returned in RESULTS to `max-result-rows`.
+   (We want to do this here so we can put a hard limit on native SQL results and other ones where we couldn't add an implicit `:limit` clause)."
   [results]
   {:pre [(map? results)
          (sequential? (:rows results))]}
@@ -182,9 +196,11 @@
          (sequential? (:columns results))
          (sequential? (:cols results))
          (sequential? (:rows results))]}
-  {:row_count (count (:rows results))
-   :status    :completed
-   :data      results})
+  (let [num-results (count (:rows results))]
+    (cond-> {:row_count (count (:rows results))
+             :status    :completed
+             :data      results}
+      (= num-results max-result-rows) (assoc :num_results_over_limit true)))) ; so the front-end can let the user know why they're being arbitarily limited

 ;; ### POST-PROCESS


(PDB-3840) Fix rededuplicate migration crash; rm values with no path

Prevent rededuplicate-facts migration failures caused by orphaned
facts that have no path in fact_paths.  For example:

  ERROR [p.p.s.migrate] Caught SQLException during migration
  java.sql.BatchUpdateException: Batch entry 3 ALTER TABLE facts ADD CONSTRAINT fact_path_id_fk
  FOREIGN KEY (fact_path_id)
  REFERENCES fact_paths(id) was aborted. Call getNextException to see the cause.
  at org.postgresql.jdbc.BatchResultHandler.handleError(BatchResultHandler.java:133)
  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2004)
  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:360)
  at org.postgresql.jdbc.PgStatement.executeBatch(PgStatement.java:1019)
  at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:125)
  at com.zaxxer.hikari.pool.HikariProxyStatement.executeBatch(HikariProxyStatement.java)
  at clojure.java.jdbc$execute_batch.invokeStatic(jdbc.clj:439)
  at clojure.java.jdbc$execute_batch.invoke(jdbc.clj:432)
  at clojure.java.jdbc$db_do_commands$fn__21859.invoke(jdbc.clj:748)
  at clojure.java.jdbc$db_transaction_STAR_.invokeStatic(jdbc.clj:662)
  at clojure.java.jdbc$db_transaction_STAR_.invoke(jdbc.clj:598)
  at clojure.java.jdbc$db_transaction_STAR_.invokeStatic(jdbc.clj:611)
  at clojure.java.jdbc$db_transaction_STAR_.invoke(jdbc.clj:598)
  at clojure.java.jdbc$db_do_commands.invokeStatic(jdbc.clj:747)
  at clojure.java.jdbc$db_do_commands.invoke(jdbc.clj:732)
  at puppetlabs.puppetdb.jdbc$do_commands.invokeStatic(jdbc.clj:38)
  at puppetlabs.puppetdb.jdbc$do_commands.doInvoke(jdbc.clj:33)
  at clojure.lang.RestFn.invoke(RestFn.java:512)
  at puppetlabs.puppetdb.scf.migrate$rededuplicate_facts.invokeStatic(migrate.clj:1433)
  at puppetlabs.puppetdb.scf.migrate$rededuplicate_facts.invoke(migrate.clj:1315)
  at puppetlabs.puppetdb.scf.migrate$migrate_BANG_$fn__36253$fn__36255$fn__36257.invoke(migrate.clj:1616)

[rlb@puppet.com: rebase onto current 5.2.x; remove deletion based on
 fact_values since that table doesn't exist during this particular
 migration; adjust commit message and add sample error message]

--- src/puppetlabs/puppetdb/scf/migrate.clj
+++ src/puppetlabs/puppetdb/scf/migrate.clj
@@ -1314,7 +1314,8 @@
 (defn rededuplicate-facts []
   (log/info (trs "[1/8] Cleaning up unreferenced facts..."))
   (jdbc/do-commands
-   "DELETE FROM facts WHERE factset_id NOT IN (SELECT id FROM factsets)")
+   "DELETE FROM facts WHERE factset_id NOT IN (SELECT id FROM factsets)"
+   "DELETE FROM facts WHERE fact_path_id NOT IN (SELECT id FROM fact_paths)")

   (log/info (trs "[2/8] Creating new fact storage tables..."))
   (jdbc/do-commands


[#1534] Include rows in dataset api response

--- backend/src/akvo/lumen/lib/dataset_impl.clj
+++ backend/src/akvo/lumen/lib/dataset_impl.clj
@@ -68,6 +68,7 @@
        (-> dataset
            (select-keys [:columns :created :id :modified :rows :status :title :transformations :updated])
            (rename-keys {:title :name})
+           (assoc :rows data)
            (assoc :status "OK"))))
     (lib/not-found {:error "Not found"})))


Make todo demo text align better

Make todo demo text align better

Make todo demo text align better

--- src/webapp/framework/client/components/main_view.cljs
+++ src/webapp/framework/client/components/main_view.cljs
@@ -70,7 +70,7 @@
                                                 (go (sql "update  coils_todo_items   set item_status = 'ACTIVE' where id = ?" [item-id]  ))
                                                 )))}))

-                  (label {:style {:width   "50%"}
+                  (label {:style {:width   "70%"}
                           :className (if (= (<-- :item_status) "COMPLETED") "completed" "item")}
                                 (str (<-- :item)))


refact arithmetic

refact arithmetic

--- src/clj/algorithms_clj/arithmetic.clj
+++ src/clj/algorithms_clj/arithmetic.clj
@@ -65,16 +65,20 @@

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

+(defn- make-op
+  [rator rands]
+  (if (< 1 (count rands))
+    (into [rator] rands)
+    (first rands)))
+
 (defn- optimize-op
   [[rator & rands] binary-op neutral]
   (let [{csts true vars false} (group-by cst? rands)
-        sum-cst (reduce binary-op neutral csts)
-        one? #(= 1 (count %))]
+        sum-cst (reduce binary-op neutral csts)]
     (cond
       (empty? vars) (cst sum-cst)
-      (and (one? vars) (= neutral sum-cst)) (sym (first vars))
-      (= neutral sum-cst) (into [rator] vars)
-      :else (into [rator (cst sum-cst)] vars)
+      (= neutral sum-cst) (make-op rator vars)
+      :else (make-op rator (into [(cst sum-cst)] vars))
       )))

 (defn- optimize-add [e]


put balance sheet first

put balance sheet first

--- src/cljs/clj_money/views/reports.cljs
+++ src/cljs/clj_money/views/reports.cljs
@@ -506,8 +506,8 @@
        [render-portfolio page-state]])))

 (def ^:private report-types
-  [:income-statement
-   :balance-sheet
+  [:balance-sheet
+   :income-statement
    :budget
    :portfolio])

@@ -524,7 +524,7 @@
                      (load-report page-state)))})))

 (defn- index []
-  (let [page-state (r/atom {:selected :income-statement
+  (let [page-state (r/atom {:selected :balance-sheet
                             :hide-zeros? true
                             :income-statement {:start-date (start-of-year)
                                                :end-date (t/today)}


remove a few methods from reactive

remove a few methods from reactive

--- src/cljs/wilkerdev/util/reactive.cljs
+++ src/cljs/wilkerdev/util/reactive.cljs
@@ -153,19 +153,6 @@
             (do (when (not= x last) (>! out x))
               (recur x))
             (close! out))))
-    out))
-
-(defn fan-in
-  ([ins] (fan-in ins (chan)))
-  ([ins out]
-    (go (loop [ins (vec ins)]
-          (when (> (count ins) 0)
-            (let [[x in] (alts! ins)]
-              (when x
-                (>! out x)
-                (recur ins))
-              (recur (vec (disj (set ins) in))))))
-        (close! out))
     out))

 (defn take-until
@@ -198,36 +185,20 @@
              (close! out))))
      out))

-(defn siphon
-  ([in] (siphon in []))
-  ([in coll]
-    (go (loop [coll coll]
-          (if-let [v (<! in)]
-            (recur (conj coll v))
-            coll)))))
-
-(defn always [v c]
-  (let [out (chan)]
-    (go (loop []
-          (if-let [e (<! c)]
-            (do (>! out v)
-              (recur))
-            (close! out))))
-    out))
-
 (defn toggle [in]
   (let [out (chan)
         control (chan)]
     (go (loop [on true]
           (recur
             (alt!
-              in ([x] (when on (>! out x)) on)
+              in ([x] (if on (>! out x)) on)
               control ([x] x)))))
     {:chan out
      :control control}))

 (defn barrier [cs]
-  (go (loop [cs (seq cs) result []]
+  (go (loop [cs (seq cs)
+             result []]
         (if cs
           (recur (next cs) (conj result (<! (first cs))))
           result))))


Checked arrays

Checked arrays

--- ClojureScript/replete/src/replete/repl.cljs
+++ ClojureScript/replete/src/replete/repl.cljs
@@ -46,7 +46,8 @@
 (defn ^:export init-app-env [app-env]
   (set! *print-namespace-maps* true)
   (load-core-analysis-caches true)
-  (reset! replete.repl/app-env (map-keys keyword (cljs.core/js->clj app-env))))
+  (reset! replete.repl/app-env (assoc (map-keys keyword (cljs.core/js->clj app-env))
+                                 :checked-arrays :warn)))

 (defn user-interface-idiom-ipad?
   "Returns true iff the interface idiom is iPad."
@@ -697,11 +698,13 @@
              source
              (if expression? source "File")
              (merge
-               {:ns         @current-ns
-                :load       load
-                :eval       cljs/js-eval
-                :source-map false
-                :verbose    (:verbose @app-env)}
+               {:ns             @current-ns
+                :load           load
+                :eval           cljs/js-eval
+                :source-map     false
+                :verbose        (:verbose @app-env)}
+               (when (:checked-arrays @app-env)
+                 {:checked-arrays (:checked-arrays @app-env)})
                (when expression?
                  {:context       :expr
                   :def-emits-var true}))


fix typo in msg str and wrap long line

fix typo in msg str and wrap long line

--- src/trammel/utils.clj
+++ src/trammel/utils.clj
@@ -4,7 +4,8 @@
 (defmacro ^:private assert-w-message
   [check message]
   `(when-not ~check
-     (throw (new AssertionError (str "Trammel asserttion failed: " ~message "\n" (pr-str '~check))))))
+     (throw (new AssertionError (str "Trammel assertion failed: " ~message "\n"
+                                     (pr-str '~check))))))

 (defn check-args!
   [name slots inv-description invariants]
@@ -15,4 +16,3 @@
                          "[pre-conditions => post-conditions] or "
                          "{:pre [pre-conditions]}"
                          "for record type " name)))
-


CMR-5067 Cleanup.

CMR-5067 Cleanup.

--- umm-spec-lib/test/cmr/umm_spec/test/umm_g/granule.clj
+++ umm-spec-lib/test/cmr/umm_spec/test/umm_g/granule.clj
@@ -26,9 +26,8 @@
 (defn- sanitize-operation-modes
   "Sanitizer for operation-modes, if sequence it removes duplicates, if nil it inserts a not provided."
   [operation-modes]
-  (cond
-    (seq operation-modes) (distinct operation-modes)
-    (nil? operation-modes) nil))
+  (when (seq operation-modes)
+    (distinct operation-modes)))

 (defn- sanitize-granule
   "Sanitizes umm-lib generated granule."


Fix indenting

Fix indenting

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -484,12 +484,12 @@
         (html
           [:nav.aside-left-nav

-            [:a.aside-item.logo {:title "Home"
+           [:a.aside-item.logo {:title "Home"
                                 :data-placement "right"
                                 :data-trigger "hover"
                                 :href "/"}
-            [:div.logomark
-             (common/ico :logo)]]
+             [:div.logomark
+              (common/ico :logo)]]

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


put changelog aside menu item back

put changelog aside menu item back

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -394,12 +394,20 @@
                            :title "Invite your teammates"}
             [:i.fa.fa-user]]

-        (when (feature/enabled? :insights)
-          [:a.aside-item {:data-placement "right"
-                          :data-trigger "hover"
-                          :title "Insights"
-                          :href "/build-insights"}
-           [:i.fa.fa-bar-chart]])
+           [:a.aside-item {:data-placement "right"
+                           :data-trigger "hover"
+                           :title "Changelog"
+                           :href "/changelog"
+                           :class (when (changelog-updated-since? (:last_viewed_changelog user))
+                                    "unread")}
+            [:i.fa.fa-bell]]
+
+           (when (feature/enabled? :insights)
+             [:a.aside-item {:data-placement "right"
+                             :data-trigger "hover"
+                             :title "Insights"
+                             :href "/build-insights"}
+              [:i.fa.fa-bar-chart]])

            (when (:admin user)
              [:a.aside-item {:data-placement "right"


Add :scope provided to clojure dep

Add :scope provided to clojure dep


Update lein to 2.7.0

Update lein to 2.7.0

--- build.boot
+++ build.boot
@@ -4,8 +4,7 @@
   :dependencies '[[org.clojure/test.check "0.9.0" :scope "test"]
                   ; project deps
                   [org.clojure/clojure "1.9.0-alpha11"]
-                  [leiningen "2.6.1" :exclusions [leiningen.search org.clojure/data.xml]]
-                  [org.clojure/data.xml "0.0.8"] ; for leiningen
+                  [leiningen "2.7.0" :exclusions [leiningen.search]]
                   [ring "1.4.0"]
                   [clojail "1.0.6"]])


Update build.boot

Update build.boot

--- build.boot
+++ build.boot
@@ -13,7 +13,7 @@
                           ;[degree9/covenant            "0.1.0-SNAPSHOT"]
                           ;[degree9/boot-docker         "0.1.0-SNAPSHOT"]
                           [degree9/boot-nodejs         "1.4.0"]
-                          [degree9/boot-npm            "1.11.0"]
+                          [degree9/boot-npm            "1.12.0-SNAPSHOT"]
                           ;[degree9/boot-exec           "1.1.0-SNAPSHOT"]
                           [degree9/boot-semver         "1.8.0"]
                           [degree9/boot-semgit         "1.3.0"]


Remove superfluous (println) in golang generator

Signed-off-by: Greg Haskins <640d9fe47775e6723f0355b7315e38f7d98d3539@gmail.com>

--- src/chaintool/platforms/golang/core.clj
+++ src/chaintool/platforms/golang/core.clj
@@ -175,7 +175,6 @@
 ;; config
 ;;-----------------------------------------------------------------
 (defn generate [{:keys [ipath opath config base package] :as params}]
-  (println params)
   (let [interfaces (intf/compile ipath config)]

      ;; generate protobuf output


Move search logic to desktopmenu

Move search logic to desktopmenu

--- src/cljs/daveconservatoire/site/ui.cljs
+++ src/cljs/daveconservatoire/site/ui.cljs
@@ -218,17 +218,21 @@
 (defn signed-in? [me]
   (boolean (:user/name me)))

+(declare LessonCell lesson-cell)
+
 (om/defui ^:once DesktopMenu
   static om/Ident
   (ident [_ props]
     (u/model-ident props))

   static om/IQuery
-  (query [_] [:db/id :db/table :user/name :user/score])
-
-  Object
-  (render [this]
-    (let [{:keys [user/score] :as props} (om/props this)]
+  (query [_] [:db/id :db/table :user/name :user/score
+              {:lesson/search (om/get-query LessonCell)}
+              :ui/search-text])
+
+  Object
+  (render [this]
+    (let [{:keys [user/score lesson/search ui/search-text] :as props} (om/props this)]
       (dom/div #js {:className "header hidden-phone"}
         (dom/div #js {:className "navbar"}
           (dom/div #js {:className "navbar-inner"}
@@ -241,6 +245,18 @@
                   (button {:react-key "btn-1" ::r/handler ::r/donate, ::button-color "orange"} "Donate")
                   (button {:react-key "btn-2" ::r/handler ::r/tuition, ::button-color "redorange"} "Personal Tuition")
                   (button {:react-key "btn-3" ::r/handler ::r/contact, ::button-color "red"} "Contact")
+                  (dom/form #js {:onSubmit #(do
+                                              (.preventDefault %)
+                                              (df/load (om/get-reconciler this) :lesson/search LessonCell {:params  {:lesson/title search-text}
+                                                                                :target  [:route/data :lesson/search]
+                                                                                :refresh [:lesson/search]}))}
+                    (dom/input #js {:value    (or search-text "")
+                                    :onChange #(om/transact! this `[(app/set-route-data {:ui/search-text ~(.. % -target -value)})])})
+                    (dom/button #js {:type "submit"} "Do Search!")
+                    #_ (dom/div #js {:className "container wrapper"}
+                         (dom/div #js {:className "tab-content"}
+                           (dom/div #js {:className "tab-pane active"}
+                             (map lesson-cell search)))))
                   (if (signed-in? props)
                     (user-menu-status this)
                     (if (> score 0)
@@ -1237,18 +1253,14 @@

 (om/defui ^:once HomePage
   static uc/InitialAppState
-  (initial-state [_ _] {:app/courses []
-                        :lesson/search nil
-                        :ui/search-text ""})
-
-  static om/IQuery
-  (query [_] [{:app/courses (om/get-query HomeCourse)}
-              {:lesson/search (om/get-query LessonCell)}
-              :ui/search-text])
-
-  Object
-  (render [this]
-    (let [{:keys [app/courses lesson/search ui/search-text]} (om/props this)]
+  (initial-state [_ _] {:app/courses []})
+
+  static om/IQuery
+  (query [_] [{:app/courses (om/get-query HomeCourse)}])
+
+  Object
+  (render [this]
+    (let [{:keys [app/courses]} (om/props this)]
       (dom/div nil
         (hero {:react-key "hero"})
         (homeboxes {:react-key "homeboxes"})
@@ -1257,19 +1269,7 @@
             (dom/div #js {:className "container intro_wrapper"}
               (dom/div #js {:className "inner_content"}
                 (dom/div #js {:className "pad30"})
-                (dom/h1 #js {:className "title"} "Search")
-                (dom/form #js {:onSubmit #(do
-                                            (.preventDefault %)
-                                            (df/load (om/get-reconciler this) :lesson/search LessonCell {:params  {:lesson/title search-text}
-                                                                                :target  [:route/data :lesson/search]
-                                                                                :refresh [:lesson/search]}))}
-                  (dom/input #js {:value    (or search-text "")
-                                  :onChange #(om/transact! this `[(app/set-route-data {:ui/search-text ~(.. % -target -value)})])})
-                  (dom/button #js {:type "submit"} "Do Search!")))))
-          (dom/div #js {:className "container wrapper"}
-            (dom/div #js {:className "tab-content"}
-              (dom/div #js {:className "tab-pane active"}
-                (map lesson-cell search)))))
+                (dom/h1 #js {:className "title"} "Search")))))
         (map home-course courses)))))

 (defmethod r/route->component ::r/home [_] HomePage)


update subscription page with modal

update subscription page with modal

--- src/cljs/daveconservatoire/site/ui.cljs
+++ src/cljs/daveconservatoire/site/ui.cljs
@@ -20,6 +20,9 @@
             [clojure.string :as str])
   (:import goog.i18n.DateTimeFormat
            goog.async.Debouncer))
+
+(declare modal)
+

 (defn debounce [f interval]
   (let [dbnc (Debouncer. f interval)]
@@ -672,13 +675,13 @@
               (dom/div #js {:className "span4"}
                 (dom/div #js {:className "tile introboxes"}
                   (dom/div #js {:className "intro-icon-disc  social-share"}
-                    (dom/img #js {:src "/img/googleplus.png"}))(dom/a #js {:href "/socialloader/gplus", :target "_blank", :className "btn btn-primary  btn-custom btn-rounded btn-block dc-btn-redorange"} "Share Dave Conservatoire on Google Plus"))
+                    (dom/img #js {:src "/img/googleplus.png"})) (dom/a #js {:href "/socialloader/gplus", :target "_blank", :className "btn btn-primary  btn-custom btn-rounded btn-block dc-btn-redorange"} "Share Dave Conservatoire on Google Plus"))
                 (dom/div #js {:className "pad25"})))
             (dom/div #js {:className "strip"} (dom/h1 #js {:className "center"} "Thanks for taking the time to do this")
                                               (dom/h1 #js {})
                                               (dom/h3 #js {:className "center about_strip"} " Ready to get back to learning? ")
                                               (dom/div #js {:className "pad45"})
-                                              (dom/a #js {:href "/", :className "big_button"} "Let's go!")(dom/div #js {:className "pad25"}))))))))
+                                              (dom/a #js {:href "/", :className "big_button"} "Let's go!") (dom/div #js {:className "pad25"}))))))))

 (defmethod r/route->component ::r/socialmedia [_] SocialMediaPage)

@@ -696,25 +699,28 @@
             (dom/h3 #js {:className "center about_strip"} "You are now officially a Dave Conservatoire subscriber. ")
             (dom/h3 #js {:className "center about_strip"} "You are playing a role in making a world class music education available to everyone everywhere!")
             (dom/h3 #js {:className "center about_strip"} " Ready to get back to learning? ")
-            (dom/div #js {:className "pad45"})(dom/a #js {:href "/", :className "big_button"} "Let's go!")
+            (dom/div #js {:className "pad45"}) (dom/a #js {:href "/", :className "big_button"} "Let's go!")
             (dom/div #js {:className "pad25"})))))))

 (defmethod r/route->component ::r/thanks [_] ThanksPage)

+
+(defn paypal-donate-url [donation-value]
+  (str "https://www.paypal.com/cgi-bin/webscr?business=dave@daveconservatoire.org&cmd=_xclick-subscriptions&currency_code=USD&p3=1&t3=M&no_shipping=1&src=1&sra=1&a3=" donation-value "&item_name=Dave%20Conservatoire%20Subscription%20&return_url=http://www.daveconservatoire.org/thanks&cancel_return=http://www.daveconservatoire.org/subscribe"))

 (om/defui ^:once SubscriptionPage
   static uc/InitialAppState
-  (initial-state [_ _] {:ui/donation-value 9})
-
-  static om/IQuery
-  (query [_] [:ui/donation-value ])
+  (initial-state [_ _] {:ui/donation-value 9 :ui/show-modal? false})
+
+  static om/IQuery
+  (query [_] [:ui/donation-value :ui/show-modal?])

   static om/Ident
   (ident [_ props] [:page/by-id "subscribe-page"])

   Object
   (render [this]
-    (let [{:keys [ui/donation-value]} (om/props this)]
+    (let [{:keys [ui/donation-value ui/show-modal?]} (om/props this)]
       (dom/div #js {}
         (course-banner {:title "Voluntary Subscription" :intro "Dave Conservatoire will always be free. But please consider subscribing!"})
         (dom/div #js {:className "container wrapper"}
@@ -757,25 +763,28 @@
                   (dom/div #js {:className "alert alert-success subchange"}
                     (dom/p #js {:id "subamount"}
                       "I would like to subscribe to Dave Conservatoire for $" (or donation-value "9") " per month.")
-                    (dom/a #js {:className "btn btn-block btn-primary dc-orange subbutton" :target "_blank" :href (str "https://www.paypal.com/cgi-bin/webscr?business=dave@daveconservatoire.org&cmd=_xclick-subscriptions&currency_code=USD&p3=1&t3=M&no_shipping=1&src=1&sra=1&a3=" donation-value "&item_name=Dave%20Conservatoire%20Subscription%20&return_url=http://www.daveconservatoire.org/thanks&cancel_return=http://www.daveconservatoire.org/subscribe")}
+                    (dom/a #js {:className "btn btn-block btn-primary dc-orange subbutton" :target "_blank" :href (paypal-donate-url (or donation-value 9))}
                       "\n\t\t         Submit\n\t\t     "))
                   (dom/div #js {:className "alert alert-danger subchange"}
                     (dom/p #js {:id "subamount"}
                       "I am unable to support Dave Conservatoire at this time. \uD83D\uDE22")
-                    (dom/a #js {:className "btn btn-block btn-primary dc-orange subbutton" :target "_blank" :href ""}
-                      "\n\t\t         Submit\n\t\t     "))
-                  ))
-              )))
-        (dom/div #js {:id "suremodal", :className "modal hide fade in", :style #js{"display" "block"}, :aria-hidden "false"}
-          (dom/div #js {:className "modal-header"}
-            (dom/button #js {:type "button", :className "close", :data-dismiss "modal", :aria-hidden "true"}
-              "×")(dom/h3 #js {} "Sure you can't just nudge us in the right direction?"))
-          (dom/div #js {:className "modal-body"}
+                    (dom/a #js {:className "btn btn-block btn-primary dc-orange subbutton"
+                                :onClick #(um/set-value! this :ui/show-modal? true)}
+                      "\n\t\t         Submit\n\t\t     ")))))))
+        (if show-modal?
+          (modal #:ui.modal{:title   "Sure you can't just nudge us in the right direction?"
+                            :footer  (fn [{:ui.modal/keys [title footer onClose onConfirm]}]
+                                       (dom/div #js {:className "modal-footer"}
+                                         (dom/a #js {:className "btn btn-success"
+                                                     :href      (paypal-donate-url 1)
+                                                     :target    "_blank"}
+                                           "Okay!  Let's do this! ($1/month subscription)")
+                                         (link {:className  "btn btn-danger"
+                                                ::r/handler ::r/socialmedia}
+                                           "Still a no, sorry")))
+                            :onClose #(um/set-value! this :ui/show-modal? false)}
             (dom/p #js {} "Could you spare just $1 each month for a worthy cause?  Music students around the world will thank you for it!")
-            (dom/p #js {} "A hard-up student?  No worries, we're still cool."))
-          (dom/div #js {:className "modal-footer"}
-            (dom/a #js {:href "https://www.paypal.com/cgi-bin/webscr?business=dave@daveconservatoire.org&cmd=_xclick-subscriptions&currency_code=USD&p3=1&t3=M&no_shipping=1&src=1&sra=1&a3=1&item_name=Dave%20Conservatoire%20Subscription%20&return_url=http://www.daveconservatoire.org/thanks&cancel_return=http://www.daveconservatoire.org/subscribe", :id "onedollar", :className "btn btn-success"} "Okay!  Let's do this! ($1/month subscription)")
-            (dom/a #js {:href "/socialmedia", :id "stillno", :className "btn btn-danger"} "Still a no, sorry. ")))))))
+            (dom/p #js {} "A hard-up student?  No worries, we're still cool.")))))))

 (defmethod r/route->component ::r/subscribe [_] SubscriptionPage)

@@ -1254,63 +1263,65 @@

 (def profile-recent-activity (om/factory ProfileRecentActivity {:keyfn :db/id}))

-(defn modal [{:ui.modal/keys [title onClose onSave]} & children]
+(defn modal [{:ui.modal/keys [title footer onClose onConfirm] :as props} & children]
   (portal {:append-to "body"}
-          (dom/div #js {:style #js {:position   "absolute"
-                                    :left       0
-                                    :top        0
-                                    :background "rgba(0, 0, 0, 0.5)"
-                                    :width      "100vw"
-                                    :height     "100vh"}}
-            (dom/div #js {:id "myModal" :className "modal hide fade in" :tabIndex "-1" :role "dialog" :style #js {:display "block"}}
-              (dom/div #js {:className "modal-header"}
-                (dom/button #js {:type "button" :className "close" :onClick #(if onClose (onClose))}
-                  "×")
-                (dom/h3 #js {:id "myModalLabel"}
-                  title))
-              (dom/div #js {:className "modal-body"}
-                (apply dom/div nil children)
-                (dom/div #js {:className "row buttons"})
-                (dom/div #js {:className "modal-footer"}
-                  (dom/button #js {:className "btn"
-                                   :onClick   #(if onClose (onClose))}
-                    "Close")
-                  (dom/button #js {:className "btn btn-primary"
-                                   :onClick   #(if onSave (onSave))}
-                    "Save")))))))
+    (dom/div #js {:style #js {:position   "absolute"
+                              :left       0
+                              :top        0
+                              :background "rgba(0, 0, 0, 0.5)"
+                              :width      "100vw"
+                              :height     "100vh"}}
+      (dom/div #js {:id "myModal" :className "modal hide fade in" :tabIndex "-1" :role "dialog" :style #js {:display "block"}}
+        (dom/div #js {:className "modal-header"}
+          (dom/button #js {:type "button" :className "close" :onClick #(if onClose (onClose))}
+            "×")
+          (dom/h3 #js {:id "myModalLabel"}
+            title))
+        (dom/div #js {:className "modal-body"}
+          (apply dom/div nil children)
+          (dom/div #js {:className "row buttons"})
+          (if footer
+            (footer props)
+            (dom/div #js {:className "modal-footer"}
+              (dom/button #js {:className "btn"
+                               :onClick   #(if onClose (onClose))}
+                "Close")
+              (dom/button #js {:className "btn btn-primary"
+                               :onClick   #(if onConfirm (onConfirm))}
+                "Save"))))))))

 (defn user-info-modal [this]
   (let [{:keys [user/about ui/tmp-about]} (om/props this)]
-    (modal #:ui.modal {:title   "Update your Profile"
-                       :onClose #(do
-                                   (um/set-value! this :ui/editing-info? false)
-                                   (um/set-value! this :ui/tmp-about about)
-                                   (om/transact! this [:ui/editing-info?]))
-                       :onSave  #(do
-                                   (om/transact! this `[(user/update {:user/about ~tmp-about})])
-                                   (um/set-value! this :ui/editing-info? false)
-                                   (om/transact! this [:ui/editing-info?]))}
-           (dom/form #js {:id "user-form" :action "profile/update" :method "post"}
-             (dom/div #js {:id "user-form_es_" :className "errorSummary" :style #js {:display "none"}}
-               (dom/p nil
-                 "Please fix the following input errors:")
-               (dom/ul nil
-                 (dom/li nil
-                   "dummy")))
-             (dom/label #js {:htmlFor "User_biog"}
-               (dom/h3 nil
-                 "About you") "Who are you? What are your musical goals? What instruments do you play? "
-               (dom/br nil)
-               "(max. 160 characters)"
-               (dom/br nil)
-               (dom/br nil))
-             (dom/textarea #js {:size      "60"
-                                :maxLength "160"
-                                :id        "User_biog"
-                                :value     (or tmp-about about)
-                                :onChange  #(um/set-string! this :ui/tmp-about :event %)
-                                :style     #js {:zIndex "auto" :position "relative" :lineHeight "20px" :fontSize 14 :transition "none" :background "none 0% 0% / auto repeat scroll padding-box border-box rgb(255 255 255)"}})
-             (dom/div #js {:className "errorMessage" :id "User_biog_em_" :style #js {:display "none"}})))))
+    (modal #:ui.modal {:title     "Update your Profile"
+                       :onClose   #(do
+                                     (um/set-value! this :ui/editing-info? false)
+                                     (um/set-value! this :ui/tmp-about about)
+                                     (om/transact! this [:ui/editing-info?]))
+                       :onConfirm #(do
+                                     (om/transact! this `[(user/update {:user/about ~tmp-about})])
+                                     (um/set-value! this :ui/editing-info? false)
+                                     (om/transact! this [:ui/editing-info?]))}
+      (dom/form #js {:id "user-form" :action "profile/update" :method "post"}
+        (dom/div #js {:id "user-form_es_" :className "errorSummary" :style #js {:display "none"}}
+          (dom/p nil
+            "Please fix the following input errors:")
+          (dom/ul nil
+            (dom/li nil
+              "dummy")))
+        (dom/label #js {:htmlFor "User_biog"}
+          (dom/h3 nil
+            "About you") "Who are you? What are your musical goals? What instruments do you play? "
+          (dom/br nil)
+          "(max. 160 characters)"
+          (dom/br nil)
+          (dom/br nil))
+        (dom/textarea #js {:size      "60"
+                           :maxLength "160"
+                           :id        "User_biog"
+                           :value     (or tmp-about about)
+                           :onChange  #(um/set-string! this :ui/tmp-about :event %)
+                           :style     #js {:zIndex "auto" :position "relative" :lineHeight "20px" :fontSize 14 :transition "none" :background "none 0% 0% / auto repeat scroll padding-box border-box rgb(255 255 255)"}})
+        (dom/div #js {:className "errorMessage" :id "User_biog_em_" :style #js {:display "none"}})))))

 (om/defui ^:once ProfileDashboard
   static om/Ident


Show graph of live stats on click

Show graph of live stats on click

--- src/cljs/sidequarter_frontend/core.cljs
+++ src/cljs/sidequarter_frontend/core.cljs
@@ -3,6 +3,7 @@
     (:require[om.core :as om :include-macros true]
              [om.dom :as dom :include-macros true]
              [cljs.core.async :refer [<!]]
+             [cljsjs.chart]
              [sidequarter-frontend.api :as api]))

 (enable-console-print!)
@@ -48,7 +49,7 @@
   (reify
     om/IInitState
     (init-state [_]
-      {:graph [] :interval-id nil})
+      {:graph [] :interval-id nil :graph-chart nil})
     om/IDidMount
     (did-mount [_]
       (let [interval-id
@@ -58,13 +59,23 @@
                  (let [response ((<! (api/get-stats (data :id))) :body)
                        stats (:stats response)]
                    (om/update-state! owner [:graph] #(conj % stats))))
-               ) 2000)]
+               ) 2000)
+            chart-ctx (. (. js/document (getElementById (str "graph-" (data :id)))) (getContext "2d"))
+            config #js {:type "line" :data #js {:labels #js [] :datasets #js []}}
+            graph-chart (js/Chart. chart-ctx config)]
+        (om/set-state! owner [:graph-chart] graph-chart)
         (om/set-state! owner [:interval-id] interval-id)))
     om/IRenderState
     (render-state [_ {:keys [graph]}]
-      (.log js/console (pr-str graph))
       (dom/div #js {:className "col s12"}
-               (dom/h5 nil "Live stats")))
+               (dom/h5 nil "Live stats")
+               (dom/canvas #js {:id (str "graph-" (data :id))
+                                :style #js {:width "90%" :height "350px"}} nil)))
+    om/IDidUpdate
+    (did-update [_ _ {:keys [graph-chart graph]}]
+      (if (empty? graph)
+        nil
+        nil)) ;; Update the graph with new stats
     om/IWillUnmount
     (will-unmount [_]
       (js/clearInterval (om/get-state owner [:interval-id])))))