test-ified function_invocation

test-ified function_invocation

--- test/function_invocation.coffee
+++ test/function_invocation.coffee
@@ -7,9 +7,11 @@
 # * Explicit Returns

 # shared identity function
-id = (_) -> if arguments.length is 1 then _ else Array::slice.call(arguments)
+id = (_) -> if arguments.length is 1 then _ else [arguments...]
+

 test "basic argument passing", ->
+
   a = {}
   b = {}
   c = {}
@@ -18,7 +20,9 @@
   eq a, (id a)
   eq c, (id a, b, c)[2]

+
 test "passing arguments on separate lines", ->
+
   a = {}
   b = {}
   c = {}
@@ -37,7 +41,9 @@
   eq b,
   (id b)

+
 test "optional parens can be used in a nested fashion", ->
+
   call = (func) -> func()
   add = (a,b) -> a + b
   result = call ->
@@ -45,7 +51,9 @@
       add 5, 5
   ok result is 10

+
 test "hanging commas and semicolons in argument list", ->
+
   fn = () -> arguments.length
   eq 2, fn(0,1,)
   eq 3, fn 0, 1,
@@ -58,24 +66,32 @@
   throws -> CoffeeScript.compile "fn(,0)"
   throws -> CoffeeScript.compile "fn(;0)"

-func = ->
-  return if true
-eq undefined, func()
-
-result = ("hello".slice) 3
-ok result is 'lo'
-
-# And even with strange things like this:
-funcs  = [((x) -> x), ((x) -> x * x)]
-result = funcs[1] 5
-ok result is 25
-
-# More fun with optional parens.
-fn = (arg) -> arg
-ok fn(fn {prop: 101}).prop is 101
-
-okFunc = (f) -> ok(f())
-okFunc -> true
+
+test "function invocation", ->
+
+  func = ->
+    return if true
+  eq undefined, func()
+
+  result = ("hello".slice) 3
+  ok result is 'lo'
+
+
+test "And even with strange things like this:", ->
+
+  funcs  = [((x) -> x), ((x) -> x * x)]
+  result = funcs[1] 5
+  ok result is 25
+
+
+test "More fun with optional parens.", ->
+
+  fn = (arg) -> arg
+  ok fn(fn {prop: 101}).prop is 101
+
+  okFunc = (f) -> ok(f())
+  okFunc -> true
+

 test "chained function calls", ->
   nonce = {}
@@ -84,31 +100,39 @@
   eq nonce, identityWrap(identityWrap(nonce))()()
   eq nonce, (identityWrap identityWrap nonce)()()

-# Multi-blocks with optional parens.
-result = fn( ->
-  fn ->
-    "Wrapped"
-)
-ok result()() is 'Wrapped'
-
-# method calls
-fnId = (fn) -> -> fn.apply this, arguments
-math = {
-  add: (a, b) -> a + b
-  anonymousAdd: (a, b) -> a + b
-  fastAdd: fnId (a, b) -> a + b
-}
-ok math.add(5, 5) is 10
-ok math.anonymousAdd(10, 10) is 20
-ok math.fastAdd(20, 20) is 40
-
-# Ensure that functions can have a trailing comma in their argument list
-mult = (x, mids..., y) ->
-  x *= n for n in mids
-  x *= y
-ok mult(1, 2,) is 2
-ok mult(1, 2, 3,) is 6
-ok mult(10, (i for i in [1..6])...) is 7200
+
+test "Multi-blocks with optional parens.", ->
+
+  fn = (arg) -> arg
+  result = fn( ->
+    fn ->
+      "Wrapped"
+  )
+  ok result()() is 'Wrapped'
+
+
+test "method calls", ->
+
+  fnId = (fn) -> -> fn.apply this, arguments
+  math = {
+    add: (a, b) -> a + b
+    anonymousAdd: (a, b) -> a + b
+    fastAdd: fnId (a, b) -> a + b
+  }
+  ok math.add(5, 5) is 10
+  ok math.anonymousAdd(10, 10) is 20
+  ok math.fastAdd(20, 20) is 40
+
+
+test "Ensure that functions can have a trailing comma in their argument list", ->
+
+  mult = (x, mids..., y) ->
+    x *= n for n in mids
+    x *= y
+  ok mult(1, 2,) is 2
+  ok mult(1, 2, 3,) is 6
+  ok mult(10, (i for i in [1..6])...) is 7200
+

 test "`@` and `this` should both be able to invoke a method", ->
   nonce = {}
@@ -118,133 +142,167 @@
   fn.withAt()
   fn.withThis()

-# Trying an implicit object call with a trailing function.
-a = null
-meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
-meth 'apple', b: 1, a: 13, ->
-  'orange'
-ok a is '13 apple orange'
-
-# Ensure that empty functions don't return mistaken values.
-obj =
-  func: (@param, @rest...) ->
-ok obj.func(101, 102, 103, 104) is undefined
-ok obj.param is 101
-ok obj.rest.join(' ') is '102 103 104'
-
-# Passing multiple functions without paren-wrapping is legal, and should compile.
-sum = (one, two) -> one() + two()
-result = sum ->
-  7 + 9
-, ->
-  1 + 3
-ok result is 20
-
-# Implicit call with a trailing if statement as a param.
-func = -> arguments[1]
-result = func 'one', if false then 100 else 13
-ok result is 13
-
-# Test more function passing:
-result = sum( ->
-  1 + 2
-, ->
-  2 + 1
-)
-ok result is 6
-
-sum = (a, b) -> a + b
-result = sum(1
-, 2)
-ok result is 3
-
-# Chained blocks, with proper indentation levels:
-counter =
-  results: []
-  tick: (func) ->
-    @results.push func()
-    this
-counter
-  .tick ->
-    3
-  .tick ->
-    2
-  .tick ->
-    1
-arrayEq [3,2,1], counter.results
-
-# This is a crazy one.
-x = (obj, func) -> func obj
-ident = (x) -> x
-result = x {one: ident 1}, (obj) ->
-  inner = ident(obj)
-  ident inner
-ok result.one is 1
-
-# More paren compilation tests:
-reverse = (obj) -> obj.reverse()
-ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
-
-# Test for inline functions with parentheses and implicit calls.
-combine = (func, num) -> func() * num
-result  = combine (-> 1 + 2), 3
-ok result is 9
-
-# Test for calls/parens/multiline-chains.
-f = (x) -> x
-result = (f 1).toString()
-  .length
-ok result is 1
-
-# Test implicit calls in functions in parens:
-result = ((val) ->
-  [].push val
-  val
-)(10)
-ok result is 10
-
-# Ensure that chained calls with indented implicit object literals below are
-# alright.
-result = null
-obj =
-  method: (val)  -> this
-  second: (hash) -> result = hash.three
-obj
-  .method(
+
+test "Trying an implicit object call with a trailing function.", ->
+
+  a = null
+  meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
+  meth 'apple', b: 1, a: 13, ->
+    'orange'
+  ok a is '13 apple orange'
+
+
+test "Ensure that empty functions don't return mistaken values.", ->
+
+  obj =
+    func: (@param, @rest...) ->
+  ok obj.func(101, 102, 103, 104) is undefined
+  ok obj.param is 101
+  ok obj.rest.join(' ') is '102 103 104'
+
+
+test "Passing multiple functions without paren-wrapping is legal, and should compile.", ->
+
+  sum = (one, two) -> one() + two()
+  result = sum ->
+    7 + 9
+  , ->
+    1 + 3
+  ok result is 20
+
+
+test "Implicit call with a trailing if statement as a param.", ->
+
+  func = -> arguments[1]
+  result = func 'one', if false then 100 else 13
+  ok result is 13
+
+
+test "Test more function passing:", ->
+
+  sum = (one, two) -> one() + two()
+
+  result = sum( ->
+    1 + 2
+  , ->
+    2 + 1
+  )
+  ok result is 6
+
+  sum = (a, b) -> a + b
+  result = sum(1
+  , 2)
+  ok result is 3
+
+
+test "Chained blocks, with proper indentation levels:", ->
+
+  counter =
+    results: []
+    tick: (func) ->
+      @results.push func()
+      this
+  counter
+    .tick ->
+      3
+    .tick ->
+      2
+    .tick ->
+      1
+  arrayEq [3,2,1], counter.results
+
+
+test "This is a crazy one.", ->
+
+  x = (obj, func) -> func obj
+  ident = (x) -> x
+  result = x {one: ident 1}, (obj) ->
+    inner = ident(obj)
+    ident inner
+  ok result.one is 1
+
+
+test "More paren compilation tests:", ->
+
+  reverse = (obj) -> obj.reverse()
+  ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
+
+
+test "Test for inline functions with parentheses and implicit calls.", ->
+
+  combine = (func, num) -> func() * num
+  result  = combine (-> 1 + 2), 3
+  ok result is 9
+
+
+test "Test for calls/parens/multiline-chains.", ->
+
+  f = (x) -> x
+  result = (f 1).toString()
+    .length
+  ok result is 1
+
+
+test "Test implicit calls in functions in parens:", ->
+
+  result = ((val) ->
+    [].push val
+    val
+  )(10)
+  ok result is 10
+
+
+test "Ensure that chained calls with indented implicit object literals below are alright.", ->
+
+  result = null
+  obj =
+    method: (val)  -> this
+    second: (hash) -> result = hash.three
+  obj
+    .method(
+      101
+    ).second(
+      one:
+        two: 2
+      three: 3
+    )
+  eq result, 3
+
+
+test "Test newline-supressed call chains with nested functions.", ->
+
+  obj  =
+    call: -> this
+  func = ->
+    obj
+      .call ->
+        one two
+      .call ->
+        three four
     101
-  ).second(
-    one:
-      two: 2
-    three: 3
-  )
-eq result, 3
-
-# Test newline-supressed call chains with nested functions.
-obj  =
-  call: -> this
-func = ->
-  obj
-    .call ->
-      one two
-    .call ->
-      three four
-  101
-eq func(), 101
-
-# Implicit objects with number arguments.
-func = (x, y) -> y
-obj =
-  prop: func "a", 1
-ok obj.prop is 1
-
-# Non-spaced unary and binary operators should cause a function call.
-func = (val) -> val + 1
-ok (func +5) is 6
-ok (func -5) is -4
-
-# Prefix unary assignment operators are allowed in parenless calls.
-val = 5
-ok (func --val) is 5
+  eq func(), 101
+
+
+test "Implicit objects with number arguments.", ->
+
+  func = (x, y) -> y
+  obj =
+    prop: func "a", 1
+  ok obj.prop is 1
+
+
+test "Non-spaced unary and binary operators should cause a function call.", ->
+
+  func = (val) -> val + 1
+  ok (func +5) is 6
+  ok (func -5) is -4
+
+
+test "Prefix unary assignment operators are allowed in parenless calls.", ->
+
+  func = (val) -> val + 1
+  val = 5
+  ok (func --val) is 5

 test "#855: execution context for `func arr...` should be `null`", ->
   contextTest = -> eq @, global
@@ -262,13 +320,14 @@
   eq nonce, a
   eq nonce, b

-obj =
-  index: 0
-  0: {method: -> this is obj[0]}
-ok obj[obj.index++].method([]...), 'should cache base value'
-
-
-# Splats in Function Invocations
+
+test "caching base value", ->
+
+  obj =
+    index: 0
+    0: {method: -> this is obj[0]}
+  ok obj[obj.index++].method([]...)
+

 test "passing splats to functions", ->
   arrayEq [0..4], id id [0..4]...
@@ -280,33 +339,40 @@
   arrayEq [2..6], others
   eq 7, last

-#894: Splatting against constructor-chained functions.
-x = null
-class Foo
-  bar: (y) -> x = y
-new Foo().bar([101]...)
-eq x, 101
-
-# Functions with splats being called with too few arguments.
-pen = null
-method = (first, variable..., penultimate, ultimate) ->
-  pen = penultimate
-method 1, 2, 3, 4, 5, 6, 7, 8, 9
-ok pen is 8
-method 1, 2, 3
-ok pen is 2
-method 1, 2
-ok pen is 2
-
-# splats with super() within classes.
-class Parent
-  meth: (args...) ->
-    args
-class Child extends Parent
-  meth: ->
-    nums = [3, 2, 1]
-    super nums...
-ok (new Child).meth().join(' ') is '3 2 1'
+
+test "Issue 894: Splatting against constructor-chained functions.", ->
+
+  x = null
+  class Foo
+    bar: (y) -> x = y
+  new Foo().bar([101]...)
+  eq x, 101
+
+
+test "Functions with splats being called with too few arguments.", ->
+
+  pen = null
+  method = (first, variable..., penultimate, ultimate) ->
+    pen = penultimate
+  method 1, 2, 3, 4, 5, 6, 7, 8, 9
+  ok pen is 8
+  method 1, 2, 3
+  ok pen is 2
+  method 1, 2
+  ok pen is 2
+
+
+test "splats with super() within classes.", ->
+
+  class Parent
+    meth: (args...) ->
+      args
+  class Child extends Parent
+    meth: ->
+      nums = [3, 2, 1]
+      super nums...
+  ok (new Child).meth().join(' ') is '3 2 1'
+

 test "#1011: passing a splat to a method of a number", ->
   eq '1011', 11.toString [2]...
@@ -315,12 +381,13 @@
   eq '1011', (131.0).toString [5]...

