tidy up some trig ugens

tidy up some trig ugens

--- src/overtone/sc/machinery/ugen/metadata/trig.clj
+++ src/overtone/sc/machinery/ugen/metadata/trig.clj
@@ -11,70 +11,88 @@
   [

    {:name "TWindex"
-    :description "Triggered window"
+    :summary "Triggered window"
+    :args [{:name "trig"
+            :doc "Trigger - can be any signal. A trigger happens when
+                  the signal changes from non-positive to positive." }
+
+           {:name "array",
+            :doc  "list of probabilities"
+            :array true }
+
+           {:name "normalize",
+            :default 0
+            :doc "normalise flag - 0 off, 1 on"}]
     :doc "When triggered, returns a random index value based on array as
           a list of probabilities. By default the list of probabilities
           should sum to 1.0, when the normalize flag is set to 1, the
           values get normalized by the ugen (less efficient)."

-    :args [{:name "trig"
-            :doc "Trigger - can be any signal. A trigger happens when
-                  the signal changes from non-positive to positive." }
-
-           {:name "array",
-            :doc  "list of probabilities"
-            :array true }
-
-           {:name "normalize",
-            :doc "normalise flag - 0 off, 1 on"
-            :default 0}]
+
     :default-rate :kr}

    {:name "Trig1"
-    :description "Timed trigger"
-    :doc "Outputs one for dur seconds whenever the input goes from
-          negative to positive, otherwise outputs 0."
-
+    :summary "Timed trigger"
     :args [{:name "trig",
+            :default 0.0
             :doc "trigger. Trigger can be any signal. A trigger happens
                   when the signal changes from non-positive to
-                  positive."
-            :default 0.0}
+                  positive."}

            {:name "dur",
-            :doc  "duration of the trigger output in seconds."
-            :default 0.1 }]
+            :default 0.1
+            :doc  "duration of the trigger output in seconds."}]
     :signal-range :unipolar
-    :default-rate :kr}
+    :default-rate :kr
+    :doc "Outputs one for dur seconds whenever the input goes from
+          negative to positive, otherwise outputs 0."}

    {:name "Trig" :extends "Trig1"
-    :description "Timed trigger"
+    :summary "Timed trigger"
     :doc "When a nonpositive to positive transition occurs at the input,
           Trig outputs the level of the triggering input for the
           specified duration, otherwise it outputs zero."}

    {:name "TDelay"
-    :description "Trigger delay"
+    :summary "Trigger delay"
+    :args [{:name "trig",
+            :default 0.0
+            :doc "input trigger signal."}
+
+           {:name "dur"
+            :default 0.1
+            :doc "delay time in seconds."}]
+    :signal-range :unipolar
+    :default-rate :kr
+    :check [(same-rate-as-first-input)]
     :doc "Delays an input trigger by dur, ignoring other triggers in the
-          meantime"
-
-    :args [{:name "trig",
-            :doc "input trigger signal."
-            :default 0.0 }
-
-           {:name "dur"
-            :doc "delay time in seconds."
-            :default 0.1 }]
-    :signal-range :unipolar
-    :default-rate :kr
-    :check [(same-rate-as-first-input)]}
+          meantime"}

    {:name "SendTrig"
-    :description "Send a /tr OSC message to Overtone"
+    :summary "Send a /tr OSC message to Overtone"
+    :args [{:name "in"
+            :default 0.0
+            :doc "input trigger signal"}
+
+           {:name "id"
+            :default 0
+            :doc "an integer that will be passed with the trigger
+                  message. This is useful if you have more than one
+                  SendTrig in a SynthDef"}
+
+           {:name "value"
+            :default 0.0
+            :doc "A UGen or float that will be polled at the time of
+                  trigger, and its value passed with the trigger
+                  message"}]
+
+    :default-rate :kr
+    :num-outs 0
+    :check [(same-rate-as-first-input)]
     :doc "On receiving a trigger sends a :trigger event with id and
           value. This command is the mechanism that synths can use to
           trigger events in clients.
@@ -87,30 +105,29 @@

           int   - trigger ID

-          float - trigger value"
-
-    :args [{:name "in"
-            :doc "input trigger signal"
-            :default 0.0 }
-
-           {:name "id"
-            :doc "an integer that will be passed with the trigger
-                  message. This is useful if you have more than one
-                  SendTrig in a SynthDef"
-            :default 0 }
-
-           {:name "value"
-            :doc "A UGen or float that will be polled at the time of
-                  trigger, and its value passed with the trigger
-                  message"
-            :default 0.0 }]
-    :default-rate :kr
-    :num-outs 0
-    :check [(same-rate-as-first-input)]}
+          float - trigger value"}

    {:name "SendReply"
-    :description "Send information via OSC to Overtone"
+    :summary "Send information via OSC to Overtone"
+    :args [{:name "trig"
+            :default 0.0
+            :doc "Input trigger signal"}
+
+           {:name "cmd-name"
+            :default "/reply"
+            :doc "A string or symbol, as a message name."
+            :mode :append-string }
+
+           {:name "values"
+            :default 0.0
+            :doc "Array of ugens, or valid ugen inputs"
+            :mode :append-sequence }
+
+           {:name "reply-id"
+            :default -1
+            :doc "Integer id (similar to that used by send-trig)"}]
+    :default-rate :kr
     :doc "Send an array of values from the server via an
           message. The OSC message is formed with cmd-name as the path,
           followed by two compulsary args: node-id (the id of the node
@@ -130,65 +147,47 @@

           You can register to respond to this event as follows:

-          (on-event \"/foobar\" (fn [msg] (println msg)) ::handle-foobar)"
-    :args [{:name "trig"
-            :doc "Input trigger signal"
-            :default 0.0 }
-
-           {:name "cmd-name"
-            :doc "A string or symbol, as a message name."
-            :default "/reply"
-            :mode :append-string }
-
-           {:name "values"
-            :doc "Array of ugens, or valid ugen inputs"
-            :default 0.0
-            :mode :append-sequence }
-
-           {:name "reply-id"
-            :doc "Integer id (similar to that used by send-trig)"
-            :default -1 }]
-    :default-rate :kr}
+          (on-event \"/foobar\" (fn [msg] (println msg)) ::handle-foobar)"}

    {:name "Latch"
-    :description "Sample and hold"
-    :doc "Holds input signal value when triggered."
+    :summary "Sample and hold"
     :args [{:name "in"
-            :doc "Input signal."
-            :default 0.0 }
+            :default 0.0
+            :doc "Input signal."}

            {:name "trig"
+            :default 0.0
             :doc "Trigger. Trigger can be any signal. A trigger happens
                   when the signal changes from non-positive to
-                  positive."
-            :default 0.0}]
-    :default-rate :kr}
+                  positive."}]
+    :default-rate :kr
+    :doc "Holds input signal value when triggered."}

    {:name "Gate" :extends "Latch"
-    :description "Gate or hold"
+    :summary "Gate or hold"
     :doc "Lets signal flow when trig is positive, otherwise holds last
           input value"}

    {:name "PulseCount"
-    :description "Pulse counter"
-    :doc "Each input trigger increments a counter value that is output."
-    :args [{:name "trig"
+    :summary "Pulse counter"
+    :args [{:name "trig"
+            :default 0.0
             :doc "Trigger. Trigger can be any signal. A trigger happens
-                  when the signal changes from non-positive to positive."
-            :default 0.0 }
+                  when the signal changes from non-positive to positive."}

            {:name "reset"
-            :doc "Resets the counter to zero when triggered."
-            :default 0.0 }]
+            :default 0.0
+            :doc "Resets the counter to zero when triggered."}]
     :check (same-rate-as-first-input)
-    :default-rate :kr}
+    :default-rate :kr
+    :doc "Each input trigger increments a counter value that is output."}

    {:name "SetResetFF", :extends "PulseCount"
-    :description "Set-reset flip flop"
+    :summary "Set-reset flip flop"
     :doc "When a trigger is received the output is set to 1.0 Subsequent
           triggers have no effect When a trigger is received in the
           reset input, the output is set back to 0.0
@@ -198,27 +197,27 @@

    {:name "Peak", :extends "PulseCount"
-    :description "Track peak signal amplitude"
+    :summary "Track peak signal amplitude"
     :doc "Outputs the peak amplitude of the signal so far, a trigger
           resets to current value"}

    {:name "RunningMin", :extends "Latch"
-    :description "Track minimum level"
+    :summary "Track minimum level"
     :doc "Outputs the minimum value received at the input. When
           triggered, the minimum output value is reset to the current
           value." }

    {:name "RunningMax", :extends "Latch"
-    :description "Track maximum level"
+    :summary "Track maximum level"
     :doc "Outputs the maximum value received at the input. When
           triggered, the maximum output value is reset to the current
           value." }

    {:name "Stepper"
-    :description "Pulse counter"
+    :summary "Pulse counter"
     :doc "Triggers increment a counter which is output as a signal. The
           counter loops around from max to min by step increments"

@@ -252,7 +251,7 @@

    {:name "PulseDivider"
-    :description "Pulse divider"
+    :summary "Pulse divider"
     :doc "Outputs a trigger every div input triggers"
     :args [{:name "trig"
             :doc "Trigger. Trigger can be any signal. A trigger happens
@@ -274,7 +273,7 @@

    {:name "ToggleFF"
-    :description "Toggle flip flop"
+    :summary "Toggle flip flop"
     :doc "Flip-flops between zero and one each trigger"
     :args [{:name "trig"
             :doc "trigger input"
@@ -283,7 +282,7 @@

    {:name "ZeroCrossing"
-    :description "Zero crossing frequency follower"
+    :summary "Zero crossing frequency follower"
     :doc "Outputs a frequency based upon the distance between
           interceptions of the X axis. The X intercepts are determined
           via linear interpolation so this gives better than just
@@ -297,7 +296,7 @@

    {:name "Timer"
-    :description "Trigger timer"
+    :summary "Trigger timer"
     :doc "Outputs time since last trigger"

     :args [{:name "trig"
@@ -308,7 +307,7 @@

    {:name "Sweep"
-    :description "Triggered linear ramp"
+    :summary "Triggered linear ramp"
     :doc "outputs a linear increasing signal by rate/second when trig input crosses from non-positive to positive"

     :args [{:name "trig"
@@ -322,7 +321,7 @@

    {:name "Phasor"
-    :description "Resettable linear ramp between two levels"
+    :summary "Resettable linear ramp between two levels"
     :doc "Phasor is a linear ramp between start and end values. When its
           trigger input crosses from non-positive to positive, Phasor's
           output will jump to its reset position. Upon reaching the end
@@ -356,7 +355,7 @@

    {:name "PeakFollower"
-    :description "Track peak signal amplitude"
+    :summary "Track peak signal amplitude"
     :doc "Outputs the peak signal amplitude, falling with decay over
          time until reaching signal level"
     :args [{:name "in"
@@ -370,7 +369,7 @@

    {:name "Pitch"
-    :description "Autocorrelation pitch follower"
+    :summary "Autocorrelation pitch follower"
     :doc "This is a better pitch follower than zero-crossing, but more
           costly of CPU. For most purposes the default settings can be
           used and only in needs to be supplied. Pitch returns two
@@ -440,7 +439,7 @@

    {:name "InRange"
-    :description "Tests if a signal is within a given range"
+    :summary "Tests if a signal is within a given range"
     :doc "If in is >= lo and <= hi output 1.0, otherwise output
           0.0. Output is initially zero."
     :args [{:name "in"
@@ -457,13 +456,13 @@
     :default-rate :kr}

    {:name "Fold", :extends "InRange"
-    :description "Fold a signal outside given thresholds."
+    :summary "Fold a signal outside given thresholds."
     :doc "Folds input wave to within the lo and hi thresholds. This
          differs from the ugen fold2 in that it allows one to
          set both low and high thresholds."}

    {:name "Clip"
-    :description "Clip a signal outside given thresholds."
+    :summary "Clip a signal outside given thresholds."
     :doc "Clip a signal outside given thresholds. This differs from the
           ugen clip2 in that it allows one to set both low and high
           thresholds."
@@ -481,20 +480,20 @@
     :default-rate :kr}

    {:name "Wrap", :extends "InRange"
-    :description "Wrap a signal outside given thresholds."
+    :summary "Wrap a signal outside given thresholds."
     :doc "Wraps input wave to the low and high thresholds. This differs
          from the ugen wrap2 in that it allows one to set both
          low and high thresholds." }

    {:name "Schmidt", :extends "InRange"
-    :description "Schmidt trigger"
+    :summary "Schmidt trigger"
     :doc "Outout one when signal greater than high, and zero when lower
          than low." }

    ;; TODO maybe allow a rect datatype as arg
    ;;      and write init function to handle it
    {:name "InRect"
-    :description "Test if a point is within a given rectangle."
+    :summary "Test if a point is within a given rectangle."
     :doc "Outputs one if the 2d coordinate of x,y input values falls
           inside a rectangle, else zero"
     :args [{:name "x"
@@ -520,7 +519,7 @@
     :default-rate :kr}

    {:name "MostChange"
-    :description "Output most changed"
+    :summary "Output most changed"
     :doc "output whichever signal changed the most"
     :args [{:name "a"
             :doc "first input"
@@ -532,11 +531,11 @@
     :default-rate :kr}

    {:name "LeastChange", :extends "MostChange"
-    :description "Output least changed"
+    :summary "Output least changed"
     :doc "output whichever signal changed the least"}

    {:name "LastValue"
-    :description "Output the last value before the input changed"
+    :summary "Output the last value before the input changed"
     :doc "Output the last value before the input changed by a threshold
           of diff"
     :args [{:name "in",


debugger: do not save highlighted signals

--- examples/_common/middleware/devtools.cljs
+++ examples/_common/middleware/devtools.cljs
@@ -180,12 +180,15 @@
                  (let [loaded-model (get storage storage-key)]
                    (when (-> loaded-model ::debugger :replay-mode?)
                      ; updating :initial-model so that on hot reload we don't see changes after modifying app init code
-                     (dispatch-action [::load (assoc-in loaded-model [::debugger :initial-model] (-> @model ::debugger :initial-model))])
+                     (let [new-model (assoc-in loaded-model [::debugger :initial-model] (-> @model ::debugger :initial-model))]
+                       (dispatch-action [::load new-model]))
+
                      (dispatch-action ::replay)))

                  ; start persisting replayable events
                  (run!
                    (let [saved-model (-> @model
+                                         (assoc-in [::debugger :highlighted-signal-id] nil)
                                          (update-in [::debugger :action-events] #(filter :for-replay? %))
                                          -remove-orphaned-signals)]
                      (assoc! storage storage-key saved-model)))


add test schema

add test schema

--- test/graphql_clj/parser_test.clj
+++ test/graphql_clj/parser_test.clj
@@ -346,6 +346,108 @@

 type SearchQuery {
   firstSearchResult: SearchResult
+}"
+
+   "
+interface Being {
+ name: String
+}
+
+interface Pet {
+  name: String
+}
+
+interface Canine {
+  name(surname: Boolean): String
+}
+
+enum DogCommand {
+  SIT @enumInt(value: 0)
+  HEEL @enumInt(value: 1)
+  DOWN @enumInt(value: 2)
+}
+
+enum FurColor {
+  BROWN @enumInt(value: 0)
+  BLACK @enumInt(value: 1)
+  TAN @enumInt(value: 2)
+  SPOTTED @enumInt(value: 3)
+}
+
+type Dog implements Being, Pet, Canine {
+  name(surname: Boolean): String
+  nickname: String
+  barks: Boolean
+  barkVolume: Int
+  doesKnowCommand(dogCommand: DogCommand): Boolean
+  isHousetrained(atOtherHomes: Boolean = true): Boolean
+  isAtLocation(x: Int, y: Int): Boolean
+}
+
+type Cat implements Being, Pet {
+  name: String
+  nickname: String
+  meows: Boolean
+  meowVolume: Int
+  furColor: FurColor
+}
+
+union CatOrDog = Dog | Cat
+
+interface Intelligent {
+  iq: Int
+}
+
+type Human implements Being, Intelligent {
+  name(surname: Boolean): String
+  pets: [Pet]
+  relatives: [Human]
+  iq: Int
+}
+
+type Alien implements Being, Intelligent {
+  name(surname: Boolean): String
+  iq: Int
+  numEyes: Int
+}
+
+union DogOrHuman = Dog | Human
+
+union HumanOrAlien = Human | Alien
+
+input ComplexInput {
+  requiredField: Boolean!
+  intField: Int
+  stringField: String
+  booleanField: Boolean
+  stringListField: [String]
+}
+
+type ComplicatedArgs {
+  intArgField(intArg: Int): String
+  nonNullIntArgField(nonNullIntArg: Int!): String
+  stringArgField(stringArg: String): String
+  booleanArgField(booleanArg: Boolean): String
+  enumArgField(enumArg: FurColor): String
+  floatArgField(floatArg: Float): String
+  idArgField(idArg: ID): String
+  stringListArgField(stringListArg: [String]): String
+  complexArgField(complexArg: ComplexInput): String
+  multipleReqs(req1: Int!, req2: Int!): String
+  multipleOpts(opt1: Int, opt2: Int): String
+  multipleOptAndReq(req1: Int!, req2: Int!, opt1: Int, opt2: Int): String
+}
+
+type QueryRoot {
+  human(id: ID): Human
+  alien: Alien
+  dog: Dog
+  cat: Cat
+  pet: Pet
+  catOrDog: CatOrDog
+  dogOrHuman: DogOrHuman
+  humanOrAlien: HumanOrAlien
+  complicatedArgs: ComplicatedArgs
 }"])

 (deftest test-schema-parse


Move docstrings to before argvecs

Move docstrings to before argvecs

--- src-cljs/valent/core.cljs
+++ src-cljs/valent/core.cljs
@@ -7,17 +7,18 @@

 (declare root*)

-(defn by [k v data]
+(defn by
   "Given a collection of maps, returns exactly one map
    where the value at `key` matches `val`."
+  [k v data]

   (first (filter #(= (get % k) v) data)))

 (defn process-map
-  [qry state joins korks root-state]
   "Takes the current state map and selects out the desired
    keys, transforming with further subselectors when specified
   by the query."
+  [qry state joins korks root-state]

   (letfn [(process-kv [m k v]
             (let
@@ -40,9 +41,9 @@
     (reduce-kv process-kv (empty qry) qry)))

 (defn process-vector
-  [qry state joins korks root-state]
   "Takes the current state vector and returns a vector of the
    desired selectored data."
+  [qry state joins korks root-state]

   (let [subqry (first qry)
         korks' (conj korks 0)]


Adds subst

Adds subst

--- src/the_little_clojurian/chapter3.clj
+++ src/the_little_clojurian/chapter3.clj
@@ -67,10 +67,23 @@
   (def insertL
     (fn [new old lat]
       (cond (null? lat) '()
-            (eq? (car lat) old) (conss new (conss old (cdr lat)))
+            (eq? (car lat) old) (conss new lat)
             :else (cons (car lat) (insertL new old (cdr lat))))))

   (is (= (insertL 'topping 'fudge '())
          '()))
   (is (= (insertL 'topping 'fudge '(ice cream with fudge for dessert))
          '(ice cream with topping fudge for dessert))))
+
+(with-test
+  (def subst
+    (fn [new old lat]
+      (cond (null? lat) '()
+            (eq? (car lat) old) (cons new (cdr lat))
+            :else (cons (car lat)
+                        (subst new old (cdr lat))))))
+
+  (is (= (subst 'topping 'fudge '())
+         '()))
+  (is (= (subst 'topping 'fudge '(ice cream with fudge for dessert))
+         '(ice cream with topping for dessert))))


Add impl for delete button on layers toolbox.

--- src/uxbox/ui/workspace/toolboxes.cljs
+++ src/uxbox/ui/workspace/toolboxes.cljs
@@ -157,7 +157,8 @@
         selected (:selected workspace)
         shapes-by-id (rum/react shapes-by-id)
         page (rum/react (focus-page (:page workspace)))
-        close #(rs/emit! (dw/toggle-toolbox :layers))]
+        close #(rs/emit! (dw/toggle-toolbox :layers))
+        delete #(rs/emit! (dw/delete-selected))]
     (html
      [:div#layers.tool-window
       [:div.tool-window-bar
@@ -173,7 +174,8 @@
        [:ul.layers-tools-content
         [:li.clone-layer i/copy]
         [:li.group-layer i/folder]
-        [:li.delete-layer i/trash]
+        [:li.delete-layer {:on-click delete}
+         i/trash]
         ]]])))


[#13047] Profile QR code overlaps share menu during sharing (IOS)

Signed-off-by: andrey <b713972e59b8e606e23253c4a13e948139fea4d1@gmail.com>

--- src/status_im/ui/screens/profile/user/views.cljs
+++ src/status_im/ui/screens/profile/user/views.cljs
@@ -53,7 +53,9 @@
           address]]]
        [react/view styles/share-link-button
         [quo/button
-         {:on-press            #(list-selection/open-share {:message link})
+         {:on-press            #(do
+                                  (re-frame/dispatch [:hide-popover])
+                                  (list-selection/open-share {:message link}))
           :accessibility-label :share-my-contact-code-button}
          (i18n/label :t/share-link)]]])))


Implement more complicated tagged constraint tests

Test tagged constraints with extra leave

Add deallocation tagged constraints

--- test/onyx/scheduler/tagged_constraints_test.clj
+++ test/onyx/scheduler/tagged_constraints_test.clj
@@ -7,6 +7,7 @@
             [com.gfredericks.test.chuck.clojure-test :refer [checking]]
             [onyx.scheduling.common-job-scheduler :refer [reconfigure-cluster-workload]]
             [onyx.log.generators :as log-gen]
+            [onyx.test-helper :refer [job-allocation-counts get-counts]]
             [onyx.log.replica-invariants :refer [standard-invariants]]
             [onyx.static.planning :as planning]
             [onyx.api]))
@@ -164,95 +165,260 @@

 (def onyx-id "tagged-gen-test-id")

-(def job-1-id "job-1")
-
-(def job-1
-  {:workflow [[:a :b] [:b :c]]
-   :catalog [{:onyx/name :a
-              :onyx/plugin :onyx.plugin.core-async/input
-              :onyx/type :input
-              :onyx/medium :core.async
-              :onyx/batch-size 20
-              :onyx/max-peers 1
-              :onyx/required-tags [:special-peer]
-              :onyx/doc "Reads segments from a core.async channel"}
-
-             {:onyx/name :b
-              :onyx/fn :mock/fn
-              :onyx/type :function
-              :onyx/batch-size 20}
-
-             {:onyx/name :c
-              :onyx/plugin :onyx.plugin.core-async/output
-              :onyx/type :output
-              :onyx/max-peers 1
-              :onyx/medium :core.async
-              :onyx/batch-size 20
-              :onyx/doc "Writes segments to a core.async channel"}]
-   :task-scheduler :onyx.task-scheduler/balanced})
-
-(def job-2-id "job-2")
-
-(def job-2
-  {:workflow [[:d :e] [:e :f]]
-   :catalog [{:onyx/name :d
-              :onyx/plugin :onyx.plugin.core-async/input
-              :onyx/type :input
-              :onyx/medium :core.async
-              :onyx/batch-size 20
-              :onyx/max-peers 1
-              :onyx/doc "Reads segments from a core.async channel"}
-
-             {:onyx/name :e
-              :onyx/fn :mock/fn
-              :onyx/type :function
-              :onyx/batch-size 20}
-
-             {:onyx/name :f
-              :onyx/plugin :onyx.plugin.core-async/output
-              :onyx/type :output
-              :onyx/max-peers 1
-              :onyx/medium :core.async
-              :onyx/batch-size 20
-              :onyx/required-tags [:special-peer]
-              :onyx/doc "Writes segments to a core.async channel"}]
-   :task-scheduler :onyx.task-scheduler/balanced})
-
 (def peer-config
   {:onyx/id onyx-id
    :onyx.messaging/impl :dummy-messenger})

+
+(defn name->task-id [catalog job-entry name]
+  (get (zipmap (map :onyx/name catalog)
+               (:tasks (:args job-entry)))
+       name))
+
 (deftest peer-leave-tagged
-  (checking
+  (let [job-1-id "job-1"
+        job-1 {:workflow [[:a :b] [:b :c]]
+               :catalog [{:onyx/name :a
+                          :onyx/plugin :onyx.plugin.core-async/input
+                          :onyx/type :input
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/max-peers 1
+                          :onyx/required-tags [:special-peer]
+                          :onyx/doc "Reads segments from a core.async channel"}
+
+                         {:onyx/name :b
+                          :onyx/fn :mock/fn
+                          :onyx/type :function
+                          :onyx/batch-size 20}
+
+                         {:onyx/name :c
+                          :onyx/plugin :onyx.plugin.core-async/output
+                          :onyx/type :output
+                          :onyx/max-peers 1
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/doc "Writes segments to a core.async channel"}]
+               :task-scheduler :onyx.task-scheduler/balanced}
+        job-2-id "job-2"
+        job-2 {:workflow [[:d :e] [:e :f]]
+               :catalog [{:onyx/name :d
+                          :onyx/plugin :onyx.plugin.core-async/input
+                          :onyx/type :input
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/max-peers 1
+                          :onyx/doc "Reads segments from a core.async channel"}
+
+                         {:onyx/name :e
+                          :onyx/fn :mock/fn
+                          :onyx/type :function
+                          :onyx/batch-size 20}
+
+                         {:onyx/name :f
+                          :onyx/plugin :onyx.plugin.core-async/output
+                          :onyx/type :output
+                          :onyx/max-peers 1
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/required-tags [:special-peer]
+                          :onyx/doc "Writes segments to a core.async channel"}]
+               :task-scheduler :onyx.task-scheduler/balanced}
+        job-entry-1 (onyx.api/create-submit-job-entry
+                      job-1-id
+                      peer-config
+                      job-1
+                      (planning/discover-tasks (:catalog job-1) (:workflow job-1)))
+        job-entry-2 (onyx.api/create-submit-job-entry
+                      job-2-id
+                      peer-config
+                      job-2
+                      (planning/discover-tasks (:catalog job-2) (:workflow job-2)))] (checking
     "Peers leaving keep the job running"
     (times 50)
     [{:keys [replica log entries peer-choices]}
      (log-gen/apply-entries-gen
-      (gen/return
-       {:replica {:job-scheduler :onyx.job-scheduler/balanced
-                  :messaging {:onyx.messaging/impl :dummy-messenger}}
-        :message-id 0
-        :entries
-        (assoc (merge (log-gen/generate-join-queues (log-gen/generate-peer-ids 6))
-                      (log-gen/generate-join-queues (log-gen/generate-peer-ids 7 2) {:tags [:special-peer]}))
-               :job-1 {:queue [(onyx.api/create-submit-job-entry
-                                job-1-id
-                                peer-config
-                                job-1
-                                (planning/discover-tasks (:catalog job-1) (:workflow job-1)))]}
-               :job-2 {:queue [(onyx.api/create-submit-job-entry
-                                job-2-id
-                                peer-config
-                                job-2
-                                (planning/discover-tasks (:catalog job-2) (:workflow job-2)))]}
-               :leave-1 {:queue [{:fn :leave-cluster :args {:id :p1}}]}
-               :leave-2 {:queue [{:fn :leave-cluster :args {:id :p2}}]})
-        :log []
-        :peer-choices []}))]
+       (gen/return
+         {:replica {:job-scheduler :onyx.job-scheduler/balanced
+                    :messaging {:onyx.messaging/impl :dummy-messenger}}
+          :message-id 0
+          :entries
+          (assoc (merge (log-gen/generate-join-queues (log-gen/generate-peer-ids 8))
+                        (log-gen/generate-join-queues (log-gen/generate-peer-ids 9 3) {:tags [:special-peer]}))
+                 :job-1 {:queue [job-entry-1]}
+                 :job-2 {:queue [job-entry-2]}
+                 :leave-1 {:predicate (fn [replica entry]
+                                        (some #{:p1} (:peers replica)))
+                           :queue [{:fn :leave-cluster :args {:id :p1}}]}
+                 :leave-with-tag {:predicate (fn [replica entry]
+                                               (some #{:p11} (:peers replica)))
+                                  :queue [{:fn :leave-cluster :args {:id :p11}}]}
+                 :leave-2 {:predicate (fn [replica entry]
+                                        (some #{:p2} (:peers replica)))
+                           :queue [{:fn :leave-cluster :args {:id :p2}}]})
+          :log []
+          :peer-choices []}))]
     (standard-invariants replica)
-    (let [task-a-id (first (get-in replica [:tasks job-1-id]))
-          task-f-id (last (get-in replica [:tasks job-2-id]))
+    (let [task-a-id (name->task-id (:catalog job-1) job-entry-1 :a)
+          task-f-id (name->task-id (:catalog job-2) job-entry-2 :f)
           task-a-peers (get-in replica [:allocations job-1-id task-a-id])
           task-f-peers (get-in replica [:allocations job-2-id task-f-id])]
-      (is (some (into #{} task-a-peers) #{:p7 :p8}))
-      (is (some (into #{} task-f-peers) #{:p7 :p8})))))
+      (is (= #{[:p9 [:special-peer]] [:p10 [:special-peer]]} (set (remove (comp nil? val) (:peer-tags replica)))))
+      (is (= 8 (count (:peers replica))))
+      (is (= [4 4]
+             (map (comp (partial apply +) vals)
+                  (get-counts replica
+                              [{:job-id job-1-id}
+                               {:job-id job-2-id}]))))
+      (is (some (into #{} task-a-peers) #{:p9 :p10}))
+      (is (some (into #{} task-f-peers) #{:p9 :p10}))))))
+
+#_(deftest peer-leave-tagged-deallocate
+  (let [job-1-id "job-1"
+        job-1 {:workflow [[:a :b] [:b :c]]
+               :catalog [{:onyx/name :a
+                          :onyx/plugin :onyx.plugin.core-async/input
+                          :onyx/type :input
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/max-peers 1
+                          :onyx/required-tags [:special-peer]
+                          :onyx/doc "Reads segments from a core.async channel"}
+
+                         {:onyx/name :b
+                          :onyx/fn :mock/fn
+                          :onyx/type :function
+                          :onyx/batch-size 20}
+
+                         {:onyx/name :c
+                          :onyx/plugin :onyx.plugin.core-async/output
+                          :onyx/type :output
+                          :onyx/max-peers 1
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/doc "Writes segments to a core.async channel"}]
+               :task-scheduler :onyx.task-scheduler/balanced}
+        job-entry-1 (onyx.api/create-submit-job-entry
+                      job-1-id
+                      peer-config
+                      job-1
+                      (planning/discover-tasks (:catalog job-1) (:workflow job-1)))]
+    (checking
+      "Tagged peer leaves, deallocates the job requiring that peer"
+      (times 50)
+      [{:keys [replica log entries peer-choices]}
+       (log-gen/apply-entries-gen
+         (gen/return
+           {:replica {:job-scheduler :onyx.job-scheduler/balanced
+                      :messaging {:onyx.messaging/impl :dummy-messenger}}
+            :message-id 0
+            :entries
+            (assoc (merge (log-gen/generate-join-queues (log-gen/generate-peer-ids 3))
+                          (log-gen/generate-join-queues (log-gen/generate-peer-ids 4 1) {:tags [:special-peer]}))
+                   :job-1 {:queue [job-entry-1]}
+                   :leave-1 {:predicate (fn [replica entry]
+                                          (some #{:p4} (:peers replica)))
+                             :queue [{:fn :leave-cluster :args {:id :p4}}]})
+            :log []
+            :peer-choices []}))]
+      (standard-invariants replica)
+      (is (= #{} (set (remove (comp nil? val) (:peer-tags replica)))))
+        (is (= 3 (count (:peers replica))))
+        (is (= [0]
+               (map (comp (partial apply +) vals)
+                    (get-counts replica
+                                [{:job-id job-1-id}])))))))
+
+(deftest all-tagged-still-balances
+  (let [job-1-id "job-1"
+        job-1 {:workflow [[:a :b] [:b :c]]
+               :catalog [{:onyx/name :a
+                          :onyx/plugin :onyx.plugin.core-async/input
+                          :onyx/type :input
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/required-tags [:special-peer]
+                          :onyx/doc "Reads segments from a core.async channel"}
+
+                         {:onyx/name :b
+                          :onyx/fn :mock/fn
+                          :onyx/type :function
+                          :onyx/batch-size 20}
+
+                         {:onyx/name :c
+                          :onyx/plugin :onyx.plugin.core-async/output
+                          :onyx/type :output
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/doc "Writes segments to a core.async channel"}]
+               :task-scheduler :onyx.task-scheduler/balanced}
+        job-2-id "job-2"
+        job-2 {:workflow [[:d :e] [:e :f]]
+               :catalog [{:onyx/name :d
+                          :onyx/plugin :onyx.plugin.core-async/input
+                          :onyx/type :input
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/doc "Reads segments from a core.async channel"}
+
+                         {:onyx/name :e
+                          :onyx/fn :mock/fn
+                          :onyx/type :function
+                          :onyx/batch-size 20}
+
+                         {:onyx/name :f
+                          :onyx/plugin :onyx.plugin.core-async/output
+                          :onyx/type :output
+                          :onyx/medium :core.async
+                          :onyx/batch-size 20
+                          :onyx/required-tags [:special-peer]
+                          :onyx/doc "Writes segments to a core.async channel"}]
+               :task-scheduler :onyx.task-scheduler/balanced}
+        job-3-id "job-3"
+        job-3 job-2
+        job-entry-1 (onyx.api/create-submit-job-entry
+                      job-1-id
+                      peer-config
+                      job-1
+                      (planning/discover-tasks (:catalog job-1) (:workflow job-1)))
+        job-entry-2 (onyx.api/create-submit-job-entry
+                      job-2-id
+                      peer-config
+                      job-2
+                      (planning/discover-tasks (:catalog job-2) (:workflow job-2)))
+        job-entry-3 (onyx.api/create-submit-job-entry
+                      job-3-id
+                      peer-config
+                      job-3
+                      (planning/discover-tasks (:catalog job-3) (:workflow job-3)))]
+    (checking
+      "More peers than necessary are tagged, job is killed, still has balanced allocation"
+      (times 50)
+      [{:keys [replica log entries peer-choices]}
+       (log-gen/apply-entries-gen
+         (gen/return
+           {:replica {:job-scheduler :onyx.job-scheduler/balanced
+                      :messaging {:onyx.messaging/impl :dummy-messenger}}
+            :message-id 0
+            :entries
+            (assoc (merge (log-gen/generate-join-queues (log-gen/generate-peer-ids 10) {:tags [:special-peer]})
+                          (log-gen/generate-join-queues (log-gen/generate-peer-ids 11 10)))
+                   :job-1 {:queue [job-entry-1]}
+                   :job-2 {:queue [job-entry-2]}
+                   :job-3 {:queue [job-entry-3
+                                   {:fn :kill-job :args {:job job-3-id}}]}
+                   :leave-untagged {:predicate (fn [replica entry]
+                                                 (some #{:p14} (:peers replica)))
+                                    :queue [{:fn :leave-cluster :args {:id :p14}}]}
+                   :leave-tagged {:predicate (fn [replica entry]
+                                               (some #{:p1} (:peers replica)))
+                                  :queue [{:fn :leave-cluster :args {:id :p1}}]})
+            :log []
+            :peer-choices []}))]
+      (standard-invariants replica)
+      (is (= 18 (count (:peers replica))))
+      (is (= [[3 3 3] [3 3 3]]
+             (map vals
+                  (get-counts replica
+                              [{:job-id job-1-id}
+                               {:job-id job-2-id}])))))))


more troubleshooting github actions

more troubleshooting github actions

--- test/mirthsync/fixture_tools.clj
+++ test/mirthsync/fixture_tools.clj
@@ -108,12 +108,13 @@

 (defn start-mirth [mirth]
   (let [mirth-base (mirth-base-dir mirth)
-        mcserver (sh/proc "./mcserver" :dir mirth-base)]
+        mcserver (sh/proc "./mcserver" :dir mirth-base :verbose :very :redirect-err true)]
     (future (sh/stream-to-out mcserver :out))

     ;; wait up to 90 seconds for the server to appear
     (loop [i 0]
-      (println (ps "-axw"))
+      ;; (println (ps "-axw"))
+      (when (= i 0) (prn mcserver))
       (sh/flush mcserver)
       (when-not (or (try
                       (client/head "http://localhost:8080")


Another JS execution test.

Another JS execution test.

--- test/sparkledriver/core_test.clj
+++ test/sparkledriver/core_test.clj
@@ -83,13 +83,19 @@
              "The ceremony of innocence is drowned")))

     (testing "javascript execution"
+      ;; use a script to set an attribute
       (execute-script browser "document.getElementById(\"heroic\")[\"data-villainous\"] = \"frenemy\";")
       (is (= (attr (find-by-id browser "heroic") "data-villainous")
+             "frenemy"))
+      ;; pass an element as an argument to javascript, receive it in return, get an attr from it
+      (is (= (attr (execute-script browser "return arguments[0];", (find-by-id browser "heroic")) "data-villainous")
              "frenemy"))))
   (stop-server))

 ;;(def browser (fetch! (make-browser) (str "http://0.0.0.0:" port)))

+;; (page-source browser)
+
 ;; (with-browser [browser (fetch! (make-browser :screen-size [1900 1000]) (str "http://0.0.0.0:" port))]
 ;;   (println (status-code browser))
 ;;   (println (-> (find-by-tag browser "h2") text))


saving.

saving.

--- docs/src/clj/om_bootstrap/server.clj
+++ docs/src/clj/om_bootstrap/server.clj
@@ -30,3 +30,6 @@
     (reset! server (run-server (handler/api #'app-routes)
                                {:port port}))
     (println "Server started on port [" port "].")))
+
+;; TODO: Check out history.js for supporting the html5 pushstate stuff
+;; on different browsers.


Continue restructuring add-projects

Continue restructuring add-projects

--- frontend/components/add_projects.cljs
+++ frontend/components/add_projects.cljs
@@ -31,18 +31,21 @@
   (let [login (:login org)
         type (if (:org org) :org :user)]
     [:div.organization {:class (when (= {:login login :type type} (get-in settings [:add-projects :selected-org])) "active")}
-     [:div.avatar
-      [:a {:on-click #(put! ch [:selected-add-projects-org {:login login :type type}])}
-       [:img {:src (gh-utils/make-avatar-url org :size 50)
-              :height 50}]]]
-     [:div.other-stuff
-      [:div.orgname
-       [:a {:on-click #(put! ch [:selected-add-projects-org {:login login :type type}])} login]]
-      [:small.github-url.pull-right
-       [:a {:href "http://github.com"}
-        [:i.fa.fa-github-alt ""]]]
-      [:div "12 projects"]
-      [:div "30 members"]]]))
+     [:div.inner
+      [:div.avatar
+       [:a {:on-click #(put! ch [:selected-add-projects-org {:login login :type type}])}
+        [:img {:src (gh-utils/make-avatar-url org :size 50)
+               :height 50}]]]
+      [:div.other-stuff
+       [:div.orgname
+        [:a {:on-click #(put! ch [:selected-add-projects-org {:login login :type type}])} login]]
+       [:small.github-url.pull-right
+        [:a {:href "http://github.com"}
+         [:i.fa.fa-github-alt ""]]]
+       [:div
+        "12 projects"
+        " • "
+        "30 members"]]]]))

 (defn org-sidebar [data owner]
   (reify
@@ -53,8 +56,12 @@
     (render [_]
       (let [user (:user data)
             settings (:settings data)
+            org (inspect (:organizations user))
             controls-ch (om/get-shared owner [:comms :controls])]
         (html [:div
+            [:div.overview
+             [:p
+              "Choose a repo in GitHub from one of your organizations, your own repos, or repos you share with others, and we'll watch it for you. We'll show you the first build immediately, and a new build will be initiated each time someone pushes commits; come back here to follow more projects."]]
                (map (fn [org] (side-item org settings controls-ch))
                     (:organizations user))
                (map (fn [org] (side-item org settings controls-ch))
@@ -229,11 +236,7 @@
             (om/build org-sidebar {:user user
                                    :settings settings})]
            [:div.project-listing
-            [:div.overview
-             [:h3 "Start following your projects"]
-             [:p
-              "Choose a repo in GitHub from one of your organizations, your own repos, or repos you share with others, and we'll watch it for you. We'll show you the first build immediately, and a new build will be initiated each time someone pushes commits; come back here to follow more projects."]]
-
+            [:hr]

             (om/build repo-filter settings)


Adding conversion tests.

Adding conversion tests.

--- test/clojurewerkz/cassaforte/conversion_test.clj
+++ test/clojurewerkz/cassaforte/conversion_test.clj
@@ -39,12 +39,11 @@
          ConsistencyLevel/EACH_QUORUM "each_quorum"
          ConsistencyLevel/ALL "all")))

-
 (deftest test-build-keyspace-definition
   (let [name           "CassaforteTest2"
         strategy-class "org.apache.cassandra.locator.SimpleStrategy"
         strategy-opts  {"replication_factor" "1"}
-        cf-defs        [(build-cfd "keyspace-name" "column-family-name" [(build-cd "name" "UTF8Type")])]
+        cf-defs        [(build-cfd "CassaforteTest2" "column-family-name" [(build-cd "name" "UTF8Type")])]
         ks-def         (build-keyspace-definition name strategy-class cf-defs :strategy-opts strategy-opts)]
     (is (= name (keyspace-def/get-name ks-def)))
     (is (= strategy-class (keyspace-def/get-strategy-class ks-def)))
@@ -74,4 +73,30 @@
     (is (= name (column-family-def/get-name cfdef)))
     ;; Order is guaranteed by Comparator, so that test does have a predictable order
     (is (= "birth_date" (column-def/get-name (first (column-family-def/get-column-metadata cfdef)))))
-    (is (= "full_name" (column-def/get-name (second (column-family-def/get-column-metadata cfdef)))))))+    (is (= "full_name" (column-def/get-name (second (column-family-def/get-column-metadata cfdef)))))))
+
+(deftest t-build-column
+  (let [name      :name
+        value     "John Doe"
+        timestamp (System/currentTimeMillis)
+        column    (build-column clojurewerkz.support.string/to-byte-buffer name value timestamp)
+        c-map     (to-map column)]
+    (are [expected actual] (is (= expected actual))
+         name (:name c-map)
+         value (:value c-map)
+         timestamp (:timestamp c-map))))
+
+(deftest t-build-super-column
+  (let [key          "a0b1c2"
+        column-map   {:age "26" :last_name "P" :first_name "Alex"}
+        timestamp    (System/currentTimeMillis)
+        super-column (build-super-column clojurewerkz.support.string/to-byte-buffer key column-map timestamp)
+        sc-map       (to-map super-column)
+        columns      (:columns sc-map)]
+    (is (= key (:name sc-map)))
+    (is (= :age (:name (first columns))))
+    (is (= "26" (:value (first columns))))
+    (is (= :last_name (:name (second columns))))
+    (is (= "P" (:value (second columns))))
+    (is (= :first_name (:name (nth columns 2))))
+    (is (= "Alex" (:value (nth columns 2))))))


Remove unnecessary, commented tests for node query compiler

These were commented because they test the SQL generated by the
compiler, which is unnecessary and prone to breakage. This is already
tested end-to-end by issuing actual queries.

--- test/com/puppetlabs/puppetdb/test/query/node.clj
+++ test/com/puppetlabs/puppetdb/test/query/node.clj
@@ -72,49 +72,3 @@
         (is (= (retrieve-nodes not-expr)
                (sort not-result))
             (format "%s => %s" not-expr not-result))))))
-
-(comment (deftest compile-term
-  (testing "compiling '=' queries"
-    (testing "should generate fact queries"
-      (doseq [[op path value :as term] [["=" ["fact" "kernel"] "Linux"]
-                                        ["=" ["fact" "uptime_days"] "200"]
-                                        ["=" ["fact" "architecture"] "i386"]]]
-        (is (= (node/compile-term term)
-               [(str "(SELECT DISTINCT certname_facts.certname FROM certname_facts "
-                     "WHERE ((certname_facts.fact = ?) AND (certname_facts.value = ?)))") (last path) value]))))
-
-    (testing "should generate queries for nodes based on activeness"
-      (is (= (node/compile-term ["=" ["node" "active"] true])
-             [(str "(SELECT DISTINCT certnames.name AS certname FROM certnames "
-                   "WHERE (certnames.deactivated IS NULL))")])))
-
-    (testing "should reject any other sort of queries"
-      (doseq [term [["=" "kernel" "Linux"]
-                    ["=" ["node" "name"] "foo"]
-                    ["=" ["facts" "kernel"] "linux"]
-                    ["=" ["foo" "bar"] "baz"]]]
-        (is (thrown-with-msg? IllegalArgumentException #"is not a valid query term"
-              (node/compile-term term))))))
-
-  (testing "joining terms together"
-    (let [term1 ["=" ["fact" "uptime_days"] "200"]
-          term2 ["=" ["fact" "kernel"] "Linux"]
-          [query1 & params1] (node/compile-term term1)
-          [query2 & params2] (node/compile-term term2)]
-
-      (doseq [[op result] {"and" "(SELECT DISTINCT certname FROM %s resources_0 NATURAL JOIN %s resources_1)"
-                           "or" "(%s UNION %s)"
-                           "not" (str "(SELECT DISTINCT lhs.name AS certname FROM certnames lhs "
-                                      "LEFT OUTER JOIN (%s UNION %s) rhs ON lhs.name = rhs.certname "
-                                      "WHERE (rhs.certname IS NULL))")}]
-        (testing (str "should be able to join using " op)
-          (is (= (node/compile-term [op term1 term2])
-                 (apply vector
-                        (format result query1 query2)
-                        (concat params1 params2)))
-              [op term1 term2]))))
-
-    (doseq [op ["and" "or" "not"]]
-      (testing (str "should fail if no terms are specified when using " op)
-        (is (thrown-with-msg? IllegalArgumentException #"requires at least one term"
-              (node/compile-term [op]))))))))


put project-settings sidebar in overview

--- frontend/components/project_settings.cljs
+++ frontend/components/project_settings.cljs
@@ -90,30 +90,61 @@
              :data-success-text "Started..."
              :type "submit"}])])))))

+(defn follow-sidebar [project owner]
+  (reify
+    om/IRender
+    (render [_]
+      (let [project-id (project-model/id project)
+            vcs-url (:vcs_url project)
+            controls-ch (om/get-shared owner [:comms :controls])]
+        (html
+          [:article
+           [:div.project-setting-watch {:class (when-not (:followed project) "unwatched")}
+            (if (:followed project)
+              (list
+               [:h2 "You're following " (vcs-url/project-name vcs-url)]
+               [:p
+                "We'll keep an eye on this and update you with personalized build emails. "
+                "You can stop these any time from your "
+                [:a {:href "/account"} "account settings"]
+                "."]
+               (forms/stateful-button
+                [:button {:on-click #(put! controls-ch [:unfollowed-project {:vcs-url vcs-url
+                                                                             :project-id project-id}])
+                          :data-loading-text "Unfollowing..."}
+                 "Unfollow"]))
+              (list
+               [:h2 "You're not following this repo"]
+               [:p
+                "We can't update you with personalized build emails unless you follow this project. "
+                "Projects are only tested if they have a follower."]
+               (forms/stateful-button
+                [:button {:on-click #(put! controls-ch [:followed-project {:vcs-url vcs-url
+                                                                           :project-id project-id}])
+                          :data-loading-text "Following..."}
+                 "Follow"])))]])))))
+
 (defn overview [project-data owner]
   (reify
     om/IRender
     (render [_]
       (html
-       [:div.project-settings-block
-        [:h2 "How to configure " (vcs-url/project-name (get-in project-data [:project :vcs_url]))]
-        [:ul.overview-options
-         [:li.overview-item
-          [:h4 "Option 1"]
-          [:p
-           "Do nothing! Circle infers many settings automatically. Works great for Ruby, Python, NodeJS, Java and Clojure. However, if it needs tweaks or doesn't work, see below."]]
-         [:li.overview-item
-          [:h4 "Option 2"]
-          [:p
-           "Override inferred settings and add new test commands "
-           [:a {:href "#setup"} "through the web UI"]
-           ". This works great for prototyping changes."]]
-         [:li.overview-item
-          [:h4 "Option 3"]
-          [:p
-           "Override all settings via a "
-           [:a {:href "/docs/configuration"} "circle.yml file"]
-           " in your repo. Very powerful."]]]]))))
+       [:section
+        (om/build follow-sidebar (:project project-data))
+        [:article
+         [:h2 "How to Configure Project"]
+         [:h4 "Option 1"]
+         [:p "Do nothing! Circle infers many settings automatically. Works great for Ruby, Python, NodeJS, Java and Clojure. However, if it needs tweaks or doesn't work, see below."]
+         [:h4 "Option 2"]
+         [:p
+          "Override inferred settings and add new test commands "
+          [:a {:href "#setup"} "through the web UI"]
+          ". This works great for prototyping changes."]
+         [:h4 "Option 3"]
+         [:p
+          "Override all settings via a "
+          [:a {:href "/docs/configuration"} "circle.yml file"]
+          " in your repo. Very powerful."]]]))))

 (defn mini-parallelism-faq [project-data]
   [:div.mini-faq
@@ -1144,44 +1175,6 @@
                                            (put! controls-ch [:saved-project-settings {:project-id project-id}])
                                            false)}]))]]]])))))

-(defn follow-sidebar [project owner]
-  (reify
-    om/IRender
-    (render [_]
-      (let [project-id (project-model/id project)
-            vcs-url (:vcs_url project)
-            controls-ch (om/get-shared owner [:comms :controls])]
-        (html
-         [:div.follow-status
-          [:div.followed
-           ;; this is weird, but it's what the css expectss
-           (when (:followed project)
-             (list
-              [:i.fa.fa-group]
-              [:h4 "You're following this repo"]
-              [:p
-               "We'll keep an eye on this and update you with personalized build emails. "
-               "You can stop these any time from your "
-               [:a {:href "/account"} "account settings"]
-               "."]
-              (forms/stateful-button
-               [:button {:on-click #(put! controls-ch [:unfollowed-project {:vcs-url vcs-url
-                                                                            :project-id project-id}])
-                         :data-loading-text "Unfollowing..."}
-                "Unfollow"])))]
-          [:div.not-followed
-           (when-not (:followed project)
-             (list
-              [:h4 "You're not following this repo"]
-              [:p
-               "We can't update you with personalized build emails unless you follow this project. "
-               "Projects are only tested if they have a follower."]
-              (forms/stateful-button
-               [:button {:on-click #(put! controls-ch [:followed-project {:vcs-url vcs-url
-                                                                          :project-id project-id}])
-                         :data-loading-text "Following..."}
-                "Follow"])))]])))))
-
 (defn project-settings [data owner]
   (reify
     om/IRender


More fixes to reakit

More fixes to reakit

--- workspaces/src/com/wsscode/fulcro/ui/reakit.cljs
+++ workspaces/src/com/wsscode/fulcro/ui/reakit.cljs
@@ -24,10 +24,10 @@
 (def group-item (uc/wrap-react-component-localized rk/Group.Item))
 (def heading (uc/wrap-react-component-localized rk/Heading))
 (def hidden (uc/wrap-react-component-localized rk/Hidden))
-(def hidden-container (uc/wrap-react-component-localized rk/HiddenContainer))
-(def hidden-hide (uc/wrap-react-component-localized rk/HiddenHide))
-(def hidden-show (uc/wrap-react-component-localized rk/HiddenShow))
-(def hidden-toggle (uc/wrap-react-component-localized rk/HiddenToggle))
+(def hidden-container (uc/wrap-react-component-localized rk/Hidden.Container))
+(def hidden-hide (uc/wrap-react-component-localized rk/Hidden.Hide))
+(def hidden-show (uc/wrap-react-component-localized rk/Hidden.Show))
+(def hidden-toggle (uc/wrap-react-component-localized rk/Hidden.Toggle))
 (def image (uc/wrap-react-component-localized rk/Image))
 (def inline (uc/wrap-react-component-localized rk/Inline))
 (def inline-block (uc/wrap-react-component-localized rk/InlineBlock))
@@ -36,34 +36,34 @@
 (def label (uc/wrap-react-component-localized rk/Label))
 (def link (uc/wrap-react-component-localized rk/Link))
 (def list (uc/wrap-react-component-localized rk/List))
-(def list-item (uc/wrap-react-component-localized rk/ListItem))
+(def list-item (uc/wrap-react-component-localized rk/List.Item))
 (def navigation (uc/wrap-react-component-localized rk/Navigation))
 (def overlay (uc/wrap-react-component-localized rk/Overlay))
-(def overlay-container (uc/wrap-react-component-localized rk/OverlayContainer))
-(def overlay-hide (uc/wrap-react-component-localized rk/OverlayHide))
-(def overlay-show (uc/wrap-react-component-localized rk/OverlayShow))
-(def overlay-toggle (uc/wrap-react-component-localized rk/OverlayToggle))
+(def overlay-container (uc/wrap-react-component-localized rk/Overlay.Container))
+(def overlay-hide (uc/wrap-react-component-localized rk/Overlay.Hide))
+(def overlay-show (uc/wrap-react-component-localized rk/Overlay.Show))
+(def overlay-toggle (uc/wrap-react-component-localized rk/Overlay.Toggle))
 (def paragraph (uc/wrap-react-component-localized rk/Paragraph))
 (def perpendicular (uc/wrap-react-component-localized rk/Perpendicular))
 (def popover (uc/wrap-react-component-localized rk/Popover))
-(def popover-arrow (uc/wrap-react-component-localized rk/PopoverArrow))
-(def popover-container (uc/wrap-react-component-localized rk/PopoverContainer))
-(def popover-hide (uc/wrap-react-component-localized rk/PopoverHide))
-(def popover-show (uc/wrap-react-component-localized rk/PopoverShow))
-(def popover-toggle (uc/wrap-react-component-localized rk/PopoverToggle))
+(def popover-arrow (uc/wrap-react-component-localized rk/Popover.Arrow))
+(def popover-container (uc/wrap-react-component-localized rk/Popover.Container))
+(def popover-hide (uc/wrap-react-component-localized rk/Popover.Hide))
+(def popover-show (uc/wrap-react-component-localized rk/Popover.Show))
+(def popover-toggle (uc/wrap-react-component-localized rk/Popover.Toggle))
 (def shadow (uc/wrap-react-component-localized rk/Shadow))
 (def sidebar (uc/wrap-react-component-localized rk/Sidebar))
-(def sidebar-container (uc/wrap-react-component-localized rk/SidebarContainer))
-(def sidebar-hide (uc/wrap-react-component-localized rk/SidebarHide))
-(def sidebar-show (uc/wrap-react-component-localized rk/SidebarShow))
-(def sidebar-toggle (uc/wrap-react-component-localized rk/SidebarToggle))
+(def sidebar-container (uc/wrap-react-component-localized rk/Sidebar.Container))
+(def sidebar-hide (uc/wrap-react-component-localized rk/Sidebar.Hide))
+(def sidebar-show (uc/wrap-react-component-localized rk/Sidebar.Show))
+(def sidebar-toggle (uc/wrap-react-component-localized rk/Sidebar.Toggle))
 (def step (uc/wrap-react-component-localized rk/Step))
-(def step-container (uc/wrap-react-component-localized rk/StepContainer))
-(def step-hide (uc/wrap-react-component-localized rk/StepHide))
-(def step-next (uc/wrap-react-component-localized rk/StepNext))
-(def step-previous (uc/wrap-react-component-localized rk/StepPrevious))
-(def step-show (uc/wrap-react-component-localized rk/StepShow))
-(def step-toggle (uc/wrap-react-component-localized rk/StepToggle))
+(def step-container (uc/wrap-react-component-localized rk/Step.Container))
+(def step-hide (uc/wrap-react-component-localized rk/Step.Hide))
+(def step-next (uc/wrap-react-component-localized rk/Step.Next))
+(def step-previous (uc/wrap-react-component-localized rk/Step.Previous))
+(def step-show (uc/wrap-react-component-localized rk/Step.Show))
+(def step-toggle (uc/wrap-react-component-localized rk/Step.Toggle))
 (def table (uc/wrap-react-component-localized rk/Table))
 (def table-body (uc/wrap-react-component-localized rk/Table.Body))
 (def table-caption (uc/wrap-react-component-localized rk/Table.Caption))
@@ -74,9 +74,10 @@
 (def table-head (uc/wrap-react-component-localized rk/Table.Head))
 (def table-row (uc/wrap-react-component-localized rk/Table.Row))
 (def tabs (uc/wrap-react-component-localized rk/Tabs))
-(def tabs-container (uc/wrap-react-component-localized rk/TabsContainer))
-(def tabs-next (uc/wrap-react-component-localized rk/TabsNext))
-(def tabs-panel (uc/wrap-react-component-localized rk/TabsPanel))
-(def tabs-previous (uc/wrap-react-component-localized rk/TabsPrevious))
-(def tabs-tab (uc/wrap-react-component-localized rk/TabsTab))
+(def tabs-container (uc/wrap-react-component-localized rk/Tabs.Container))
+(def tabs-next (uc/wrap-react-component-localized rk/Tabs.Next))
+(def tabs-panel (uc/wrap-react-component-localized rk/Tabs.Panel))
+(def tabs-previous (uc/wrap-react-component-localized rk/Tabs.Previous))
+(def tabs-tab (uc/wrap-react-component-localized rk/Tabs.Tab))
 (def tooltip (uc/wrap-react-component-localized rk/Tooltip))
+(def tooltip-arrow (uc/wrap-react-component-localized rk/Tooltip.Arrow))


Added tests for key-str.

Added tests for key-str.

--- test/test/appengine_magic/services/datastore.clj
+++ test/test/appengine_magic/services/datastore.clj
@@ -1,7 +1,8 @@
 (ns test.appengine-magic.services.datastore
   (:use clojure.test)
   (:require [appengine-magic.services.datastore :as ds]
-            [appengine-magic.testing :as ae-testing]))
+            [appengine-magic.testing :as ae-testing])
+  (:import com.google.appengine.api.datastore.KeyFactory))

 (use-fixtures :each (ae-testing/local-services :all))
@@ -10,6 +11,7 @@
 (ds/defentity Author [^:key name])
 (ds/defentity Article [^:key title author body comment-count])
 (ds/defentity Comment [^:key subject article author body])
+(ds/defentity Note [author body])

 (deftest basics
@@ -54,3 +56,20 @@
           (is (= comment-2 (ds/save! comment-2))))))
     (let [article (ds/retrieve Article "Article 1")]
       (is (= 2 (:comment-count article))))))
+
+
+(deftest key-strings
+  (is (= "Note(1)" (ds/key-str "Note" "1")))
+  (is (= "Note(1)" (ds/key-str "Note" 1)))
+  (is (= "Note(1)" (ds/key-str Note "1")))
+  (is (= "Note(1)" (ds/key-str Note 1)))
+  (is (= "Note(3)" (str (KeyFactory/createKey "Note" (long 3)))))
+  (is (thrown? IllegalArgumentException (ds/key-str (Note. 1 2))))
+  (let [alice (ds/save! (Author. "Alice"))
+        note-1 (ds/save! (Note. alice "Note 1."))
+        note-2 (ds/save! (Note. alice "Note 2."))]
+    (is (= "Author(\"Alice\")" (ds/key-str alice)))
+    (is (= (str (ds/get-key-object note-1)) (ds/key-str note-1)))
+    (is (= (str (ds/get-key-object note-2)) (ds/key-str note-2)))
+    (is (= (ds/key-str (KeyFactory/keyToString (ds/get-key-object note-2)))
+           (ds/key-str note-2)))))


Fix ns.

Fix ns.

--- test/onyx/hornetq/standalone_test.clj
+++ test/onyx/hornetq/standalone_test.clj
@@ -1,4 +1,4 @@
-(ns onyx.peer.single-peer-test
+(ns onyx.hornetq.standalone-test
   (:require [midje.sweet :refer :all]
             [onyx.queue.hornetq-utils :as hq-util]
             [onyx.api]))
@@ -49,7 +49,7 @@
     :onyx/batch-size batch-size}

    {:onyx/name :inc
-    :onyx/fn :onyx.peer.single-peer-test/my-inc
+    :onyx/fn :onyx.hornetq.standalone-test/my-inc
     :onyx/type :transformer
     :onyx/consumption :concurrent
     :onyx/batch-size batch-size}


diagonal-line? - next win condition

diagonal-line? - next win condition

--- test/tic_tac_toe/tic_tac_toe_test.clj
+++ test/tic_tac_toe/tic_tac_toe_test.clj
@@ -14,9 +14,10 @@

 (def win (repeat 3 (repeat 3 \x)))

-(def horizontal-win [[\o \o \o]
-                     [nil nil nil]
-                     [nil nil nil]])
+(def horizontal-win
+  [[\o \o \o]
+   [nil nil nil]
+   [nil nil nil]])
 (def horizontal-win-second
   [[nil nil nil]
    [\o \o \o]
@@ -39,7 +40,14 @@
    [nil nil \o]
    [nil nil \o]])

-
+(def diagonal-win
+  [[\o nil nil]
+   [nil \o nil]
+   [nil nil \o]])
+(def diagonal-win-second
+  [[nil nil \o]
+   [nil \o nil]
+   [\o nil nil]])

 (deftest tic-tac-toe-test

@@ -75,6 +83,9 @@
     (is (true? (vertical-line? vertical-win-second)))
     (is (true? (vertical-line? vertical-win-third)))

+    (is (true? (diagonal-line? diagonal-win)))
+    (is (true? (diagonal-line? diagonal-win-second)))
+
     (is (false? (player-win?)))
     (is (true? (player-win? horizontal-win))))
 )


allow wall moves

allow wall moves

--- src/quoridor/core.clj
+++ src/quoridor/core.clj
@@ -137,6 +137,11 @@
                 next-player (first next)]
             (cond
               (= move "q") (println "Thanks for playing!")
+              (allowed-wall-move? state move) (recur next-player
+                                                     (rest next)
+                                                     (-> state
+                                                         (assoc :walls (conj (state :walls) move))
+                                                         (assoc :current next-player)))
               (allowed-pawn-move? state move) (recur next-player
                                                      (rest next)
                                                      (-> state


use the new tool icons for shared mice

use the new tool icons for shared mice

--- src-cljs/frontend/components/canvas.cljs
+++ src-cljs/frontend/components/canvas.cljs
@@ -98,17 +98,28 @@
         (apply dom/g #js {:className "layers"}
                (mapv (partial svg-element selected-eids) layers))))))

+(defn subscriber-cursor-icon [tool]
+  (case (name tool)
+    "pen" :crosshair
+    "line" :crosshair
+    "rect" :crosshair
+    "circle" :crosshair
+
+    "text" :ibeam
+
+    "select" :tool-select))
+
 (defn cursor [[id subscriber] owner]
   (reify
     om/IRender
     (render [_]
       (if (and (:tool subscriber)
                (:show-mouse? subscriber))
-        (html (common/svg-icon (keyword (str "tool-" (name (:tool subscriber))))
+        (html (common/svg-icon (utils/inspect (subscriber-cursor-icon (:tool subscriber)))
                                {:svg-props {:height 16 :width 16
                                             :class "mouse-tool"
-                                            :x (first (:mouse-position subscriber))
-                                            :y (last (:mouse-position subscriber))}
+                                            :x (- (first (:mouse-position subscriber)) 8)
+                                            :y (- (last (:mouse-position subscriber)) 8)}
                                 :path-props {:stroke (:color subscriber)}}))
         (dom/circle #js {:cx 0 :cy 0 :r 0})))))


remove old iconpiler function

remove old iconpiler function

--- src-cljs/frontend/components/common.cljs
+++ src-cljs/frontend/components/common.cljs
@@ -74,15 +74,6 @@
    :repo {:paths [:repo]}
    :spinner {:paths [:turn :circle]}})

-; (defn icon [icon-name]
-;   (let [template (get icon-templates icon-name)]
-;     [:i {:class (str "icon-" (name icon-name))}
-;       [:svg {:viewBox "0 0 100 100"
-;              :dangerouslySetInnerHTML
-;              #js {"__html" (apply str
-;                                   (for [path (:paths template)]
-;                                     (str "<path class='" (name path) "' fill='none' d='" (get icon-paths path) "'></path>")))}}]]))
-
 (defn icon [icon-name]
   (let [template (get icon-templates icon-name)]
     [:i {:class (str "icon-" (name icon-name))}


Add link to bot documentation

Add link to bot documentation

--- src/braid/core/client/bots/views/bots_page.cljs
+++ src/braid/core/client/bots/views/bots_page.cljs
@@ -130,6 +130,9 @@
       (when @admin?
         [:div.add-bot
          [:h2 "Add a New Bot"]
+         [:p "For information on creating bots, see "
+          [:a {:href "https://github.com/braidchat/braid/blob/master/docs/dev/how-to/developing-bots.md"}
+           "the documentation"] "."]
          (case @state

            :creating


Send token

Send token

--- src/cider_ci/dispatcher/dispatch/build_data.clj
+++ src/cider_ci/dispatcher/dispatch/build_data.clj
@@ -77,27 +77,26 @@
                                      :CIDER_CI_TASK_ID (:task_id trial)
                                      :CIDER_CI_TRIAL_ID trial-id
                                      :CIDER_CI_TREE_ID (:tree_id branch-and-commit)})]
-    {
-     :environment-variables environment-variables
-     :git-options (or (:git-options task-spec) {})
-     :git_branch_name (:name branch-and-commit)
-     :git_commit_id commit-id
-     :git_tree_id (:tree_id branch-and-commit)
-     :git_url (git-url repository-id)
-     :git-proxies {}
-     :job_id job-id
-     :patch_path (patch-path executor trial-id)
-     :ports (:ports task-spec)
-     :repository_id repository-id
-     :scripts (get-scripts trial)
-     :task_id (:task_id trial)
-     :templates (templates-data task-spec)
-     :tree-attachments (:tree-attachments task-spec)
-     :tree-attachments-path (tree-attachments-path tree-id)
-     :trial-attachments (:trial-attachments task-spec)
-     :trial-attachments-path (trial-attachments-path trial-id)
-     :trial_id trial-id
-     }))
+    (merge (select-keys trial [:token :task_id])
+           {:environment-variables environment-variables
+            :git-options (or (:git-options task-spec) {})
+            :git_branch_name (:name branch-and-commit)
+            :git_commit_id commit-id
+            :git_tree_id (:tree_id branch-and-commit)
+            :git_url (git-url repository-id)
+            :git-proxies {}
+            :job_id job-id
+            :patch_path (patch-path executor trial-id)
+            :ports (:ports task-spec)
+            :repository_id repository-id
+            :scripts (get-scripts trial)
+            :templates (templates-data task-spec)
+            :tree-attachments (:tree-attachments task-spec)
+            :tree-attachments-path (tree-attachments-path tree-id)
+            :trial-attachments (:trial-attachments task-spec)
+            :trial-attachments-path (trial-attachments-path trial-id)
+            :trial_id trial-id
+            })))

 ;#### debug ###################################################################


For downloading a programme open gnome-terminal.

--- src/beebster_clj/core.clj
+++ src/beebster_clj/core.clj
@@ -14,14 +14,11 @@
 (def iplayer-command
   '("get_iplayer" "--nocopyright" "--limitmatches" "50" "--listformat" "<index> <pid> <thumbnail> <name> <episode>"))

-
-
 (def iplayer-info
   '("get_iplayer" "-i"))

 (def delete-string
   "These programmes should be deleted:")
-

 (defn get-info
   "get-iplayer info for entered index"
@@ -74,8 +71,9 @@
 (defn iplayer-download-command
   "concatenate index and mode to download command"
    [index mode]
-   (list "get-iplayer" (apply str "modes=" mode "1\"")
-         "output=\"$HOME/Videos\"" "-g" index))
+   (list "gnome-terminal" "-e" (apply str "get-iplayer" " --modes=" mode "1"
+                                       " output=$HOME/Videos/" " -g " index)))
+

 (defn get-url
   "return /info url string concatenated with index"


Make image url encoding optional

Make image url encoding optional

--- src/hatti/views/photos.cljs
+++ src/hatti/views/photos.cljs
@@ -33,18 +33,20 @@
 (defn- make-url
   "If not a fully qualified URL, remove the API namespace prefix from a URI
    string and convert to a fully qualified URL."
-  [url]
+  [url & [encode-url?]]
   (let [string-vec (split url #"\?")
         index 1
         encoded-question-mark "%3F"
-        encoded-url
-        (join encoded-question-mark
-              (assoc string-vec
-                     index
-                     (js/encodeURIComponent (nth string-vec index))))]
-    (if (= (subs encoded-url 0 4) "http")
-      encoded-url
-      (remote/make-url (replace encoded-url #"/api/v1/" "")))))
+        image-url
+        (if encode-url?
+          (join encoded-question-mark
+                (assoc string-vec
+                       index
+                       (js/encodeURIComponent (nth string-vec index))))
+          url)]
+    (if (= (subs image-url 0 4) "http")
+      image-url
+      (remote/make-url (replace image-url #"/api/v1/" "")))))

 (defn- build-caption
   [item]
@@ -150,11 +152,11 @@
                  rank (get datum constants/_rank)]]
        (map-indexed
         (fn [j attachment]
-          (let [download-url (make-url attachment)
+          (let [download-url (make-url attachment true)
                 thumbnail (resize-image download-url
                                         thumb-width-px)]
             {:src (resize-image download-url width-px)
-             :original-src download-url
+             :original-src (make-url attachment)
              :msrc thumbnail
              :thumb thumbnail
              :title (format "%s/%s | ID: %s" (+ 1 cumulative-sum j) total id)


Comment out deliberate error in todomvc

Comment out deliberate error in todomvc

--- examples/todomvc/src/todomvc/db.cljs
+++ examples/todomvc/src/todomvc/db.cljs
@@ -17,7 +17,7 @@
 (def schema
   {:todos   (s/both (s/pred map?) (s/pred sorted?))
    :showing (s/enum :all :done :active)
-   :mistake (s/enum :one :two)   ;; add this bogus schema item in, then watch the console
+   ;; :mistake (s/enum :one :two)   ;; add this bogus schema item, then watch the errors in the console
    })


delete trash file

delete trash file


Add explanation of logging setup.

Add explanation of logging setup.

--- src/afterglow/examples.clj
+++ src/afterglow/examples.clj
@@ -16,6 +16,8 @@
 ;; Make sure the experimenter does not get blasted with a ton of debug messages
 (timbre/set-level! :info)

+;; Provide a nice, organized set of log files to help hunt down problems, especially
+;; for exceptions which occur on background threads.
 (timbre/set-config!
  [:appenders :rotor]
  {:min-level :info


Use the new pricing page for everything except piggieback plans.

--- frontend/models/plan.cljs
+++ frontend/models/plan.cljs
@@ -44,8 +44,9 @@
   (boolean (:paid plan)))

 (defn can-edit-plan? [plan org-name]
-  (or (freemium? plan)
-      (and (paid? plan) (not (piggieback? plan org-name)))))
+  ;; kill plan pricing page for trial plans by making
+  ;; can-edit-plan?' return true for them
+  (not (piggieback? plan org-name)))

 (defn trial? [plan]
   (boolean (:trial plan)))


Updated repository root path in the sample blog pipeline.

--- lambda-blog/test/lambda_blog/fixtures.clj
+++ lambda-blog/test/lambda_blog/fixtures.clj
@@ -83,8 +83,8 @@
                          "style/highlight.default.css"
                          "style/lambda-blog.css"]})

-(defn- read-git-tags []
-  (gitp/with-repo "."
+(defn- read-git-tags [path]
+  (gitp/with-repo path
     (map (fn [tag]
            (let [t (->> tag
                         .getValue
@@ -118,7 +118,7 @@
                   (add-paths "<title>.html"))
       (read-dir :entries "doc/entries" parse)
       (update :entries
-              #(concat % (read-git-tags)))
+              #(concat % (read-git-tags "..")))
       (update-all :entries
                   (promote :metadata)
                   (add-paths "entries/<title>.html")


make blank starts more pleasant

make blank starts more pleasant

--- sidecar/src/figwheel_sidecar/schemas/config.clj
+++ sidecar/src/figwheel_sidecar/schemas/config.clj
@@ -754,8 +754,13 @@
    :req-un [:cljsbuild.lein-project/cljsbuild]))

 (defn must-have-one-opt-none-build [with-builds]
-  (if (or (map? (:builds with-builds))
-          (vector? (:builds with-builds)))
+  (if (and (or (map? (:builds with-builds))
+               (vector? (:builds with-builds)))
+           (pos? (count (:builds with-builds)))
+           (every? (if (map? (:builds with-builds))
+                     #{:compiler :source-paths}
+                     #{:compiler :source-paths :id})
+                   (:builds with-builds)))
     (let [v (:builds with-builds)]
       (let [blds (if (map? v) (vals v) v)]
         (some opt-none-build blds)))


make link on the dashboard work

make link on the dashboard work

--- src/client/dashboard.cljs
+++ src/client/dashboard.cljs
@@ -160,7 +160,7 @@
   [:div.wrapper-2ba66
     [:div.hdr-93a4f
       [:img.logo-dd80d {:src "/img/t3tr0s_logo_200w.png" :alt "T3TR0S Logo"}]
-      [:div.game-6dc02 "Game"]
+      [:div#battleGameLink.game-6dc02 "Game"]
       [:div.dashboard-3a58e "Dashboard"]]
     ;; NOTE: this button is for testing purposes
     [:button#shuffleBtn {:style "padding: 12px 24px; display: none"} "Shuffle!"]
@@ -329,6 +329,17 @@
   (reset! page-state (shuffle test-state)))

 ;;------------------------------------------------------------------------------
+;; DOM Events
+;;------------------------------------------------------------------------------
+
+(defn- click-battle-link []
+  (aset js/window "location" "hash" "#/battle-game"))
+
+(defn- add-events []
+  (.on ($ "#shuffleBtn") "click" shuffle-page-state)
+  (.on ($ "#battleGameLink") "click" click-battle-link))
+
+;;------------------------------------------------------------------------------
 ;; Page Initialization / Cleanup
 ;;------------------------------------------------------------------------------

@@ -339,10 +350,11 @@
 (defn init []
   (dom/set-bw-background!)
   (dom/set-page-body! (page-shell))
+  (add-events)
+
   (swap! page-state identity)

   ;; NOTE: for debugging
-  ; (.click ($ "#shuffleBtn") shuffle-page-state)
   ; (shuffle-page-state)
   ; (js/setInterval shuffle-page-state 2000)


add/edit goals on server

add/edit goals on server

--- src/clj/tictag/server.clj
+++ src/clj/tictag/server.clj
@@ -244,6 +244,14 @@
       (catch Exception e {:status 401 :body "unauthorized"}))
     {:status 401 :body "unauthorized"}))

+(defn add-goal [{:keys [db]} {:keys [params user-id]}]
+  (db/add-goal db user-id params))
+
+(defn update-goal [{:keys [db]} {:keys [params user-id]}]
+  (when-let [int-id (try (Integer. (:id params))
+                         (catch Exception _ nil))]
+    (db/update-goal db user-id (assoc params :id int-id))))
+
 (defn routes [component]
   (compojure.core/routes
    (GET "/slack-callback" _ (partial slack-callback component))
@@ -262,7 +270,9 @@
             (GET "/user/me" _ (partial my-user component))
             (POST "/user/me/beeminder" _ (partial add-beeminder component))
             (DELETE "/user/me/beeminder" _ (partial delete-beeminder component))
-            (DELETE "/user/me/slack" _ (partial delete-slack component)))
+            (DELETE "/user/me/slack" _ (partial delete-slack component))
+            (POST "/user/me/goals/" _ (partial add-goal component))
+            (PUT "/user/me/goals/:id" _ (partial update-goal component)))
    (POST "/signup" _ (partial signup component))
    (GET "/healthcheck" _ (health-check component))))


Use strict hostname verification for SSL certificates

Relates to #298

--- src/clj_http/conn_mgr.clj
+++ src/clj_http/conn_mgr.clj
@@ -50,6 +50,10 @@
                        (^boolean verify [_ ^String _ ^SSLSession _]
                         true))))

+(def ^SSLSocketFactory secure-ssl-socket-factory
+  (doto (SSLSocketFactory/getSocketFactory)
+    (.setHostnameVerifier SSLSocketFactory/STRICT_HOSTNAME_VERIFIER)))
+
 ;; New Generic Socket Factories that can support socks proxy
 (defn ^SSLSocketFactory SSLGenericSocketFactory
   "Given a function that returns a new socket, create an SSLSocketFactory that
@@ -94,7 +98,7 @@
 (def regular-scheme-registry
   (doto (SchemeRegistry.)
     (.register (Scheme. "http" 80 (PlainSocketFactory/getSocketFactory)))
-    (.register (Scheme. "https" 443 (SSLSocketFactory/getSocketFactory)))))
+    (.register (Scheme. "https" 443 secure-ssl-socket-factory))))

 (defn ^KeyStore get-keystore*
   [keystore-file keystore-type ^String keystore-pass]


Switch application order in move so that we don't overwrite when clicking on the same square twice

--- src/cljs/chess/board.cljs
+++ src/cljs/chess/board.cljs
@@ -133,8 +133,8 @@
   [board from-sq to-sq]
   (if-let [p (in board from-sq)]
     (-> board
-        (put to-sq p)
-        (put from-sq empty-sq))
+        (put from-sq empty-sq)
+        (put to-sq p))
     board))

 (def start-position


Add long docstring

Add long docstring

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -784,7 +784,28 @@
   "Organizes all of the Nodes and Segments in a FlatGraph into horizontally-
   aligned blocks. These blocks are then organized into a graph of their own,
   where the nodes are blocks and the edges are determined by adjacency
-  between their constituent Nodes and Segments in each FlatLayer"
+  between their constituent Nodes and Segments in each FlatLayer.
+
+  This approach is very heavily based on Fast and Simple Horizontal Coordinate
+  Assignment by Ulrik Brandes and Boris Köpf (BK), even though the algorithm
+  is pretty much entirely dissimilar. I've taken BK's basic idea (which is to
+  align nodes into 'blocks' group these blocks into 'classes' and then
+  recursively position each class and block on the x axis), discarded the
+  algorithm they provided, and made my own. Their algorithm operated on blocks
+  and classes as sort of emergent properties from relationships between nodes,
+  whereas mine explicity constructs blocks and classes and organizes each into
+  graphs, which are then used for positioning. I just found my approach easier
+  to reason about.
+
+  It is also important to note that BK (and pretty much all of the academic
+  literature, for that matter), is concerned with drawing graphs vertically,
+  while we are drawing them horizontally. The practical result of this is that
+  our graphs are reflected across the upper-left-to-lower-right diagonal as
+  compared to the graphs in BK, and as a result we sometimes do things in the
+  opposite manner. The most obvious example is that while BK-style classes are
+  defined by their sinks in a block graph, ours are defined by sources in the
+  block graph. If you flip the graph though, you'll see that we're working from
+  the same block and getting the same result."
   [flat-graph]
   (let [[roots blocks] (blockify flat-graph)]
     (loop [bs blocks


Whitespace.

Whitespace.

--- src/clojurecraft/core.clj
+++ src/clojurecraft/core.clj
@@ -12,9 +12,9 @@
 ; Connection Wrappers --------------------------------------------------------------
 (defn connect [server]
   (let [socket (Socket. (:name server) (:port server))
-               in (DataInputStream. (.getInputStream socket))
-               out (DataOutputStream. (.getOutputStream socket))
-               conn (ref {:in in :out out})]
+        in (DataInputStream. (.getInputStream socket))
+        out (DataOutputStream. (.getOutputStream socket))
+        conn (ref {:in in :out out})]
     (doto (Thread. #(conn-handler conn)) (.start))
     conn))


Fixed create-system.

Fixed create-system.

--- src/cmr/ingest/system.clj
+++ src/cmr/ingest/system.clj
@@ -19,15 +19,15 @@

 (defn create-system
   "Returns a new instance of the whole application."
-  [log config web]
+  ([log config web]
   {:log log
    :config config
-   :web web}
-  []
+   :web web})
+  ([]
   {:log (log/create-logger)
    :config default-config
    :web (web/create-web-server 3002 routes/make-api)
-   :zipkin (context/zipkin-config "Ingest" false)})
+   :zipkin (context/zipkin-config "Ingest" false)}))

    (defn start
      "Performs side effects to initialize the system, acquire resources,


fix keyword and string concatenation typos

--- src/babel/francais/morphology/verbs.cljc
+++ src/babel/francais/morphology/verbs.cljc
@@ -967,39 +967,93 @@
    {:path [:français :future-stem]
     :merge-fn
     (fn [val]
-      {:français {:infl :future
-                  :conjugated true
-                  :français (get-in val [:français :future-stem] "ais")
+      {:français {:infl :conditional
+                  :conjugated true
+                  :français (str (get-in val [:français :future-stem]) "ais")
                   :agr {:number :sing
                         :person :1st}}})}
    {:path [:français :future-stem]
     :merge-fn
     (fn [val]
-      {:français {:infl :future
-                  :conjugated true
-                  :français (get-in val [:français :future-stem] "ais")
+      {:français {:infl :conditional
+                  :conjugated true
+                  :français (str (get-in val [:français :future-stem]) "ais")
                   :agr {:number :sing
                         :person :2nd}}})}
    {:path [:français :future-stem]
     :merge-fn
     (fn [val]
-      {:français {:infl :future
-                  :conjugated true
-                  :français (get-in val [:français :future-stem] "ait")
+      {:français {:infl :conditional
+                  :conjugated true
+                  :français (str (get-in val [:français :future-stem]) "ait")
                   :agr {:number :sing
                         :person :3rd}}})}
    {:path [:français :future-stem]
     :merge-fn
     (fn [val]
-      {:français {:infl :future
-                  :français (get-in val [:français :future-stem] "ions")
+      {:français {:infl :conditional
+                  :français (str (get-in val [:français :future-stem]) "ions")
                   :agr {:number :plur
                         :person :1st}}})}
    {:path [:français :future-stem]
     :merge-fn
     (fn [val]
+      {:français {:infl :conditional
+                  :français (str (get-in val [:français :future-stem]) "iez")
+                  :conjugated true
+                  :agr {:number :plur
+                        :person :2nd}}})}
+
+   {:path [:français :future-stem]
+    :merge-fn
+    (fn [val]
+      {:français {:infl :conditional
+                  :français (str (get-in val [:français :future-stem]) "aient")
+                  :conjugated true
+                  :agr {:number :plur
+                        :person :3rd}}})}
+
+   ;; 4. future-tense exceptions
+   {:path [:français :future-stem]
+    :merge-fn
+    (fn [val]
       {:français {:infl :future
-                  :français (get-in val [:français :future-stem] "iez")
+                  :conjugated true
+                  :français (str (get-in val [:français :future-stem]) "ai")
+                  :agr {:number :sing
+                        :person :1st}}})}
+
+   {:path [:français :future-stem]
+    :merge-fn
+    (fn [val]
+      {:français {:infl :future
+                  :val val
+                  :got-here true
+                  :conjugated true
+                  :français (str (get-in val [:français :future-stem]) "as")
+                  :agr {:number :sing
+                        :person :2nd}}})}
+
+   {:path [:français :future-stem]
+    :merge-fn
+    (fn [val]
+      {:français {:infl :future
+                  :conjugated true
+                  :français (str (get-in val [:français :future-stem]) "a")
+                  :agr {:number :sing
+                        :person :3rd}}})}
+   {:path [:français :future-stem]
+    :merge-fn
+    (fn [val]
+      {:français {:infl :future
+                  :français (str (get-in val [:français :future-stem]) "ons")
+                  :agr {:number :plur
+                        :person :1st}}})}
+   {:path [:français :future-stem]
+    :merge-fn
+    (fn [val]
+      {:français {:infl :future
+                  :français (str (get-in val [:français :future-stem]) "ez")
                   :conjugated true
                   :agr {:number :plur
                         :person :2nd}}})}
@@ -1007,56 +1061,7 @@
     :merge-fn
     (fn [val]
       {:français {:infl :future
-                  :français (get-in val [:français :future-stem] "aient")
-                  :conjugated true
-                  :agr {:number :plur
-                        :person :3rd}}})}
-
-   ;; 4. future-tense exceptions
-   {:path [:français :future-stem]
-    :merge-fn
-    (fn [val]
-      {:français {:infl :future
-                  :conjugated true
-                  :français (get-in val [:français :future-stem] "ai")
-                  :agr {:number :sing
-                        :person :1st}}})}
-   {:path [:français :future-stem]
-    :merge-fn
-    (fn [val]
-      {:français {:infl :future
-                  :conjugated true
-                  :français (get-in val [:français :future-stem] "as")
-                  :agr {:number :sing
-                        :person :2nd}}})}
-   {:path [:français :future-stem]
-    :merge-fn
-    (fn [val]
-      {:français {:infl :future
-                  :conjugated true
-                  :français (get-in val [:français :future-stem] "a")
-                  :agr {:number :sing
-                        :person :3rd}}})}
-   {:path [:français :future-stem]
-    :merge-fn
-    (fn [val]
-      {:français {:infl :future
-                  :français (get-in val [:français :future-stem] "ons")
-                  :agr {:number :plur
-                        :person :1st}}})}
-   {:path [:français :future-stem]
-    :merge-fn
-    (fn [val]
-      {:français {:infl :future
-                  :français (get-in val [:français :future-stem] "ez")
-                  :conjugated true
-                  :agr {:number :plur
-                        :person :2nd}}})}
-   {:path [:français :future-stem]
-    :merge-fn
-    (fn [val]
-      {:français {:infl :future
-                  :français (get-in val [:français :future-stem] "ont")
+                  :français (str (get-in val [:français :future-stem] "ont"))
                   :conjugated true
                   :agr {:number :plur
                         :person :3rd}}})}


Fix doc typo

Fix doc typo

--- src/cognitect/transit.clj
+++ src/cognitect/transit.clj
@@ -119,7 +119,7 @@
 (deftype Writer [w])

 (defn writer
-  "Creates a writer over the privided destination `out` using
+  "Creates a writer over the provided destination `out` using
    the specified format, one of: :msgpack, :json or :json-verbose.

    An optional opts map may be passed. Supported options are:


minor

minor

--- src-cljs/cljs_gui/core.cljs
+++ src-cljs/cljs_gui/core.cljs
@@ -34,7 +34,7 @@
   :projects {
     "~/t3tr0s/project.clj" {
       :name "t3tr0s"
-      :state :dormant
+      :state :idle
       :builds {
         :client {
           :checked? true
@@ -234,7 +234,7 @@
     [:td.cell-9ad24 (checked-cell (:checked? b))]
     [:td.cell-9ad24 (-> b :cljsbuild :source-paths first)] ;; TODO: print the vector here
     [:td.cell-9ad24 (-> b :cljsbuild :compiler :output-to)]
-    [:td.cell-9ad24 (status-cell  b)]
+    [:td.cell-9ad24 (status-cell b)]
     [:td.cell-9ad24 (last-compile-cell (:last-compile-time b))]
     [:td.cell-9ad24 (-> b :cljsbuild :compiler :optimizations name)]
     ;;[:td.cell-9ad24 "Actions" [:i.fa.fa-caret-down]]


Added doc string.

Added doc string.

--- src-cljs/freactive/dom.cljs
+++ src-cljs/freactive/dom.cljs
@@ -782,6 +782,9 @@
       (append-child! elem ch))))

 (defn update-attrs
+  "Convenience function to update the attrs in a virtual dom vector.
+Works like Clojure's update function but f (and its args) only modify the attrs
+map in vdom."
   ([vdom f & args]
    (let [tag (first vdom)
          attrs? (second vdom)


More sensible start and stop times

More sensible start and stop times

--- src-cljs/frontend/send.cljs
+++ src-cljs/frontend/send.cljs
@@ -1,12 +1,14 @@
 (ns frontend.send
-  (:require [cljs.core.async :refer [chan]]
+  (:require [cljs-time.coerce :as time-coerce]
+            [cljs-time.core :as time]
+            [cljs.core.async :refer [chan]]
             [clojure.spec :as s :include-macros true]
+            [clojure.string :as string]
             [clojure.test.check.generators :as gen]
             [frontend.api :as api]
             [frontend.utils.vcs-url :as vcs-url]
             [om.next :as om-next]
-            [om.util :as om-util]
-            [clojure.string :as string])
+            [om.util :as om-util])
   (:require-macros [cljs.core.async.macros :as am :refer [go-loop]]))

 ;; These spec should find a better place to live, but data generation in `send`
@@ -37,27 +39,45 @@
 (s/def :run/started-at inst?)
 (s/def :run/stopped-at inst?)
 (s/def :run/branch-name string?)
-(s/def :run/commit-sha (s/with-gen (s/and string?
-                                          #(= 40 (count %))
-                                          (partial re-matches #"^[0-9a-f]*$"))
+(s/def :run/commit-sha (s/with-gen
+                         (s/and string?
+                                #(= 40 (count %))
+                                (partial re-matches #"^[0-9a-f]*$"))
                          #(gen/fmap string/join
                                     (gen/vector
                                      (gen/fmap char
                                                (gen/one-of [(gen/choose 48 57)
                                                             (gen/choose 97 102)]))
                                      40))))
-(s/def :run/entity (s/keys :req [:run/id
-                                 :run/status
-                                 :run/started-at
-                                 :run/stopped-at
-                                 :run/branch-name
-                                 :run/commit-sha]))
+(s/def :run/entity (s/and
+                    (s/keys :req [:run/id
+                                  :run/status
+                                  :run/started-at
+                                  :run/stopped-at
+                                  :run/branch-name
+                                  :run/commit-sha])
+                    #(< (:run/started-at %)
+                        (:run/stopped-at %))))

-;; via https://github.com/paraseba/faker/blob/master/src/faker/lorem_data.clj
+;; via https://github.com/paraseba/faker/blob/master/srfaker/lorem_data.clj
 (def latin-word
   (gen/elements
    ["alias" "consequatur" "aut" "perferendis" "sit" "voluptatem" "accusantium" "doloremque" "aperiam" "eaque" "ipsa" "quae" "ab" "illo" "inventore" "veritatis" "et" "quasi" "architecto" "beatae" "vitae" "dicta" "sunt" "explicabo" "aspernatur" "aut" "odit" "aut" "fugit" "sed" "quia" "consequuntur" "magni" "dolores" "eos" "qui" "ratione" "voluptatem" "sequi" "nesciunt" "neque" "dolorem" "ipsum" "quia" "dolor" "sit" "amet" "consectetur" "adipisci" "velit" "sed" "quia" "non" "numquam" "eius" "modi" "tempora" "incidunt" "ut" "labore" "et" "dolore" "magnam" "aliquam" "quaerat" "voluptatem" "ut" "enim" "ad" "minima" "veniam" "quis" "nostrum" "exercitationem" "ullam" "corporis" "nemo" "enim" "ipsam" "voluptatem" "quia" "voluptas" "sit" "suscipit" "laboriosam" "nisi" "ut" "aliquid" "ex" "ea" "commodi" "consequatur" "quis" "autem" "vel" "eum" "iure" "reprehenderit" "qui" "in" "ea" "voluptate" "velit" "esse" "quam" "nihil" "molestiae" "et" "iusto" "odio" "dignissimos" "ducimus" "qui" "blanditiis" "praesentium" "laudantium" "totam" "rem" "voluptatum" "deleniti" "atque" "corrupti" "quos" "dolores" "et" "quas" "molestias" "excepturi" "sint" "occaecati" "cupiditate" "non" "provident" "sed" "ut" "perspiciatis" "unde" "omnis" "iste" "natus" "error" "similique" "sunt" "in" "culpa" "qui" "officia" "deserunt" "mollitia" "animi" "id" "est" "laborum" "et" "dolorum" "fuga" "et" "harum" "quidem" "rerum" "facilis" "est" "et" "expedita" "distinctio" "nam" "libero" "tempore" "cum" "soluta" "nobis" "est" "eligendi" "optio" "cumque" "nihil" "impedit" "quo" "porro" "quisquam" "est" "qui" "minus" "id" "quod" "maxime" "placeat" "facere" "possimus" "omnis" "voluptas" "assumenda" "est" "omnis" "dolor" "repellendus" "temporibus" "autem" "quibusdam" "et" "aut" "consequatur" "vel" "illum" "qui" "dolorem" "eum" "fugiat" "quo" "voluptas" "nulla" "pariatur" "at" "vero" "eos" "et" "accusamus" "officiis" "debitis" "aut" "rerum" "necessitatibus" "saepe" "eveniet" "ut" "et" "voluptates" "repudiandae" "sint" "et" "molestiae" "non" "recusandae" "itaque" "earum" "rerum" "hic" "tenetur" "a" "sapiente" "delectus" "ut" "aut" "reiciendis" "voluptatibus" "maiores" "doloribus" "asperiores" "repellat"]))
+
+(def inst-in-last-day
+  #(s/gen (s/inst-in (time-coerce/to-date (time/minus (time/now) (time/days 1)))
+                     (time-coerce/to-date (time/now)))))
+
+(def
+  ^{:doc
+    "Generator overrides that make nice looking data. Good for mock data
+     displays; bad for property testing, which wants to hit edge cases."}
+  dummy-data-overrides
+  {:run/branch-name #(gen/fmap (partial string/join "-")
+                               (gen/vector latin-word 1 7))
+   :run/started-at inst-in-last-day
+   :run/stopped-at inst-in-last-day})

@@ -158,11 +178,12 @@
                       (let [ident-vals (second (om-util/join-key expr))]
                         (gen/generate
                          (s/gen :workflow/entity
-                                {:run/branch-name #(gen/fmap (partial string/join "-") (gen/vector latin-word 1 7))
-                                 [:workflow/name] #(gen/return (:workflow/name ident-vals))
-                                 [:workflow/project :project/name] #(gen/return (:project/name ident-vals))
-                                 [:workflow/project :project/organization :organization/name] #(gen/return (:organization/name ident-vals))
-                                 [:workflow/project :project/organization :organization/vcs-type] #(gen/return (:organization/vcs-type ident-vals))})))})
+                                (merge
+                                 dummy-data-overrides
+                                 {[:workflow/name] #(gen/return (:workflow/name ident-vals))
+                                  [:workflow/project :project/name] #(gen/return (:project/name ident-vals))
+                                  [:workflow/project :project/organization :organization/name] #(gen/return (:organization/name ident-vals))
+                                  [:workflow/project :project/organization :organization/vcs-type] #(gen/return (:organization/vcs-type ident-vals))}))))})
             ui-query)

         :else (throw (str "No clause found for " (pr-str expr)))))))


refactored function

refactored function

--- src/clj/backtype/storm/daemon/nimbus.clj
+++ src/clj/backtype/storm/daemon/nimbus.clj
@@ -136,7 +136,7 @@
                  }})

 (defn topology-status [nimbus storm-id]
-  (:status (.storm-base (:storm-cluster-state nimbus) storm-id nil)))
+  (-> nimbus :storm-cluster-state (.storm-base storm-id nil) :status))

 (defn transition!
   ([nimbus storm-id event]


need dispatchset?

need dispatchset?

--- src/cljc/ow/starbuck/message_router.cljc
+++ src/cljc/ow/starbuck/message_router.cljc
@@ -155,6 +155,9 @@
                      :booker {:transform (fn [msg] (assoc msg :checked true))
                               :next [:invoice-generator (fn [msg] :notifier)]}}}}})

+  (def dispatchset1
+    {})
+
   #_(def router1 (message-router ruleset1))

   (->> (message :book-flight {:foo :bar})