-# Implicit Return
-
-eq ok, new ->
-  ok
-  ### Should `return` implicitly   ###
-  ### even with trailing comments. ###
+test "implicit return", ->
+
+  eq ok, new ->
+    ok
+    ### Should `return` implicitly   ###
+    ### even with trailing comments. ###
+

 test "implicit returns with multiple branches", ->
   nonce = {}
@@ -332,6 +399,7 @@
       nonce
   eq nonce, fn()

+
 test "implicit returns with switches", ->
   nonce = {}
   fn = ->
@@ -339,6 +407,7 @@
       when nonce then nonce
       else return undefined
   eq nonce, fn()
+

 test "preserve context when generating closure wrappers for expression conversions", ->
   nonce = {}
@@ -355,9 +424,7 @@
   eq nonce, obj.property

-# Explicit Returns
-
-test "don't wrap \"pure\" statements in a closure", ->
+test "don't wrap 'pure' statements in a closure", ->
   nonce = {}
   items = [0, 1, 2, 3, nonce, 4, 5]
   fn = (items) ->


proper env variable name

proper env variable name

--- test/helpers/integration.coffee
+++ test/helpers/integration.coffee
@@ -1,10 +1,10 @@
-#
+#
 # Integration test helper that makes it easy to write fast integration tests.
 # One of the ways it does this is by providing the methods `startServer` and
 # `closeServer` that will spawn a child process of this project. This means
 # a version of this project server will run on localhost:5000 using a fake
 # API server exposed below a `api`.
-#
+#
 spawn = require("child_process").spawn
 express = require "express"

@@ -21,7 +21,7 @@
   return callback() if @child?
   envVars =
     NODE_ENV: "test"
-    ARTSY_URL: "http://localhost:5000/__api"
+    API_URL: "http://localhost:5000/__api"
     PORT: 5000
   envVars[k] = val for k, val of process.env when not envVars[k]?
   @child = spawn "make", ["s"],
@@ -31,7 +31,7 @@
   @child.on "message", -> callback()
   @child.stdout.on "data", (data) -> console.log data.toString()

-# Closes the server child process, used in an `after` hook and on
+# Closes the server child process, used in an `after` hook and on
 # `process.exit` in case the test suite is interupted.
 @closeServer = =>
   @child?.kill()
@@ -39,7 +39,7 @@

 process.on "exit", @closeServer

-# You can debug your integration app and run this app server by running
+# You can debug your integration app and run this app server by running
 # this module directly and opening up localhost:5000.
 # e.g. `coffee test/helpers/integration.coffee`
 return unless module is require.main


displayが表示されていない時のみ表示するようにする

displayが表示されていない時のみ表示するようにする

--- app/assets/javascripts/components/shared/twitter_shared_button.js.cjsx
+++ app/assets/javascripts/components/shared/twitter_shared_button.js.cjsx
@@ -7,7 +7,7 @@

   componentDidMount: ->
     if twttr?
-      twttr.widgets.load()
+      twttr.widgets.load $('#twitter-shared-button')
     else
       twitterjs = document.createElement 'script'
       twitterjs.async = true
@@ -15,10 +15,11 @@
       document.getElementsByTagName('body')[0].appendChild twitterjs

   componentDidUpdate: ->
-    @setState display: 'block'
+    @setState display: 'block' if @state.display is 'none'

   render: ->
     <a
+      id='twitter-shared-button'
       style={display: @state.display}
       href='https://twitter.com/share'
       data-text={@state.text}


Fixed test by removing erroneous `done()` call


Switch to Courier for linux compatible tests


Remove global debugging hook

Remove global debugging hook

--- services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
+++ services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
@@ -11,7 +11,7 @@
 			CUR_FILE : "cur_file"
 			OVERVIEW : "overview"

-		window.reviewPanel = $scope.reviewPanel =
+		$scope.reviewPanel =
 			entries: {}
 			hasEntries: false
 			subView: $scope.SubViews.CUR_FILE


Better warning detection + file paths

Better warning detection + file paths


fix tss highlight selector bug

fix tss highlight selector bug

--- grammars/tss.cson
+++ grammars/tss.cson
@@ -9,7 +9,8 @@
       'include': '#comment-block'
     }
     { # ID
-      'match': '(["\'])#.+?\\1'
+      'begin': '(["\'])#.+?'
+      'end' : '\\1'
       'name': 'entity.other.attribute-name.id.css'
       'patterns':[
         {
@@ -18,7 +19,8 @@
       ]
     }
     { # CLASS
-      'match': '(["\'])\..+?\\1'
+      'begin': '(["\'])\\..+?'
+      'end' : '\\1'
       'name': 'entity.other.attribute-name.class.css'
       # "match": "\"#(.+)\""
       'patterns':[
@@ -29,7 +31,8 @@
     }
     { # TAG
       # TODO: create match generation code (below math condition from languate-tss package, thanks @m1ga)
-      'match': "([\"'])(2DMatrix|3DMatrix|ActivityIndicator|ActivityIndicatorStyle|AlertDialog|Android|ProgressIndicator|SearchView|Animation|Button|ButtonBar|Clipboard|CoverFlowView|DashboardItem|DashboardView|EmailDialog|ImageView|Label|ListItem|ListSection|ListView|MaskedImage|MobileWeb|iOS|iPhone|NavigationGroup|TableViewSeparatorStyle|Notification|OptionDialog|Picker|PickerColumn|PickerRow|ProgressBar|RefreshControl|SMSDialog|ScrollView|ScrollableView|SearchBar|Slider|Switch|Tab|TabGroup|TabbedBar|TableView|TableViewRow|TableViewSection|TextArea|TextField|Toolbar|View|WebView|Window|iOS|3DMatrix|AdView|AnchorAttachmentBehavior|Animator|AttributedString|CollisionBehavior|CoverFlowView|DocumentViewer|DynamicItemBehavior|GravityBehavior|NavigationWindow|PushBehavior|SnapBehavior|TabbedBar|Toolbar|ViewAttachmentBehavior|iPad|DocumentViewer|Popover|SplitWindow|iPhone|ActivityIndicatorStyle|AlertDialogStyle|AnimationStyle|ListViewCellSelectionStyle|ListViewScrollPosition|ListViewSeparatorStyle|ListViewStyle|NavigationGroup|ProgressBarStyle|RowAnimationStyle|ScrollIndicatorStyle|StatusBar|SystemButton|SystemButtonStyle|SystemIcon|TableViewCellSelectionStyle|TableViewScrollPosition|TableViewSeparatorStyle|TableViewStyle)\\1"
+      'begin': "([\"'])(2DMatrix|3DMatrix|ActivityIndicator|ActivityIndicatorStyle|AlertDialog|Android|ProgressIndicator|SearchView|Animation|Button|ButtonBar|Clipboard|CoverFlowView|DashboardItem|DashboardView|EmailDialog|ImageView|Label|ListItem|ListSection|ListView|MaskedImage|MobileWeb|iOS|iPhone|NavigationGroup|TableViewSeparatorStyle|Notification|OptionDialog|Picker|PickerColumn|PickerRow|ProgressBar|RefreshControl|SMSDialog|ScrollView|ScrollableView|SearchBar|Slider|Switch|Tab|TabGroup|TabbedBar|TableView|TableViewRow|TableViewSection|TextArea|TextField|Toolbar|View|WebView|Window|iOS|3DMatrix|AdView|AnchorAttachmentBehavior|Animator|AttributedString|CollisionBehavior|CoverFlowView|DocumentViewer|DynamicItemBehavior|GravityBehavior|NavigationWindow|PushBehavior|SnapBehavior|TabbedBar|Toolbar|ViewAttachmentBehavior|iPad|DocumentViewer|Popover|SplitWindow|iPhone|ActivityIndicatorStyle|AlertDialogStyle|AnimationStyle|ListViewCellSelectionStyle|ListViewScrollPosition|ListViewSeparatorStyle|ListViewStyle|NavigationGroup|ProgressBarStyle|RowAnimationStyle|ScrollIndicatorStyle|StatusBar|SystemButton|SystemButtonStyle|SystemIcon|TableViewCellSelectionStyle|TableViewScrollPosition|TableViewSeparatorStyle|TableViewStyle)"
+      'end' : '\\1'
       'name' : 'entity.name.tag.css'
       'patterns':[
         {
@@ -157,24 +160,6 @@
               'name': 'keyword.other.unit.css'
           'match': '(?x)\n\t\t\t\t\t    (?:-|\\+)?(?:(?:[0-9]+(?:\\.[0-9]+)?)|(?:\\.[0-9]+))\n\t\t\t\t\t    ((?:px|pt|ch|cm|mm|in|r?em|ex|pc|deg|g?rad|dpi|dpcm|dppx|fr|ms|s|turn|vh|vmax|vmin|vw)\\b|%)?\n\t\t\t\t\t'
           'name': 'constant.numeric.css'
-        }
-      ]
-
-    'selector':
-      'begin': '\\s*"(?=[:.*#a-zA-Z])'
-      'end': '"\\s*(?=:)'
-      'name': 'meta.selector.css'
-      'patterns': [
-        { # TAG
-          # TODO: create match generation code (below math condition from languate-tss package, thanks @m1ga)
-          'match': "(2DMatrix|3DMatrix|ActivityIndicator|ActivityIndicatorStyle|AlertDialog|Android|ProgressIndicator|SearchView|Animation|Button|ButtonBar|Clipboard|CoverFlowView|DashboardItem|DashboardView|EmailDialog|ImageView|Label|ListItem|ListSection|ListView|MaskedImage|MobileWeb|iOS|iPhone|NavigationGroup|TableViewSeparatorStyle|Notification|OptionDialog|Picker|PickerColumn|PickerRow|ProgressBar|RefreshControl|SMSDialog|ScrollView|ScrollableView|SearchBar|Slider|Switch|Tab|TabGroup|TabbedBar|TableView|TableViewRow|TableViewSection|TextArea|TextField|Toolbar|View|WebView|Window|iOS|3DMatrix|AdView|AnchorAttachmentBehavior|Animator|AttributedString|CollisionBehavior|CoverFlowView|DocumentViewer|DynamicItemBehavior|GravityBehavior|NavigationWindow|PushBehavior|SnapBehavior|TabbedBar|Toolbar|ViewAttachmentBehavior|iPad|DocumentViewer|Popover|SplitWindow|iPhone|ActivityIndicatorStyle|AlertDialogStyle|AnimationStyle|ListViewCellSelectionStyle|ListViewScrollPosition|ListViewSeparatorStyle|ListViewStyle|NavigationGroup|ProgressBarStyle|RowAnimationStyle|ScrollIndicatorStyle|StatusBar|SystemButton|SystemButtonStyle|SystemIcon|TableViewCellSelectionStyle|TableViewScrollPosition|TableViewSeparatorStyle|TableViewStyle)"
-          # 'end': "\""
-          'name' : 'entity.name.tag.css'
-          # 'patterns':[
-          #   {
-          #     'include' : '#query'
-          #   }
-          # ]
         }
       ]
     'string-double':


Hooks page is broken atm, no longer

Hooks page is broken atm, no longer

--- packages/shrub-grunt/dox/dynamic.coffee
+++ packages/shrub-grunt/dox/dynamic.coffee
@@ -96,7 +96,7 @@
     # Comment.
     if '#'.charCodeAt(0) is line.trim().charCodeAt(0)

-      @push "```\n" if @hasWrittenCode and not @commenting
+      @push "```\n\n" if @hasWrittenCode and not @commenting

       comment = line.trim().substr 2
       @push "#{comment}\n"
@@ -106,7 +106,7 @@
     else

       @hanging = [] if @commenting
-      @push "```#{@highlight}\n" if @commenting or not @hasWrittenCode
+      @push "\n```#{@highlight}\n" if @commenting or not @hasWrittenCode

       if line.length is 0
         @hanging.push '' unless @commenting


btter controls

btter controls

--- web/src/cs/views/default.coffee
+++ web/src/cs/views/default.coffee
@@ -100,7 +100,11 @@
 	mouse.x = e.clientX / window.innerWidth
 	mouse.y = e.clientY / window.innerHeight
 update = () ->
-	amount = (1 - mouse.y ) * 8 + 1
+	amount = (1 - (Math.abs(mouse.x - 0.5) + Math.abs(mouse.y - 0.5))) * 8
+	if amount < 1
+		amount = 1
+	console.log amount
+	amount = ~~amount
 	move(amount)
 	camera.position.x = -(mouse.x - 0.5) * 1000
 	camera.position.y = -(mouse.y - 0.5) * 1000


Demo

Demo

- Fixed to use Template.loadTemplateFile.

--- demo/src/demo.coffee
+++ demo/src/demo.coffee
@@ -238,7 +238,7 @@

 		CUI.DOM.prepend(document.body, @main_menu_pane.DOM)

-		Template.loadFile("demo/easydbui_demo.html")
+		Template.loadTemplateFile("demo/easydbui_demo.html")
 		.done =>
 			@displayDemo()


add refactor notes

add refactor notes

--- app/assets/javascripts/hanuman/controllers/question.js.coffee
+++ app/assets/javascripts/hanuman/controllers/question.js.coffee
@@ -61,9 +61,14 @@

     deleteQuestion: ->
       question = @get('model')
+
+      ##### adolfo need to refactor to share this method with surveyStep controller #####
+      ##### call updateSortOrder(indexes)
+
       question.get('surveyStep').get('questions').removeObject(question)
       question.deleteRecord()
       question.save()
+

     newAnswerChoice: ->
       @set "isNewAnswerChoice", true


fixed merit order table sorting

fixed merit order table sorting

--- app/assets/javascripts/lib/views/html_table_chart_view.coffee
+++ app/assets/javascripts/lib/views/html_table_chart_view.coffee
@@ -15,7 +15,7 @@
     @container_node().html(@table_html())
     @fill_cells()
     # sort rows on merit order chart
-    @merit_order_sort() if @model.get("id") == 116
+    @merit_order_sort() if @model.get("key") == 'merit_order_table'

   # The table HTML is provided by the rails app.
   #
@@ -64,7 +64,7 @@
   can_be_shown_as_table: -> false

   merit_order_sort: =>
-    rows = _.sortBy $("##{@container_id()} tbody tr"), @merit_order_position
+    rows = _.sortBy @container_node().find("tbody tr"), @merit_order_position
     # get rid of rows with merit order of 1000. See ETE#193.
     # Ugly solution until we use better gqueries
     rows = _.reject rows, (item) => @merit_order_position(item) == 1000


Minor change (comments).

Minor change (comments).

--- app/assets/javascripts/ng-services/ng-AnimationsSvc.js.coffee
+++ app/assets/javascripts/ng-services/ng-AnimationsSvc.js.coffee
@@ -7,7 +7,7 @@
 ($rootScope)->

   #--------------------------------------------
-  # PRIVATE FUNCTION - Add a CSS class that sets identifies entry as open, for testing.
+  # PRIVATE FUNCTION - Add a CSS class that identifies entry as open, for testing.
   # Also set explictly height to 'auto' (setting the CSS class alone does not override the explicitly set
   # height otherwise).
   # This way if images in the entry are lazy-loaded after the open animation is finished,
@@ -17,9 +17,7 @@
     $(this).addClass('entry_open').css 'height', 'auto'

   #--------------------------------------------
-  # PRIVATE FUNCTION - Add a CSS class that sets entry height to 'auto'.
-  # This way if images in the entry are lazy-loaded after the open animation is finished,
-  # the entry height will adjust instantaneously.
+  # PRIVATE FUNCTION - Remove the CSS class that identifies entry as open.
   #--------------------------------------------
   remove_entry_open_class = ->
     $(this).removeClass 'entry_open'
@@ -27,7 +25,7 @@
   #--------------------------------------------
   # PRIVATE FUNCTION - Open a dropdown menu.
   # Receives as arguments:
-  # - jquery object of the menu wrapper (normally a li with class .dropdown)
+  # - jquery object of the menu wrapper (normally a li or div with class .dropdown)
   # - jquery object of the link that toggles the menu
   # - namespace to apply to the event handler that will be created to close the menu if user clicks outside it.
   # It should be a namespaced "click" event, like "click.mynamespace"
@@ -59,7 +57,7 @@
   # Receives as arguments:
   # - jquery object of the menu wrapper (normally a li with class .dropdown)
   # - jquery object of the link that toggles the menu
-  # - namespace to apply to the event handler that will be created to close the menu if user clicks outside it.
+  # - namespace to apply to the event handler that was created to close the menu if user clicks outside it.
   # It should be a namespaced "click" event, like "click.mynamespace"
   #--------------------------------------------
   close_menu = (menu_wrapper, menu_link, event_namespace)->
@@ -133,7 +131,7 @@
         open_menu menu_wrapper, menu_link, event_namespace

     #---------------------------------------------
-    # Animate toggling (open/close) the folders management menu
+    # Animate toggling (open/close) the user menu
     #---------------------------------------------
     toggle_user_menu: ->
       menu_wrapper = $('#user-dropdown')
@@ -146,7 +144,7 @@
         open_menu menu_wrapper, menu_link, event_namespace

     #---------------------------------------------
-    # Animate toggling (open/close) the folders management menu.
+    # Animate toggling (open/close) an entry social sharing menu.
     # Receives the entry as argument.
     #---------------------------------------------
     toggle_entry_social_menu: (entry)->
@@ -160,8 +158,7 @@
         open_menu menu_wrapper, menu_link, event_namespace

     #---------------------------------------------
-    # Animate toggling (open/close) the folders management menu.
-    # Receives the entry as argument.
+    # Animate toggling (open/close) the switch locale menu.
     #---------------------------------------------
     toggle_locale_menu: ->
       menu_wrapper = $('#switch-locale-dropdown')


Replace on ajax:sucess triggers replace:success

This makes the comment box resize correctly after a new comment is
posted.

--- app/assets/javascripts/replace_self_on_ajax_success.js.coffee
+++ app/assets/javascripts/replace_self_on_ajax_success.js.coffee
@@ -1,4 +1,4 @@
 $(document).on 'ajax:success', '[data-replace-self-on-ajax-success]', (event, data, status, xhr) ->
-  $(this).replaceWith(data)
-  $.fancybox.update()
-
+  newEl = $(data)
+  $(this).replaceWith(newEl)
+  newEl.trigger('replace:success')


upload files sequentially

upload files sequentially

--- app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js.coffee
+++ app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js.coffee
@@ -100,6 +100,8 @@
   p_upload.uploadFile({
     url: p_upload.attr("data-url"),
     fileName: "file_upload",
+    sequential: true,
+    sequentialCount: 1,
     uploadButtonClass: "btn btn-primary btn-block",
     dragDropStr: ''+p_upload.attr('data-dragDropStr')+'',
     uploadStr: p_upload.attr('data-uploadStr'),


fix(kanban): reduce time to hide swimlane dropdown

--- app/modules/components/swimlane-selector/swimlane-selector.directive.coffee
+++ app/modules/components/swimlane-selector/swimlane-selector.directive.coffee
@@ -52,7 +52,7 @@
         scope.hideOptions = () ->
             timeout = $timeout (() ->
                 scope.displaySelector = false
-            ), 1000
+            ), 100

         scope.selectSwimlane = (swimlane) ->
             scope.ngModel = swimlane.id


Rebuild

Rebuild

--- documentation/app/static/scripts/modules/load-markdown-documents.coffee
+++ documentation/app/static/scripts/modules/load-markdown-documents.coffee
@@ -136,8 +136,8 @@
   "mdown!../../documents/api/update-sandbox-permissions-example.md"
   "mdown!../../documents/api/update-sandbox-permissions.md"
   "mdown!../../documents/getting-started.md"
+  "mdown!../../documents/lp-reference.md"
   "mdown!../../documents/reference-manual.md"
-  "mdown!../../documents/lp-reference.md"
 ], (
   account_credentials_example
   account_credentials
@@ -276,8 +276,8 @@
   update_sandbox_permissions_example
   update_sandbox_permissions
   getting_started
+  lp_reference
   reference_manual
-  lp_reference
 ) ->
   Markdown =
     account_credentials_example: account_credentials_example
@@ -417,7 +417,7 @@
     update_sandbox_permissions_example: update_sandbox_permissions_example
     update_sandbox_permissions: update_sandbox_permissions
     getting_started: getting_started
+    lp_reference: lp_reference
     reference_manual: reference_manual
-    lp_reference: lp_reference

   return Markdown


Update Atom config

Update Atom config

--- atom.cson
+++ atom.cson
@@ -1,12 +1,14 @@
 "*":
   editor:
-    fontFamily: "Fira Mono OT"
+    fontFamily: "Fira Mono"
     showIndentGuide: true
     tabLength: 2
     softWrap: true
-    invisibles: {}
+    invisibles:
+      {}
     zoomFontWhenCtrlScrolling: false
     nonWordCharacters: "^*\"`'/|\\?!;:,.%#@(){}[]<>=+-~_"
+    fontSize: 17
   core:
     disabledPackages: [
       "language-objective-c"
@@ -36,13 +38,14 @@
     showOnStartup: false
   "markdown-preview":
     breakOnSingleNewline: true
-  "spell-check": {}
-".html.source":
+  "tree-view":
+    hideVcsIgnoredFiles: true
+".js.source":
   editor:
     tabLength: 4
 ".css.source":
   editor:
     tabLength: 4
-".js.source":
+".html.source":
   editor:
     tabLength: 4


Fix create line modal

Fix create line modal

--- view/coffee/creator/lines.coffee
+++ view/coffee/creator/lines.coffee
@@ -14,21 +14,20 @@
             last: json.pagination.last
       openModal: (line) ->
         if lineModal?
-          @lineModal = modalVue()
-        @lineModal.setLine(line)
+          @lineModal = modalVue(line)
         $(modalId).modal('show')

 modalId = '#lineModal'

-modalVue = -> new Vue
+modalVue = (line) -> new Vue
   el: modalId
   data:
-    line: {company: null}
+    line: line
     stations: []
   methods:
     getStations: ->
       API.getJSON "/api/line/#{@line.id}/stations", (json) =>
         @stations = json
-    setLine: (line) ->
-      @line = line
+  mounted: ->
+    @.$nextTick =>
       @getStations()


Add Stop/Reload to menu (Linux/Windows)

Add Stop/Reload to menu (Linux/Windows)

--- views/components/etc/menu.coffee
+++ views/components/etc/menu.coffee
@@ -62,6 +62,18 @@
     {
       label: __ 'View'
       submenu: [
+        {
+          label: __ 'Reload'
+          accelerator: 'CmdOrCtrl+R'
+          click: (item, focusedWindow) ->
+            exeCodeOnWindowHasReloadArea(focusedWindow, 'reload()')
+        },
+        {
+          label: __ 'Stop'
+          accelerator: 'CmdOrCtrl+.'
+          click: (item, focusedWindow) ->
+            exeCodeOnWindowHasReloadArea(focusedWindow, 'stop()')
+        },
         {
           label: __ 'Developer Tools'
           click: (item, focusedWindow) ->


parallax!

parallax!

--- ng-modules/travelScreen/travelScreen.coffee
+++ ng-modules/travelScreen/travelScreen.coffee
@@ -1,6 +1,8 @@
 require('angular');

-window.TRAVEL_SPEED = 1 # pixels per movement tick
+window.TRAVEL_SPEED = 1 # pixels per movement tick of tile travel
+window.TRAVELS_PER_MOVE = 5  # TRAVEL_SPEED divisor (for getting < 1 TRAVEL_SPEED)
+

 # TODO: move this to separate file and require it here
 class Tile
@@ -8,6 +10,7 @@
         @x = startX
         @img = imageElement
         @tileW = 1920  # TODO: load this dynamically
+        @travelCount = 0

     draw: (ctx)->
         # draws the tile
@@ -16,7 +19,11 @@

     travel: ()->
         # moves the tile 1 travel unit
-        @x -= window.TRAVEL_SPEED
+        if @travelCount > TRAVELS_PER_MOVE
+            @x -= window.TRAVEL_SPEED
+            @travelCount = 0
+        else
+            @travelCount += 1

     getOverhang: ()->
         # returns theoretical amount of tile overhanging right of screen, yet to be traveled to


Unbreak verification for file upload

Unbreak verification for file upload

--- resources/assets/coffee/react/profile-page/cover-uploader.coffee
+++ resources/assets/coffee/react/profile-page/cover-uploader.coffee
@@ -44,8 +44,8 @@
       done: (_e, data) ->
         $.publish 'user:update', data.result

-      fail: =>
-        osu.fileuploadFailCallback @$uploadButton()
+      fail: (event, data) =>
+        osu.fileuploadFailCallback(@$uploadButton()) event, data

       complete: ->
         $.publish 'user:cover:upload:state', false


Use createRef

Use createRef

--- resources/assets/coffee/react/profile-page/cover-uploader.coffee
+++ resources/assets/coffee/react/profile-page/cover-uploader.coffee
@@ -21,6 +21,12 @@

 class ProfilePage.CoverUploader extends React.Component
+  constructor: (props) ->
+    super props
+
+    @uploadButtonContainer = React.createRef()
+
+
   componentDidMount: =>
     $dropzone = $('.js-profile-cover-upload--dropzone')

@@ -30,7 +36,7 @@
       name: 'cover_file'
       disabled: !@props.canUpload

-    @uploadButtonContainer.appendChild($uploadButton[0])
+    @uploadButtonContainer.current.appendChild($uploadButton[0])

     $uploadButton.fileupload
       url: laroute.route('account.cover')
@@ -69,7 +75,7 @@

       el 'label',
         className: labelClass
-        ref: (el) => @uploadButtonContainer = el
+        ref: @uploadButtonContainer
         osu.trans 'users.show.edit.cover.upload.button'

       el 'div', className: 'profile-cover-uploader__info',
@@ -86,4 +92,4 @@

   $uploadButton: =>
-    $(@uploadButtonContainer).find('.js-profile-cover-upload')
+    $(@uploadButtonContainer.current).find('.js-profile-cover-upload')


watch for any change to group.members and moderators and save it if necessary

--- www/js/controllers/group.coffee
+++ www/js/controllers/group.coffee
@@ -170,6 +170,18 @@
 				.$save photo: outImg
 				.catch $log.error

+		saveGroup = (newValue, oldValue) ->
+			filter = (list) ->
+				list = _.map list, (item) ->
+					_.pick item, 'email'
+				list = _.sortBy list, 'email'
+			newValue = filter newValue
+			oldValue = filter oldValue
+			if not _.isEqual newValue, oldValue
+				model.$save().catch $log.error
+		$scope.$watch 'model.moderators', saveGroup, true
+		$scope.$watch 'model.members', saveGroup, true
+
 .filter 'groupFilter', ->
 		(collection, search) ->
 			if search


chore(refactor): ensure edit forms get clone

--- vue/src/mixins/poll_modal.coffee
+++ vue/src/mixins/poll_modal.coffee
@@ -16,14 +16,14 @@
       EventBus.$emit('openModal',
                       component: 'PollCommonEditVoteModal',
                       props: {
-                        stance: stance
+                        stance: stance.clone()
                       })

     openEditPollModal: (poll) ->
       EventBus.$emit('openModal',
                       component: 'PollCommonEditModal',
                       props: {
-                        poll: poll
+                        poll: poll.clone()
                       })

     openPollOutcomeModal: (outcome) ->


Run delete post action after a file/folder delete

--- client/landing/app/MainApp/filetree/controllers/findertreecontroller.coffee
+++ client/landing/app/MainApp/filetree/controllers/findertreecontroller.coffee
@@ -215,18 +215,22 @@

   confirmDelete:(nodeView, event)->

+    extension = nodeView.data?.getExtension() or null
+
     if @selectedNodes.length > 1
       new NFinderDeleteDialog {},
         items     : @selectedNodes
         callback  : (confirmation)=>
           @deleteFiles @selectedNodes if confirmation
           @setKeyView()
+          @runPostActions 'delete', extension
     else
       @beingEdited = nodeView
       nodeView.confirmDelete (confirmation)=>
         @deleteFiles [nodeView] if confirmation
         @setKeyView()
         @beingEdited = null
+        @runPostActions 'delete', extension

   deleteFiles:(nodes, callback)->


:memo: :lipstick:

:memo: :lipstick:

--- src/editor.coffee
+++ src/editor.coffee
@@ -975,8 +975,8 @@
   ###
   Section: Undo Operations
   ###
+
   # Public: Undo the last change.
-
   undo: ->
     @getCursor().needsAutoscroll = true
     @buffer.undo(this)


:memo: Mention packages instead of extension

--- src/editor.coffee
+++ src/editor.coffee
@@ -18,7 +18,7 @@
 # if you type in either buffer it immediately appears in both but if you scroll
 # in one it doesn't scroll the other.
 #
-# Almost all extension will interact primiarily with this class as it provides
+# Almost all packages will interact primiarily with this class as it provides
 # access to objects you'll most commonly interact with. To access it you'll
 # want to register a callback on {WorkspaceView} which will be fired once for every
 # existing {Editor} as well as any future {Editor}s.


Starting to fill out abstract entity class

--- src/entity.coffee
+++ src/entity.coffee
@@ -2,6 +2,67 @@
 # An entity belongs to a scene.

 class Kona.Entity
-  constructor: (opts) ->
-    Kona.debug "entity superconstructor called!"
-    # TODO: what to put here?
+  constructor: (opts={}) ->
+    @solid = true
+
+    @position =
+      x: opts.x || 0
+      y: opts.y || 0
+
+    @direction =
+      dx: opts.dx || 0
+      dy: opts.dy || 0
+
+    @box =
+      width:  opts.width   || 0
+      height: opts.height || 0
+
+    # TODO: Kona.Sprite /sheet ?
+    @sprite = new Image()
+    @sprite.src = ''
+
+  # Punt if not defined in child class
+  update: ->
+  draw: ->
+
+  # Standard edge coordinates
+  top:    -> @position.y
+  bottom: -> @position.y + @box.height
+  left:   -> @position.x
+  right:  -> @position.x + @box.width
+
+  # Edge coordinates accounting for current motion
+  futureTop:    -> @position.y + @direction.dy
+  futureBottom: -> @position.y + @direction.dy + @box.height
+  futureLeft:   -> @position.x + @direction.dx
+  futureRight:  -> @position.x + @direction.dx + @box.width
+
+  # onSuface = ->
+
+  # function intersecting(a, b) {
+  #        return !(
+  #            ((a.y + a.height) < (b.y)) ||
+  #            (a.y > (b.y + b.height))   ||
+  #            ((a.x + a.width) < b.x)    ||
+  #            (a.x > (b.x + b.width))
+  #        );
+  #     }
+  intersecting: (e) ->
+    if e?
+      test = !(
+        (@bottom() < e.top())    ||
+        (@top()    > b.bottom()) ||
+        (@right    < e.left())   ||
+        (@left()   > e.right())
+      )
+
+    if test
+      Kona.debug "intersecting"
+      return true
+
+  stop: (axis) ->
+    # TODO: factor out accepted axes. Enforce?
+    if axis?
+      _.contains(['dx', 'dy'], axis) || throw new Error("Axis #{axis} not recognized")
+      @direction[axis] = 0
+


Some errors were not being exported.

Some errors were not being exported.

--- src/errors.coffee
+++ src/errors.coffee
@@ -27,24 +27,24 @@
 class AuthKeyError extends CogsError
   constructor: (message, cause) -> super message, cause

-class PubSubError extends CogsError
-  constructor: (message, cause, statusCode, details) ->
-    super message, cause, statusCode, details
-
 class PubSubFailureResponse extends PubSubError
   constructor: (message, cause, statusCode, details, @record) ->
     super message, cause, statuscode, details

 class ApiError extends CogsError
 class InfoError extends CogsError
+class PubSubError extends CogsError
 class ToolsError extends CogsError

 module.exports =
   ApiError: ApiError
+  AuthKeyError: AuthKeyError
   CogsError: CogsError
   ConfigError: ConfigError
   InfoError: InfoError
   MonitorError: MonitorError
+  PubSubError: PubSubError
+  PubSubFailureResponse: PubSubFailureResponse
+  PushError: PushError
   TimeoutError: TimeoutError
   ToolsError: ToolsError
-  AuthKeyError: AuthKeyError


reactivity: chatinput: helpers code cleanup

--- client/activity/lib/components/chatinputwidget/helpers.coffee
+++ client/activity/lib/components/chatinputwidget/helpers.coffee
@@ -1,3 +1,5 @@
+textHelpers = require 'activity/util/textHelpers'
+
 module.exports = helpers =

   getCursorPosition: (textInput) -> textInput.selectionStart
@@ -9,48 +11,10 @@
     textInput.setSelectionRange position, position

-  getTextBeforeCursor: (textInput) ->
-
-    position = helpers.getCursorPosition textInput
-    value    = textInput.value
-
-    return value.substring 0, position
-
-
-  getLastWord: (str) ->
-
-    matchResult = str.match /([^\s]+)$/
-    return matchResult?[1]
-
-
-  getCurrentWord: (textInput) ->
-
-    textBeforeCursor = helpers.getTextBeforeCursor textInput
-    lastWord         = helpers.getLastWord textBeforeCursor
-
-    return lastWord
-
-
-  insertDropboxItem: (textInput, item) ->
-
-    textBeforeCursor  = helpers.getTextBeforeCursor textInput
-    textToReplace     = helpers.getLastWord textBeforeCursor
-    startReplaceIndex = textBeforeCursor.lastIndexOf textToReplace
-    endReplaceIndex   = helpers.getCursorPosition textInput
-
-    value             = textInput.value
-    textBeforeCursor  = value.substring(0, startReplaceIndex)
-    textBeforeCursor += item
-    cursorPosition    = textBeforeCursor.length
-    newValue          = textBeforeCursor + value.substring endReplaceIndex
-
-    return { value : newValue, cursorPosition }
-
-
   replaceWordAtPosition: (value, position, word) ->

     textBeforePosition = value.substring 0, position
-    textToReplace      = helpers.getLastWord textBeforePosition
+    textToReplace      = textHelpers.getLastWord textBeforePosition
     startReplaceIndex  = textBeforePosition.lastIndexOf textToReplace
     endReplaceIndex    = position


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/follow.coffee
+++ src/follow.coffee
@@ -47,5 +47,6 @@
   Object.reverseMerge I,
     direction: Point(0, 0)

+
   follow: (obj) ->
     I.direction = obj.position().subtract(self.position()).norm()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/follow.coffee
+++ src/follow.coffee
@@ -5,7 +5,7 @@
 The calculated direction is based on the center point of
 each object.

-This method relies on both objects having `position` methods.
+This method relies on both objects having position` methods.
 All GameObjects have this method by default.


Added sub_comments_count in frontend

Added sub_comments_count in frontend

--- core/app/backbone/views/sub_comments/sub_comments_view.coffee
+++ core/app/backbone/views/sub_comments/sub_comments_view.coffee
@@ -130,4 +130,10 @@
     @subCommentsListRegion.close()

   updateLink: ->
-    @$(".js-sub-comments-link").text "Comments" # Add comment count here
+    count = @model.get('sub_comments_count')
+    count_str = ""
+
+    if count
+      count_str = " (#{count})"
+
+    @$(".js-sub-comments-link").text "Comments#{count_str}"


Use KeymapManager::findKeyBindings

Use KeymapManager::findKeyBindings

--- lib/background-tips-view.coffee
+++ lib/background-tips-view.coffee
@@ -66,10 +66,10 @@

   renderTip: (str) ->
     str = str.replace /\{(.+)\}/g, (match, command) =>
-      bindings = atom.keymap.keyBindingsForCommand(command.trim())
+      bindings = atom.keymap.findKeyBindings(command: command.trim())
       binding = @getKeyBindingForCurrentPlatform(bindings)
       if binding?
-        "#{_.humanizeKeystroke(binding.keystroke)}"
+        "#{_.humanizeKeystroke(binding.keystrokes)}"
       else
         command
     str


Don't include | in bracket expression

Don't include | in bracket expression

This would previously literally match | if present in the scanned text

--- lib/bracket-matcher-view.coffee
+++ lib/bracket-matcher-view.coffee
@@ -88,9 +88,9 @@

   findAnyStartPair: (cursorPosition) ->
     scanRange = new Range([0, 0], cursorPosition)
-    startPair = _.escapeRegExp(_.keys(startPairMatches).join('|'))
-    endPair = _.escapeRegExp(_.keys(endPairMatches).join('|'))
-    combinedRegExp = new RegExp("[#{startPair}|#{endPair}]", 'g')
+    startPair = _.escapeRegExp(_.keys(startPairMatches).join(''))
+    endPair = _.escapeRegExp(_.keys(endPairMatches).join(''))
+    combinedRegExp = new RegExp("[#{startPair}#{endPair}]", 'g')
     startPairRegExp = new RegExp("[#{startPair}]", 'g')
     endPairRegExp = new RegExp("[#{endPair}]", 'g')
     startPosition = null


Update autoform-file.coffee

Update autoform-file.coffee

--- lib/client/autoform-file.coffee
+++ lib/client/autoform-file.coffee
@@ -1,3 +1,5 @@
+getCollection = undefined
+getDocument = undefined
 AutoForm.addInputType 'fileUpload',
   template: 'afFileUpload'
   valueOut: ->
@@ -5,109 +7,134 @@

 getCollection = (context) ->
   if typeof context.atts.collection == 'string'
-    FS._collections[context.atts.collection] or window[context.atts.collection]
+    return FS._collections[context.atts.collection] or window[context.atts.collection]
+  return

 getDocument = (context) ->
-  collection = getCollection context
-  id = Template.instance()?.value?.get?()
-  collection?.findOne(id)
+  collection = undefined
+  id = undefined
+  ref = undefined
+  ref1 = undefined
+  collection = getCollection(context)
+  id = if (ref = Template.instance()) != null then (if (ref1 = ref.value) != null then (if typeof ref1.get == 'function' then ref1.get() else undefined) else undefined) else undefined
+  if collection != null then collection.findOne(id) else undefined

 Template.afFileUpload.onCreated ->
-  self = @
-  @value = new ReactiveVar @data.value
+  self = undefined
+  self = this
+  @value = new ReactiveVar(@data.value)
+  @_stopInterceptValue = false
+  @_interceptValue = ((_this) ->
+    (ctx) ->
+      ref = undefined
+      t = undefined
+      if !_this._stopInterceptValue
+        t = Template.instance()
+        if t.value.get() != false and t.value.get() != ctx.value and (if (ref = ctx.value) != null then ref.length else undefined) > 0
+          t.value.set ctx.value
+          return _this._stopInterceptValue = true
+      return
+  )(this)

   @_insert = (file) ->
-    collection = getCollection self.data
-
+    `var file`
+    collection = undefined
+    ref = undefined
+    collection = getCollection(self.data)
     if Meteor.userId
       file.owner = Meteor.userId()
-
-    if typeof self.data.atts?.onBeforeInsert is 'function'
-      file = (self.data.atts.onBeforeInsert file) or file
-
+    if typeof (if (ref = self.data.atts) != null then ref.onBeforeInsert else undefined) == 'function'
+      file = self.data.atts.onBeforeInsert(file) or file
+    file = new (FS.File)(file)
+    file.uploadedFrom = Meteor.userId()
+    maxChunk = 2097152
+    FS.config.uploadChunkSize = if file.original.size < 10 * maxChunk then file.original.size / 10 else maxChunk
     collection.insert file, (err, fileObj) ->
-      if typeof self.data.atts?.onAfterInsert is 'function'
+      ref1 = undefined
+      if typeof (if (ref1 = self.data.atts) != null then ref1.onAfterInsert else undefined) == 'function'
         self.data.atts.onAfterInsert err, fileObj
-
       fileObj.update $set: metadata: owner: Meteor.userId()
-
-      if err then return console.log err
+      if err
+        return console.log(err)
       self.value.set fileObj._id

   @autorun ->
+    _id = undefined
     _id = self.value.get()
-    _id and Meteor.subscribe 'autoformFileDoc', self.data.atts.collection, _id
-
+    _id and Meteor.subscribe('autoformFileDoc', self.data.atts.collection, _id)
 Template.afFileUpload.onRendered ->
-  self = @
+  self = undefined
+  self = this
   $(self.firstNode).closest('form').on 'reset', ->
     self.value.set false
-
 Template.afFileUpload.helpers
   label: ->
     @atts.label or 'Choose file'
   removeLabel: ->
     @atts.removeLabel or 'Remove'
   value: ->
-    doc = getDocument @
-    doc?.isUploaded() and doc._id
+    doc = undefined
+    doc = getDocument(this)
+    (if doc then doc.isUploaded() else undefined) and doc._id
   schemaKey: ->
     @atts['data-schema-key']
   previewTemplate: ->
-    @atts?.previewTemplate or if getDocument(@)?.isImage() then 'afFileUploadThumbImg' else 'afFileUploadThumbIcon'
+    ref = undefined
+    ref1 = undefined
+    (if (ref = @atts) != null then ref.previewTemplate else undefined) or (if (if (ref1 = getDocument(this)) != null then ref1.isImage() else undefined) then 'afFileUploadThumbImg' else 'afFileUploadThumbIcon')
   previewTemplateData: ->
-    file: getDocument @
-    atts: @atts
+    {
+      file: getDocument(this)
+      atts: @atts
+    }
   file: ->
-    getDocument @
+    Template.instance()._interceptValue this
+    getDocument this
   removeFileBtnTemplate: ->
-    @atts?.removeFileBtnTemplate or 'afFileRemoveFileBtnTemplate'
+    ref = undefined
+    (if (ref = @atts) != null then ref.removeFileBtnTemplate else undefined) or 'afFileRemoveFileBtnTemplate'
   selectFileBtnTemplate: ->
-    @atts?.selectFileBtnTemplate or 'afFileSelectFileBtnTemplate'
+    ref = undefined
+    (if (ref = @atts) != null then ref.selectFileBtnTemplate else undefined) or 'afFileSelectFileBtnTemplate'
   selectFileBtnData: ->
-    label: @atts.label or 'Choose file'
-    accepts: @atts.accepts
+    {
+      label: @atts.label or 'Choose file'
+      accepts: @atts.accepts
+    }
   uploadProgressTemplate: ->
-    @atts?.uploadProgressTemplate or 'afFileUploadProgress'
-
+    ref = undefined
+    (if (ref = @atts) != null then ref.uploadProgressTemplate else undefined) or 'afFileUploadProgress'
 Template.afFileUpload.events
-  "dragover .js-af-select-file": (e) ->
+  'dragover .js-af-select-file': (e) ->
     e.stopPropagation()
     e.preventDefault()
-
-  "dragenter .js-af-select-file": (e) ->
+  'dragenter .js-af-select-file': (e) ->
     e.stopPropagation()
     e.preventDefault()
-
-  "drop .js-af-select-file": (e, t) ->
+  'drop .js-af-select-file': (e, t) ->
     e.stopPropagation()
     e.preventDefault()
-    t._insert new FS.File e.originalEvent.dataTransfer.files[0]
-
+    t._insert new (FS.File)(e.originalEvent.dataTransfer.files[0])
   'click .js-af-remove-file': (e, t) ->
     e.preventDefault()
     t.value.set false
-
   'fileuploadchange .js-file': (e, t, data) ->
-    t._insert new FS.File data.files[0]
-
-Template.afFileUploadThumbImg.helpers
-  url: ->
-    @file.url store: @atts.store
-
+    t._insert new (FS.File)(data.files[0])
+Template.afFileUploadThumbImg.helpers url: ->
+  @file.url store: @atts.store
 Template.afFileUploadThumbIcon.helpers
   url: ->
     @file.url store: @atts.store
   icon: ->
     switch @file.extension()
       when 'pdf'
-        'file-pdf-o'
+        return 'file-pdf-o'
       when 'doc', 'docx'
-        'file-word-o'
+        return 'file-word-o'
       when 'ppt', 'avi', 'mov', 'mp4'
-        'file-powerpoint-o'
+        return 'file-powerpoint-o'
       else
-        'file-o'
-
+        return 'file-o'
+    return
 Template.afFileSelectFileBtnTemplate.onRendered ->
   @$('.js-file').fileupload()


Fixes #79 - json: cannot unmarshal number

--- node_modules_koding/processes-monitor/processes-monitor.coffee
+++ node_modules_koding/processes-monitor/processes-monitor.coffee
@@ -24,7 +24,7 @@
           heapTotal : Math.floor((process.memoryUsage().heapTotal)/(1024*1024))
           heapUsed  : Math.floor((process.memoryUsage().heapUsed)/(1024*1024))
           unit      : 'MB'
-        uptime : process.uptime()
+        uptime : Math.floor process.uptime()

       try process.send? data
       catch e


Dispatch el events on collapse, expand.

Dispatch el events on collapse, expand.

--- app/assets/javascripts/ample_assets/classes/ample_assets.js.coffee
+++ app/assets/javascripts/ample_assets/classes/ample_assets.js.coffee
@@ -222,12 +222,14 @@
       el.animate {height: @options.collapsed_height}, "fast", =>
         @collapse()
         @options.onCollapse()
+        el.trigger('collapse')
     else
       @options.expanded = true
       $('body').animate {'padding-bottom': @options.expanded_height}, "fast"
       el.animate {height: @options.expanded_height}, "fast", =>
         @expand()
         @options.onExpand()
+        el.trigger('expand')

   # Loads contents of page identified by `i`
   load: (i) ->


one way of doing confirms

one way of doing confirms

--- app/assets/javascripts/effective_datatables/bulk_actions.js.coffee
+++ app/assets/javascripts/effective_datatables/bulk_actions.js.coffee
@@ -5,6 +5,25 @@

   $wrapper.find("input[data-role='bulk-actions']").prop('checked', false)
   toggleDropdown($wrapper)
+
+$(document).on 'mousedown', ".dataTables_wrapper .buttons-bulk-actions [data-confirm]", (event) ->
+  $obj = $(event.currentTarget)
+  return if $obj.data('confirmed')
+
+  $wrapper = $obj.closest('.dataTables_wrapper')
+  selected = $wrapper.find("input[data-role='bulk-action']:checked").length
+
+  unless $obj.data('bulk-action-original-confirm')
+    $obj.data('bulk-action-original-confirm', $obj.data('confirm'))
+
+  newConfirm = $obj.data('bulk-action-original-confirm') + "\n\n"
+
+  if selected == 1
+    newConfirm += "This action will affect #{selected} item."
+  else
+    newConfirm += "This action will affect #{selected} items."
+
+  $obj.attr('data-confirm', newConfirm)

 $(document).on 'change', ".dataTables_wrapper input[data-role='bulk-actions']", (event) ->
   $wrapper = $(event.currentTarget).closest('.dataTables_wrapper')


fixed multi condition bug

fixed multi condition bug

--- app/assets/javascripts/hanuman/hanuman-conditional-logic.js.coffee
+++ app/assets/javascripts/hanuman/hanuman-conditional-logic.js.coffee
@@ -12,9 +12,9 @@
       $(rules).each ->
         rule = this
         matchType = rule.match_type
+
         $(rule.conditions).each ->
-          condition = this
-          conditionQuestionId = condition.question_id
+          conditionQuestionId = this.question_id
           # the container for the rule element(s), could be a single element contained in form-container-entry-item or multiple in form-container-repeater
           $ruleContainer = $ruleContainer
           # the condition container
@@ -37,7 +37,7 @@
             problemWithCL = true

           # deal with any condition, once we get a hide_questions = false then we dont need to run through the rules
-          hideQuestions = self.setHideQuestions(condition, $conditionElement)
+          hideQuestions = self.setHideQuestions(this, $conditionElement)

           ancestorId = rule.question_id
@@ -50,7 +50,7 @@
             if $conditionElement.is(":checkbox")
               # limit binding of each checkbox if data-label-value and answer are the same-kdh
               if rule.type != 'Hanuman::CalculationRule'
-                $conditionElement = $conditionContainer.find(".form-control[data-label-value='" + condition.answer.replace("/","\\/").replace("'","\\'") + "']")
+                $conditionElement = $conditionContainer.find(".form-control[data-label-value='" + this.answer.replace("/","\\/").replace("'","\\'") + "']")

               self.bindConditions($conditionElement, rule, $ruleContainer)
             else
@@ -69,6 +69,10 @@
             self.updateCalculation(rule, $ruleContainer)
           else
             self.checkConditionsAndHideShow(rule.conditions, ancestorId, $ruleContainer, $ruleContainer, inRepeater, matchType, rule)
+
+          # need the direct returns so that the nested loops don't get broken when they're compiled to JS
+          return
+        return

     if problemWithCL
       e = new Error("conditional Logic # findRules")


flip arrow on drag assignment groups

flip arrow on drag assignment groups

fixes CNVS-9092

test plan
 - enable draft state
 - navigate to assignments show page
 - drag an assignment group
     - the little arrow should turn to the right
 - release the assignment group
     - the little arrow should flip back down
 - collapse an assignment group
 - drag the group
     - the little arrow should not turn
 - release the assignment group
     - the little arrow should not turn
     - the assignment group should stay collapsed

Change-Id: I6b50802a35a163603c65a2c592ef14cab6667178
Reviewed-on: https://gerrit.instructure.com/25754
QA-Review: Caleb Guanzon <54fa1f30d451e4f3c341a8f3c47c9215fd0be9c6@instructure.com>
Tested-by: Jenkins <d95b56ce41a2e1ac4cecdd398defd7414407cc08@instructure.com>
Reviewed-by: Simon Williams <088e16a1019277b15d58faf0541e11910eb756f6@instructure.com>
Product-Review: Simon Williams <088e16a1019277b15d58faf0541e11910eb756f6@instructure.com>

--- app/coffeescripts/views/assignments/AssignmentGroupListView.coffee
+++ app/coffeescripts/views/assignments/AssignmentGroupListView.coffee
@@ -79,13 +79,32 @@
       @$list.on('sortstart', @collapse)
       @$list.on('sortstop', @expand)

+    handleExtraClick: (e) =>
+      e.stopImmediatePropagation()
+      $(e.target).off('click', @handleExtraClick)
+
     collapse: (e, ui) =>
-      id = ui.item.children(":first").data('id')
-      ui.item.find("#assignment_group_#{id}_assignments").slideUp(100)
+      item = ui.item
+      id = item.children(":first").attr('data-id')
+      item.find("#assignment_group_#{id}_assignments").slideUp(100)
       ui.item.css("height", "auto")
+      arrow = item.find('i').first()
+      arrow.removeClass('icon-mini-arrow-down').addClass('icon-mini-arrow-right')

     expand: (e, ui) =>
-      id = ui.item.children(":first").data('id')
-      ag = @collection.findWhere id: parseInt(id)
+      item = ui.item
+      $toggler = item.find('.element_toggler').first()
+      # FF triggers an extra click when you drop the item, so we want to handle it here
+      $toggler.on('click', @handleExtraClick)
+
+      # remove the extra click handler for browsers that don't trigger the extra click
+      setTimeout(=>
+        $toggler.off('click', @handleExtraClick)
+      , 50)
+
+      id = item.children(":first").attr('data-id')
+      ag = @collection.findWhere id: id
       if ag && ag.groupView.shouldBeExpanded()
-        ui.item.find("#assignment_group_#{id}_assignments").slideDown(100)
+        item.find("#assignment_group_#{id}_assignments").slideDown(100)
+        arrow = item.find('i').first()
+        arrow.addClass('icon-mini-arrow-down').removeClass('icon-mini-arrow-right')


Added document.location, which mirrors window.location.

--- lib/server/browser/index.coffee
+++ lib/server/browser/index.coffee
@@ -125,7 +125,6 @@
         # an http request.
         @window.addEventListener 'load', () =>
             postload(@window) if postload?
-            @emit('load') # TODO: deprecate
             @emit('PageLoaded')
             process.nextTick(() => @emit('afterload'))

@@ -145,11 +144,15 @@
             parser : HTML5)
         document.parentWindow = @window
         @window.document = document
+        document.__defineGetter__ 'location', () =>
+            return @window.__location
+        document.__defineSetter__ 'location', (href) =>
+            return @window.__location = new Location(href)

         Request {uri: url}, (err, response, html) =>
             throw err if err
             # Fire window load event once document is loaded.
-            document.addEventListener 'load', (ev) =>
+            document.addEventListener 'DOMContentLoaded', (ev) =>
                 ev = document.createEvent('HTMLEvents')
                 ev.initEvent('load', false, false)
                 @window.dispatchEvent(ev)


delete unused declare imports

delete unused declare imports

--- lib/web-shortcutter-view.coffee
+++ lib/web-shortcutter-view.coffee
@@ -1,6 +1,4 @@
 {SelectListView, $, $$} = require 'atom-space-pen-views'
-{match} = require 'fuzzaldrin'
-fuzzaldrinPlus = require 'fuzzaldrin-plus'
 fs = require 'fs'
 shell = require 'shell'


fixed resetting locations list after form is cleared

--- app/assets/javascripts/species/views/search_form/geo_entities_search_button.js.coffee
+++ app/assets/javascripts/species/views/search_form/geo_entities_search_button.js.coffee
@@ -31,12 +31,12 @@
   ).property("selectedGeoEntities.@each")

   click: (event) ->
-    if (@get('controller.isSearchContextDocuments') &&
-    @get('taxonConceptQuery') != @get('taxonConceptQueryLastCheck') &&
-    @get('taxonConceptQuery.length') >= 3)
+    if @get('controller.isSearchContextDocuments') &&
+    @get('taxonConceptQuery') != @get('taxonConceptQueryLastCheck')
       @set('taxonConceptQueryLastCheck', @get('taxonConceptQuery'))
+      if @get('taxonConceptQuery.length') >= 3
+        query = @get('taxonConceptQuery')
       # we're in the E-Library search, need to check if
       # filtering by taxon is required for locations
-      @get('controller.geoEntities').reload(@get('taxonConceptQuery'))
+      @get('controller.geoEntities').reload(query)
     @handlePopupClick(event)
-


app/storage: expose default group name (bucket) :cat:

--- client/app/lib/appstorage.coffee
+++ client/app/lib/appstorage.coffee
@@ -1,5 +1,5 @@
-kd       = require 'kd'
-whoami   = require './util/whoami'
+kd         = require 'kd'
+whoami     = require './util/whoami'

 module.exports =

@@ -7,7 +7,7 @@

   @DEFAULT_VERSION: '1.0'

-  DEFAULT_GROUP_NAME = 'bucket'
+  @DEFAULT_GROUP_NAME = 'bucket'

   constructor: (appId, version = AppStorage.DEFAULT_VERSION) ->

@@ -56,7 +56,7 @@
     @emit 'ready'

-  fetchValue: (key, callback, group = DEFAULT_GROUP_NAME, force = no) ->
+  fetchValue: (key, callback, group = AppStorage.DEFAULT_GROUP_NAME, force = no) ->

     @reset()

@@ -65,14 +65,14 @@
     , force

-  getValue: (key, group = DEFAULT_GROUP_NAME) ->
+  getValue: (key, group = AppStorage.DEFAULT_GROUP_NAME) ->

     return unless @_storage
     return if @_storageData[group]?[key]? then @_storageData[group][key]
     return if @_storage[group]?[key]?     then @_storage[group][key]

-  setValue: (key, value, callback, group = DEFAULT_GROUP_NAME) ->
+  setValue: (key, value, callback, group = AppStorage.DEFAULT_GROUP_NAME) ->

     pack = @zip key, group, value

@@ -91,7 +91,7 @@
       @setValue key, value  unless (@getValue key)?

-  unsetKey: (key, callback, group = DEFAULT_GROUP_NAME) ->
+  unsetKey: (key, callback, group = AppStorage.DEFAULT_GROUP_NAME) ->

     pack = @zip key, group, 1


Add todo.

Add todo.

--- app/assets/javascripts/application/seeds_controller.js.coffee
+++ app/assets/javascripts/application/seeds_controller.js.coffee
@@ -12,6 +12,7 @@
     @progressBar.start()
   didLoadCategories: (index) ->
     logger.verbose 'SeedsController#didLoadCategories', index
+    # TODO use callback to do the delegate call, or return promise
     @store.updateCategories(index)
     if @delegate && @delegate.seedsSyncControllerDidSyncCategories
       @delegate.seedsSyncControllerDidSyncCategories()


Remove unused $scope attributes from Checkout controller

--- app/assets/javascripts/sprangular/controllers/checkout.coffee
+++ app/assets/javascripts/sprangular/controllers/checkout.coffee
@@ -15,10 +15,7 @@

   user = Account.user

-  $scope.countries = countries
   $scope.order = order
-  $scope.processing = false
-  $scope.user = user
   $scope.secure = $location.protocol() == 'https'
   $scope.currencySymbol = Env.currency.symbol


recaptcha in modal...makes the form look cleaner and easier

--- coffee/jquery.contactform.coffee
+++ coffee/jquery.contactform.coffee
@@ -10,6 +10,7 @@
   recaptcha_verification_url: "/recaptcha_verification.php"
   recipients: []
   recaptcha_placeholder_text: "Bitte gib die 2 Worte ein..."
+  button_text: "Absenden"
   button_sending_text: "Wird Gesendet..."
   button_sent_text: "Gesendet!"
   form_el: null
@@ -17,6 +18,9 @@
   mandrill: null

 methods =
+  #
+  # init
+  #
   init: (options) ->
     # set options
     $.extend config, options
@@ -24,31 +28,68 @@
     # set the form element if form exists in DOM
     if $(this).parent().length > 0
       config.form_el = $(this)
-      config.btn_submit = $("[type=submit]",config.form_el)

       try
         methods.init_mandrill()
         methods.init_recaptcha()
         methods.bind_submit_handler()
-        methods.set_button_states()
       catch error
-        console.log error
+        console.log error if console?
     else
       console.log "you need to define a form element!" if console?
-
+
+  #
   # init mandrill
+  #
   init_mandrill: ->
     if mandrill?
       config.mandrill = new mandrill.Mandrill config.mandrill_key
     else
       $.error "the perfect contactform needs the Mandrill API"

+  #
   # init recaptcha
+  #
   init_recaptcha: ->
     if Recaptcha?
-      # insert custom recaptcha markup
-      recaptcha_markup = '

 <button id="recaptcha_reload" class="btn btn-default"> </button>

 <input type="text" id="recaptcha_response_field" class="form-control" placeholder="#{config.recaptcha_placeholder_text}" name="recaptcha_response_field" />

'
-      config.btn_submit.nearest(".form-group").before recaptcha_markup
+      # define the markup
+      recaptcha_modal = """

+

+

+

+                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+
Modal title

+

+

+

+

+

+

+

+                        <button id="recaptcha_reload" class="btn btn-default"> </button>
+

+

+                    <input type="text" id="recaptcha_response_field" class="form-control" placeholder="#{config.recaptcha_placeholder_text}" name="recaptcha_response_field" />
+

+

+

+

+                <button type="button" class="btn btn-primary" id="btn_send_contactform">#{config.button_text}</button>
+

+

+

+
"""
+
+      config.form_el.after recaptcha_modal
+
+      # set the button states
+      methods.set_button_states()
+
+      # bind click-event to button
+      config.btn_submit = $("#btn_send_contactform")
+      config.btn_submit.click (e) ->
+        e.preventDefault()
+        methods.send_contactform()

       # load recaptcha
       Recaptcha.create recaptcha_pubkey,
@@ -62,55 +103,71 @@
     else
       $.error "the perfect contactform needs the ReCaptcha API"

+  #
   # set the submit button states
+  #
   set_button_states: ->
     config.btn_submit.attr
       "data-sending-text": config.button_sending_text
       "data-sent-text": config.button_sent_text

+  #
+  # open the modal
+  #
+  open_modal: ->
+    $("#modal_recaptcha").modal "show"
+
+  #
+  # verify recaptcha and send form
+  #
+  send_contactform: ->
+    # bring submit button into sending state
+    config.btn_submit.button "sending"
+
+    # define params for recaptcha verification
+    recaptcha_params =
+      recaptcha_response_field: Recaptcha.get_response()
+      recaptcha_challenge_field: Recaptcha.get_challenge()
+
+    # check recaptcha
+    $.post config.recaptcha_verification_url, recaptcha_params, (response) ->
+      if response is 1
+        # set mandrill params
+        mandrill_params =
+          message:
+            from_email: $("#input_email").val()
+            from_name: $("#input_name").val()
+            to: config.recipients
+            subject: $("#input_subject").val()
+            text: $("#input_message").val()
+
+        # send the message
+        m.messages.send mandrill_params, (res) ->
+          console.log res if console?
+          # output message
+
+          # set button into sent state
+          config.btn_submit.button "sent"
+
+          # reload recaptcha
+          Recaptcha.reload()
+
+          # reset the form
+          config.form_el[0].reset()
+        , (err) ->
+          console.log err if console?
+      else
+        console.log "the recaptcha solution is wrong" if console?
+
+  #
   # bind the forms submit event
+  #
   bind_submit_handler: ->
     config.form_el.submit (e) ->
       # prevent form from sending
       e.preventDefault()
-
-      # bring submit button into sending state
-      config.btn_submit.button "sending"
-
-      # define params for recaptcha verification
-      recaptcha_params =
-        recaptcha_response_field: Recaptcha.get_response()
-        recaptcha_challenge_field: Recaptcha.get_challenge()
-
-      # check recaptcha
-      $.post config.recaptcha_verification_url, recaptcha_params, (response) ->
-        if response is 1
-          # set mandrill params
-          mandrill_params =
-            message:
-              from_email: $("#input_email").val()
-              from_name: $("#input_name").val()
-              to: config.recipients
-              subject: $("#input_subject").val()
-              text: $("#input_message").val()
-
-          # send the message
-          m.messages.send mandrill_params, (res) ->
-            console.log res if console?
-            # output message
-
-            # set button into sent state
-            config.btn_submit.button "sent"
-
-            # reload recaptcha
-            Recaptcha.reload()
-
-            # reset the form
-            config.form_el[0].reset()
-          , (err) ->
-            console.log err if console?
-        else
-          console.log "the recaptcha solution is wrong" if console?
+      # open the modal
+      methods.open_modal()

 $.fn.contactform = (method,options...) ->


Environment: log both errors and result for build

--- client/Environments/views/scene/environmentmachineitem.coffee
+++ client/Environments/views/scene/environmentmachineitem.coffee
@@ -40,8 +40,7 @@
           kloud = KD.singletons.kontrol.getKite {
             name:"kloud", environment:"vagrant"
           }
-          kloud.build machineId: machine._id, ->
-            log ">>>>>>", arguments
+          kloud.build(machineId: machine._id).then(log, warn)

       'Re-initialize VM'  :
         disabled          : KD.isGuest()


activity: add render ThreadSidebar method

--- client/activity/lib/components/channelthreadpane/index.coffee
+++ client/activity/lib/components/channelthreadpane/index.coffee
@@ -4,6 +4,7 @@
 ActivityFlux   = require 'activity/flux'
 immutable      = require 'immutable'
 classnames     = require 'classnames'
+ThreadSidebar  = require 'activity/components/threadsidebar'

 module.exports = class ChannelThreadPane extends React.Component

@@ -63,7 +64,11 @@
       channelThread : @state.channelThread

-  renderChannelSidebar: -> null
+  renderSidebar: ->
+    <ThreadSidebar
+      channelThread={@state.channelThread}
+      popularMessages={@state.popularMessages}
+      channelParticipants={@state.channelParticipants}/>

   getClassName: ->


Renamed last_visited_url to background_page_url

--- core/app/backbone/modules/discussion_modal_on_frontend.coffee
+++ core/app/backbone/modules/discussion_modal_on_frontend.coffee
@@ -1,18 +1,18 @@
 FactlinkApp.module "DiscussionModalOnFrontend", (DiscussionModalOnFrontend, MyApp, Backbone, Marionette, $, _) ->

-  last_visited_url = null
+  background_page_url = null

   DiscussionModalOnFrontend.addInitializer ->
     FactlinkApp.vent.on 'load_url', ->
       DiscussionModalOnFrontend.closeDiscussion()

     FactlinkApp.vent.on 'close_discussion_modal', ->
-      Backbone.history.navigate last_visited_url, false
+      Backbone.history.navigate background_page_url, false
       DiscussionModalOnFrontend.closeDiscussion()

   DiscussionModalOnFrontend.openDiscussion = (fact, url) ->
     Backbone.history.navigate fact.get('url'), false
-    last_visited_url = url if url?
+    background_page_url = url if url?
     newClientModal = new DiscussionModalContainer
     FactlinkApp.discussionModalRegion.show newClientModal
     newClientModal.mainRegion.show new NDPDiscussionView model: fact


Remove if statements from parser selection

--- client/models.coffee
+++ client/models.coffee
@@ -12,12 +12,9 @@
         source: source
         target: @

-  getHtml: ->
-    mode = @get "mode"
-    code = @get "code"
-    if mode == "html"
-      return code
-    else if mode == "jade"
+  parsers:
+    html: (html) -> html
+    jade: (code) ->
       jade = require('jade')
       try
         return jade.compile(code)()
@@ -28,8 +25,12 @@
           <pre>#{ e.message }</pre>
         </div>
         """
-    else
-      return '<script type="text/javascript">alert("should not happen");</script>'
+
+  getHtml: ->
+    parser = @parsers[@get "mode"]
+    parser = @parsers.html unless parser
+    parser @get "code"
+

   getPresentationURL: ->
     "/#{@get "id"}"


Delete unused Angular service ofnConfirmHandler

--- app/assets/javascripts/admin/services/confirm_handler.js.coffee
+++ app/assets/javascripts/admin/services/confirm_handler.js.coffee
@@ -1,24 +0,0 @@
-angular.module("ofn.admin").factory "ofnConfirmHandler", (pendingChanges, $compile, $q) ->
-  return (scope, callback) ->
-    template = "

" + t('js.services.unsaved_changes_message') + "

"
-    dialogDiv = $compile(template)(scope)
-    return ->
-      if pendingChanges.changeCount(pendingChanges.pendingChanges) > 0
-        dialogDiv.dialog
-          dialogClass: "no-close"
-          resizable: false
-          height: 140
-          modal: true
-          buttons:
-            "SAVE": ->
-              dialogDiv = $(this)
-              $q.all(pendingChanges.submitAll()).then ->
-                callback()
-                dialogDiv.dialog "close"
-            "IGNORE": ->
-              callback()
-              $(this).dialog "close"
-              scope.$apply()
-        dialogDiv.dialog "open"
-      else
-        callback()


remove console.log

remove console.log

--- services/web/test/UnitTests/coffee/Project/ProjectEntityHandlerTests.coffee
+++ services/web/test/UnitTests/coffee/Project/ProjectEntityHandlerTests.coffee
@@ -505,7 +505,6 @@
 			@ProjectModel.putElement = (project_id, folder_id, doc, type, callback)-> callback(null, {path:{fileSystem:opts.path}})

 			@tpdsUpdateSender.addFile = (options)=>
-				console.log @project.name, options.project_name
 				options.project_id.should.equal project_id
 				options.path.should.equal opts.path
 				options.project_name.should.equal @project.name


bug fix

bug fix

--- app/assets/javascripts/swell_media/plugins/jquery.assetup.js.coffee
+++ app/assets/javascripts/swell_media/plugins/jquery.assetup.js.coffee
@@ -21,7 +21,7 @@
 		form_id = "new_asset_"+(assetup_counter++)

 		$('body').append("""
-		<form accept-charset="UTF-8" action="/assets?response=url&#{$.param(params)}" class="new_asset" enctype="multipart/form-data" id="#{form_id}" method="post">
+		<form accept-charset="UTF-8" action="/assets?response=url&#{$.param(params)}" class="new_asset" enctype="multipart/form-data" id="#{form_id}" method="post" style="display:none;">

<input name="utf8" type="hidden" value="✓">

 					<input name="file" type="file">
           <input name="commit" type="submit" value="Upload">


Fix a possible null error

Fix a possible null error

--- app/assets/javascripts/controllers/toolbar.controller.js.coffee
+++ app/assets/javascripts/controllers/toolbar.controller.js.coffee
@@ -45,7 +45,11 @@
   ).property('@each.isActive')

   searchString: Ember.computed('queryString', ->
-    return decodeURIComponent(this.get('queryString').replace(/\+/g, ' '))
+    queryString = this.get('queryString')
+    if queryString?
+      return decodeURIComponent(queryString.replace(/\+/g, ' '))
+    else
+      return queryString
   )

   activeStatusFilters: ((key, activeStatusFilters)->


PLATEFORM increase embed preview height...

--- app/assets/javascripts/platform/views/embed_form_view.js.coffee
+++ app/assets/javascripts/platform/views/embed_form_view.js.coffee
@@ -31,7 +31,7 @@
     params = ""
     params += "/?tagIds=#{tagIds.join(',')}" if tagIds

-    iframeCode = ""
+    iframeCode = ""

     @$('#preview').html @templates.preview(iframeCode: iframeCode)


Clean up

Clean up

--- app/assets/javascripts/react_components/todo_list/app.js.coffee
+++ app/assets/javascripts/react_components/todo_list/app.js.coffee
@@ -53,7 +53,7 @@
 stores =
   TodoStore: new TodoStore

-# Creation of a Flux instance
+# Creating a Flux instance with our stores and actions

 flux = new Fluxxor.Flux(stores, actions)


Pricing & enables

Pricing & enables

Former-commit-id: 90c6f229dff8bbc4442a5b67bd00d9486d145b7e [formerly 37fe489c861ec6f3fc7a69aa14f64028e3e3a3e9] [formerly 357b98ef0f6bbe7bf8384bbffd76feabd7f82eb7 [formerly d9bd6406749df2cb9655cd046cc84b42ac392c5d]] [formerly fde06863fcff6ee50e28dfb7a585a5a6657627fd [formerly baf9945f410061e63379c890d68fcf987ca457e9] [formerly 791955e6eb4ee938b40ef9183832dc2bf220bafa [formerly 791955e6eb4ee938b40ef9183832dc2bf220bafa [formerly 0dccbfb070a3acd15577b9f8fe999fa765c33ab5]]]]
Former-commit-id: 839b4e930c79e4ecf395467a68a59e8baf984f2b [formerly febfb355b7a83a5509322358f53dce4bbf936015] [formerly 47eedc935152d8d3555617593a437caa020853f6 [formerly acf760dff1faf870cffa6d766900d40bf0957e06]]
Former-commit-id: 7da3f83dbdcb796c9cc385c5fafcec151843e92b [formerly 71c8607f103e230b032051f9b8144c5a71719982]
Former-commit-id: 879a60e5e5dd6875d53899baa8339de0087b504f
Former-commit-id: 6dd5ec3cabe7f348aaaaa83b72c7445c7f3e0db9

--- @client/saas_landing_page.coffee
+++ @client/saas_landing_page.coffee
@@ -73,14 +73,25 @@
       save ui

     DIV null,
+
+      DIV
+        style: _.extend h1,
+          margin: '50px 0'
+
+        'Bring focused discussion to your'
+        BR null,
+        'community, organization or classroom'
+
+
       Video()
       usedFor()
+      enables()
       pricing()
       contact(@local)
       story()

-HEADER_HEIGHT = 80
+HEADER_HEIGHT = 70
 Header = ReactiveComponent
   displayName: "Header"
   render: ->
@@ -103,7 +114,7 @@
           src: asset("saas_landing_page/considerit_logo.svg")
           style:
             position: "relative"
-            top: HEADER_HEIGHT * .05 + 18
+            top: HEADER_HEIGHT * .05 + 16
             left: 0
             height: HEADER_HEIGHT * .95

@@ -133,14 +144,15 @@
               href: "#story"
               'story'

-        DIV
-          style:
-            fontSize: 24
-            fontWeight: 300
-            color: logo_red
-            position: 'absolute'
-            top: 4 + HEADER_HEIGHT
-          "for thinking together"
+        # DIV
+        #   style:
+        #     fontSize: 24
+        #     fontWeight: 300
+        #     color: logo_red
+        #     position: 'absolute'
+        #     top: 4 + HEADER_HEIGHT
+        #   "for thinking together"
+

 VIDEO_SLIDER_WIDTH = 250
@@ -153,7 +165,7 @@
     controls = fetch('video_controls')

     if !controls.playing?
-      controls.playing = true
+      controls.playing = false
       save controls

     video = DIV null,
@@ -174,7 +186,7 @@

     DIV
       style:
-        marginTop: 70
+        #marginTop: 70
         height: 756
         position: 'relative'

@@ -247,6 +259,9 @@
   drawCaptions : ->
     ui = fetch('homepage_ui')
     chapter = fetch("video_chapter")
+
+    if !chapter.text?
+      chapter.text = "Proposals often require careful thought"

     DIV
       style:
@@ -365,7 +380,19 @@

   componentDidUpdate: -> @attachToVideo()
-  componentDidMount: -> @attachToVideo()
+  componentDidMount: ->
+    @attachToVideo()
+
+    # # wait a couple seconds before playing video to give user time to
+    # # orient to homepage
+    # console.log 'SET'
+    # setTimeout =>
+    #   controls = fetch('video_controls')
+    #   controls.playing = true
+    #   save controls
+    #   @refs.video.getDOMNode().play()
+    #   console.log 'PLAY'
+    # , 1000

   attachToVideo : ->
     # we use timeupdate rather than tracks / cue changes / vtt
@@ -465,7 +492,9 @@
       marginTop: if ui.frame == 'laptop' then 30 else 60

     H1 style: h1,
-      'The first forum to function better when more people participate'
+      'The first forum to function better'
+      BR null,
+      'when more people participate'

     bullet
       point_style: 'bullet'
@@ -482,8 +511,68 @@
       strong: "Produces an interactive summary of group thought"
       body: ". Patterns of thought across the whole group can be identified. Perhaps 80% of opposers have a single con point that can be addressed!"

+enables = ->
+  DIV
+    style:
+      marginTop: 60
+
+    H1 style: h1,
+      'Creates new opportunities for...'
+
+    bullet
+      point_style: 'bullet'
+      strong: "Involving 5, 20, 100s of people"
+      body: " deliberating an issue together, without becoming overwhelming."
+
+    bullet
+      point_style: 'bullet'
+      strong: "Leading change"
+      body: """. Collect organized feedback from employees, membership, and stakeholder groups
+                 for strategic planning, process improvement, program evaluation, and other
+                 change efforts. Strong leaders create change by explaining and evolving plans.
+                 Weak leaders try to impose them.
+            """
+
+    bullet
+      point_style: 'bullet'
+      strong: "Distributing decision making"
+      body: """. Make decisions as a whole, without resorting to hierarchy. The will of a community,
+                 and the thoughts behind that will, become visible and actionable.
+            """
+
+    bullet
+      point_style: 'bullet'
+      strong: "Teaching critical thinking"
+      body: """. Students learn how to develop and express a considered opinion while listening
+                 to and engaging with other’s ideas. Works well for Common Core aligned exercises
+                 in English and Social Studies.
+            """
+

 pricing = ->
+  DIV
+    id: 'pricing'
+
+    DIV
+      style: h1
+
+      'Pricing'
+
+    DIV
+      style:
+        width: TEXT_WIDTH
+        margin: 'auto'
+
+      'We are offering free pilots for a limited time. '
+
+      A
+        style: a
+        'Contact us'
+
+      ' about getting set up. '
+      BR null
+      BR null
+      'If advanced configuration or custom design is needed, we can discuss whether compensation is necessary.'

 contact = (local) ->

@@ -640,7 +729,7 @@

           A
             style: story_link
-            href: 'https://www.dropbox.com/s/ycqfoxdl5sghaud/dissertation.pdf?dl=0'
+            href: 'https://dl.dropboxusercontent.com/u/3403211/papers/dissertation.pdf'
             "PhD dissertation"

@@ -661,7 +750,7 @@

         P null,
           """
-          Kevin Miniter joined Consider.it serindipitously in 2012. Motivated by
+          Kevin Miniter joined Consider.it serendipitously in 2012. Motivated by
           his experiencing running a ... , and his life philosophy of simply
           asking “how can I help?”
           """
@@ -828,7 +917,7 @@
               A
                 style:  _.extend {}, story_link,
                   textDecoration: 'underline'
-                href: "http://dx.doi.org/10.1080/19331681.2012.665755"
+                href: "https://dl.dropboxusercontent.com/u/3403211/papers/jitp.pdf"
                 'Facilitating Diverse Political Engagement'
               DIV
                 style: _.extend {}, small_text,
@@ -886,7 +975,7 @@
         margin: 'auto'
         color: 'white'

-      'That is our story, new friend!'
+      'That is our story, friend!'
       BR null,
       'Tell us '
       A


Remove duplicate.

Remove duplicate.

--- client/landing/app/MainApp/maincontroller/mainview.coffee
+++ client/landing/app/MainApp/maincontroller/mainview.coffee
@@ -275,7 +275,7 @@
       @profileLandingView = new KDView
         lazyDomId : 'profile-landing'

-    if @groupsEnabled()
+    if @userEnteredFromGroup()

       @groupLandingView = new KDView
         lazyDomId : 'group-landing'
@@ -296,10 +296,7 @@
           height : groupLandingContentView.getHeight() - (256)

     if isLoggedIn
-      if @userEnteredFromGroup() then @switchGroupState yes
-      else $('body').addClass "loggedIn"
-
-      if @groupsEnabled()
+      if @userEnteredFromGroup()
         @switchGroupState yes
         @mainTabView.hideHandleContainer()


Fix warning when going next

Fix warning when going next

--- views/components/ship/ship.cjsx
+++ views/components/ship/ship.cjsx
@@ -7,6 +7,7 @@

 inBattle = [false, false, false, false]
 goback = {}
+combined = false

 getStyle = (state) ->
   if state in [0..5]
@@ -80,6 +81,7 @@
           names = body.api_deck_port.map (e) -> e.api_name
           inBattle = [false, false, false, false]
           goback = {}
+          combined = body.api_combined_flag? && body.api_combined_flag > 0
         when '/kcsapi/api_req_hensei/change', '/kcsapi/api_req_hokyu/charge', '/kcsapi/api_get_member/deck', '/kcsapi/api_get_member/ship_deck', '/kcsapi/api_get_member/ship2', '/kcsapi/api_get_member/ship3', '/kcsapi/api_req_kousyou/destroyship', '/kcsapi/api_req_kaisou/powerup', '/kcsapi/api_req_nyukyo/start', '/kcsapi/api_req_nyukyo/speedchange'
           true
         # FCF
@@ -111,27 +113,30 @@
             if gobackShip != -1
               console.log "退避：#{_ships[damagedShip].api_name} 护卫：#{_ships[gobackShip].api_name}"
               goback[damagedShip] = goback[gobackShip] = true
-        when '/kcsapi/api_req_map/start'
-          deckId = parseInt(postBody.api_deck_id) - 1
-          inBattle[deckId] = true
+        when '/kcsapi/api_req_map/start', '/kcsapi/api_req_map/next'
+          if path == '/kcsapi/api_req_map/next'
+            if combined
+              deckId = 0
+              inBattle[0] = inBattle[1] = true
+            else
+              deckId = parseInt(postBody.api_deck_id) - 1
+              inBattle[deckId] = true
           {decks, states} = @state
-          {_ships} = window
-          deck = decks[deckId]
-          for shipId in deck.api_ship
-            continue if shipId == -1
-            ship = _ships[shipId]
-            if ship.api_nowhp / ship.api_maxhp < 0.250001 and !goback[shipId]
-              toggleModal '出击注意！', "Lv. #{ship.api_lv} - #{ship.api_name} 大破，请到舰队面板确认是否有应急修理要员/女神携带！"
-        when '/kcsapi/api_req_map/next'
-          {decks, states} = @state
-          {_ships} = window
-          for deck, i in decks
-            continue if states[i] != 5
+          {_ships, _slotitems} = window
+          for deckId in [0..3]
+            continue unless inBattle[deckId]
+            deck = decks[deckId]
             for shipId in deck.api_ship
               continue if shipId == -1
               ship = _ships[shipId]
               if ship.api_nowhp / ship.api_maxhp < 0.250001 and !goback[shipId]
-                toggleModal '进击注意！', "Lv. #{ship.api_lv} - #{ship.api_name} 大破，请到舰队面板确认是否有应急修理要员/女神携带！"
+                # 应急修理要员/女神
+                safe = false
+                for slotId in ship.api_slot
+                  continue if slotId == -1
+                  safe = true if _slotitems[slotId].api_type[3] is 14
+                if !safe
+                  toggleModal '注意！', "Lv. #{ship.api_lv} - #{ship.api_name} 大破，可能有击沉风险！"
         else
           flag = false
       return unless flag


Added list records

Added list records

--- route53.coffee
+++ route53.coffee
@@ -79,4 +79,9 @@
         return
       records = data.ResourceRecordSets
       for record in records
-        msg.send "Name: #{record.Name}\n#{record.Type}"
+        message ="Name: #{record.Name}\nRecord Type: #{record.Type}\nTTL: #{record.TTL}"
+        for rec in record.ResourceRecords
+          message += "\n#{rec.Value}"
+        if record.AliasTarget
+          message += "\nDNSName: #{record.AliasTarget.DNSName}"
+        msg.send "#{message}"


--- client/activity/lib/components/channelthreadpane/index.coffee
+++ client/activity/lib/components/channelthreadpane/index.coffee
@@ -38,11 +38,10 @@
       channelParticipants   : immutable.List()

-
-  componentDidMount: -> reset @props
+  componentDidMount: -> reset @props, @state

-  componentWillReceiveProps: (nextProps) -> reset nextProps
+  componentWillReceiveProps: (nextProps) -> reset nextProps, @state

   renderHeader: ->
@@ -81,22 +80,39 @@

 React.Component.include.call ChannelThreadPane, [KDReactorMixin]

-reset = (props) ->
+reset = (props, state) ->

   { channelName, postId } = props.routeParams
   { thread, channel: channelActions, message: messageActions } = ActivityFlux.actions

+<<<<<<< HEAD
   if channelName
     channelActions.loadChannel('public', channelName).then ({ channel }) ->
       thread.changeSelectedThread channel.id
+=======
+  # if there is no channel in the url, and there is no selected channelThread,
+  # then load public.
+  unless channelName
+    unless state.channelThread
+      channelName = 'public'
+
+  if channelName
+    channelActions.loadChannel('public', channelName).then ({ channel }) ->
+      thread.changeSelectedThread channel.id
+      channelActions.loadPopularMessages channel.id
+>>>>>>> activity: improve channels route handling
       channelActions.loadParticipants channel.id, channel.participantsPreview

       if postId
         messageActions.changeSelectedMessage postId
       else
         messageActions.changeSelectedMessage null
+<<<<<<< HEAD

   else
+=======
+  else if not state.channelThread
+>>>>>>> activity: improve channels route handling
     thread.changeSelectedThread null


SidebarOwnMachinesList: Update title and cssClass.

--- client/app/lib/activity/sidebar/sidebarownmachineslist.coffee
+++ client/app/lib/activity/sidebar/sidebarownmachineslist.coffee
@@ -8,9 +8,9 @@

   constructor: (options = {}, data) ->

-    options.title       = 'VMs'
+    options.title       = 'Your VMs'
     options.hasPlusIcon = yes
-    options.cssClass    = 'my-machines-list'
+    options.cssClass    = 'my-machines'

     super options, data


Remove console.log

Remove console.log

--- index.cjsx
+++ index.cjsx
@@ -184,7 +184,6 @@
     handleNextExpChange: (e) ->
       @handleExpChange @state.currentLevel, e.target.value, @state.goalLevel, @state.mapValue, @state.mapPercent
     handleGoalLevelChange: (e) ->
-      console.log e.target.value
       @handleExpChange @state.currentLevel, @state.nextExp, e.target.value, @state.mapValue, @state.mapPercent
     handleExpMapChange: (e) ->
       @handleExpChange @state.currentLevel, @state.nextExp, @state.goalLevel, e.target.value, @state.mapPercent


Add nickname

Add nickname

--- index.cjsx
+++ index.cjsx
@@ -122,7 +122,7 @@
   # Drop ship report
   window.addEventListener 'battle.result', async (e) ->
     {rank, boss, map, mapCell, quest, enemy, dropShipId, enemyShipId, enemyFormation, getEventItem} = e.detail
-    {_teitokuLv, _nickNameId} = window
+    {_teitokuLv, _nickName, _nickNameId} = window
     info =
       shipId: dropShipId
       quest: quest
@@ -147,6 +147,7 @@
       info =
         teitokuId: _nickNameId
         teitokuLv: _teitokuLv
+        teitoku: _nickName
         mapId: map
         mapLv: mapLv[map] or 0
       try


sync cond and yomi

sync cond and yomi

--- index.cjsx
+++ index.cjsx
@@ -132,7 +132,7 @@
   enemyTyku = enemyInfo.totalTyku
   [shipName, shipLv, maxHp, nowHp, enemyFormation, enemyTyku]

-getInfo = (shipName, shipLv, friend, enemy, enemyLv) ->
+getInfo = (shipName, shipLv, friend, enemy, enemyLv, exerciseFlag) ->
   {$ships, _ships} = window
   for shipId, i in friend
     continue if shipId == -1
@@ -144,7 +144,10 @@
     if $ships[shipId].api_yomi == "-"
       shipName[i + 5] = $ships[shipId].api_name
     else
-      shipName[i + 5] = $ships[shipId].api_name + $ships[shipId].api_yomi
+      if exerciseFlag == 0
+        shipName[i + 5] = $ships[shipId].api_name + $ships[shipId].api_yomiapi_yomi
+      else
+        shipName[i + 5] = $ships[shipId].api_name
   [shipName, shipLv]

 getHp = (maxHp, nowHp, maxHps, nowHps) ->
@@ -276,10 +279,11 @@
       enemyIntercept: 0
       enemyName: "深海棲艦"
       result: "不明"
+      shipCond: [0, 0, 0, 0, 0, 0]
       deckId: 0
     handleResponse: (e) ->
       {method, path, body, postBody} = e.detail
-      {afterHp, nowHp, maxHp, damageHp, shipName, shipLv, enemyInfo, getShip, enemyFormation, enemyTyku, enemyIntercept, enemyName, result, deckId} = @state
+      {afterHp, nowHp, maxHp, damageHp, shipName, shipLv, enemyInfo, getShip, enemyFormation, enemyTyku, enemyIntercept, enemyName, result, shipCond, deckId} = @state
       if path == '/kcsapi/api_req_map/start' || formationFlag
         @setState
           enemyFormation: 0
@@ -333,7 +337,7 @@
             shipLv[i] = -1
           {_decks} = window
           flag = true
-          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_dock_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv
+          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_dock_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv, 0
           [maxHp, nowHp] = getHp maxHp, nowHp, body.api_maxhps, body.api_nowhps
           afterHp = Object.clone nowHp
           getShip = null
@@ -380,7 +384,7 @@
           {_decks} = window
           flag = true
           getShip = null
-          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_deck_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv
+          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_deck_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv, 0
           [maxHp, nowHp] = getHp maxHp, nowHp, body.api_maxhps, body.api_nowhps
           afterHp = Object.clone nowHp
           if body.api_formation?
@@ -409,7 +413,7 @@
           {_decks} = window
           flag = true
           getShip = null
-          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_dock_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv
+          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_dock_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv, 0
           [maxHp, nowHp] = getHp maxHp, nowHp, body.api_maxhps, body.api_nowhps
           afterHp = Object.clone nowHp
           if body.api_formation?
@@ -449,7 +453,7 @@
           flag = true
           getShip = null
           enemyName = "演習相手"
-          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_dock_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv
+          [shipName, shipLv] = getInfo shipName, shipLv, _decks[body.api_dock_id - 1].api_ship, body.api_ship_ke, body.api_ship_lv, 1
           [maxHp, nowHp] = getHp maxHp, nowHp, body.api_maxhps, body.api_nowhps
           if body.api_formation?
             enemyFormation = body.api_formation[1]
@@ -507,6 +511,7 @@
             maxHp[i] = _ships[shipId].api_maxhp
             nowHp[i] = _ships[shipId].api_nowhp
             damageHp[i] = 0
+            shipCond[i] = _ships[shipId].api_cond
           shipLv[i] = -1 for i in [6..11]
       return unless flag
       @setState
@@ -522,6 +527,7 @@
         enemyIntercept: enemyIntercept
         enemyName: enemyName
         result: result
+        shipCond: shipCond
         deckId: deckId

     componentDidMount: ->
@@ -544,7 +550,12 @@
                 continue unless @state.shipLv[i] != -1
                 continue unless i < 6

-                  Lv. {@state.shipLv[i]} - {tmpName}
+
+                    Lv. {@state.shipLv[i]} - {tmpName}
+
+                      <FontAwesome key={1} name='star-o' />{@state.shipCond[i]}
+
+

                     <ProgressBar bsStyle={getHpStyle @state.nowHp[i] / @state.maxHp[i] * 100}
                       now={@state.nowHp[i] / @state.maxHp[i] * 100}
@@ -608,7 +619,7 @@
                   for j in [0..1]
                     list.push
                 else
-                  list.push Lv. {@state.shipLv[i]} - {tmpName}
+                  list.push Lv. {@state.shipLv[i]} - {tmpName} <FontAwesome key={1} name='star-o' />{@state.shipCond[i]}
                   list.push <ProgressBar bsStyle={getHpStyle @state.nowHp[i] / @state.maxHp[i] * 100} now={@state.nowHp[i] / @state.maxHp[i] * 100} label={if @state.damageHp[i] > 0 then "#{@state.nowHp[i]} / #{@state.maxHp[i]} (-#{@state.damageHp[i]})" else "#{@state.nowHp[i]} / #{@state.maxHp[i]}"} />
                 if @state.shipLv[i + 6] == -1
                   for j in [0..1]


only 404 the request detail page on empty history if the current request 404'd as well

--- SingularityUI/app/controllers/RequestDetail.coffee
+++ SingularityUI/app/controllers/RequestDetail.coffee
@@ -110,7 +110,9 @@
         app.showView @view

     refresh: ->
-        @models.request.fetch().error =>
+        requestFetch = @models.request.fetch()
+
+        requestFetch.error =>
             # ignore 404 so we can still display info about
             # deleted requests (show in `requestHistoryMsg`)
             @ignore404
@@ -123,13 +125,12 @@
         @collections.scheduledTasks.fetch().error @ignore404

         if @collections.requestHistory.currentPage is 1
-            @collections.requestHistory.fetch()
-                .done =>
-                    # Request never existed
+            requestHistoryFetch = @collections.requestHistory.fetch()
+            requestHistoryFetch.error => @ignore404
+            requestFetch.error =>
+                requestHistoryFetch.done =>
                     if @collections.requestHistory.length is 0
                         app.router.notFound()
-                .error =>
-                    @ignore404

         if @collections.taskHistory.currentPage is 1
             @collections.taskHistory.fetch().error    @ignore404


Switch logFunction for testing Logger

Switch logFunction for testing Logger

--- packages/deft/test/coffee/log/Logger.coffee
+++ packages/deft/test/coffee/log/Logger.coffee
@@ -11,7 +11,10 @@
 			logFunction = null

 			beforeEach( ->
-				logFunction = sinon.stub( Ext, 'log' )
+				if Deft.isFunction( Ext.log )
+					logFunction = sinon.stub( Ext, 'log' )
+				else
+					logFunction = sinon.stub( Ext.Logger, 'log' )
 				return
 			)


Use "popup" consistently ("popover" interferes too much with the popoverMixin..)

--- core/app/backbone/views/evidence/vote_up_down_view.coffee
+++ core/app/backbone/views/evidence/vote_up_down_view.coffee
@@ -17,7 +17,7 @@

   onRender: ->
     @_updateButtons()
-    @_setPopoverHoverIntent()
+    @_setPopupHoverIntent()

   _updateButtons: ->
     @ui.upButton.toggleClass 'active', @model.get('current_user_opinion') == 'believes'
@@ -58,24 +58,24 @@
       'right'

   _openVoteUpPopup: ->
-    return unless @_canShowPopover()
+    return unless @_canShowPopup()

     @_open_vote_popup '.js-up', new FactRelationVoteUpView model: @model

   _openVoteDownPopup: ->
-    return unless @_canShowPopover()
+    return unless @_canShowPopup()

     @_open_vote_popup '.js-down', new FactRelationVoteDownView model: @model

-  _canShowPopover: ->
+  _canShowPopup: ->
     @model instanceof FactRelation && Factlink.Global.can_haz['vote_up_down_popup']

   _closePopups: ->
     @popoverRemove '.js-up'
     @popoverRemove '.js-down'

-  _setPopoverHoverIntent: ->
-    return unless @_canShowPopover()
+  _setPopupHoverIntent: ->
+    return unless @_canShowPopup()

     @ui.upButton.hoverIntent
       timeout: 100