Use spacepen for html generation

Use spacepen for html generation

For consistency

--- src/root-view.coffee
+++ src/root-view.coffee
@@ -65,7 +65,7 @@

   # Private:
   initialize: (state={}) ->
-    @prepend("

") if atom.getLoadSettings().devMode
+    @prepend($$ -> @div class: 'dev-mode') if atom.getLoadSettings().devMode

     if state instanceof telepath.Document
       @state = state


add missing clearTimeout method to scheduler

--- src/scheduler.coffee
+++ src/scheduler.coffee
@@ -2,5 +2,6 @@
   setTimeout: (f,d) -> setTimeout(f,d)
   setInterval: (f, i) -> setInterval(f, i)
   clearInterval: (id) -> clearInterval(id)
+  clearTimeout: (id) -> clearTimeout(id)
   now: -> new Date().getTime()
 }


Goodbye FS/Exec

Goodbye FS/Exec

Handful of improvements, and removed the non-transport plague from
our codebase. Huzzah!

--- lib/deps/outdated.coffee
+++ lib/deps/outdated.coffee
@@ -3,9 +3,7 @@
 #
 # A simple module as a function to check the dependencies of a directory.
 #
-fs              = require 'fs'
 path            = require 'path'
-{exec}          = require 'child_process'
 verexp          = require 'verbal-expressions'
 autoTransport   = require '../transports/auto'

@@ -81,10 +79,13 @@

 # ## Node Production Outdated
+#
+# This function is a bit "overly complex" due to the double-async calls,
+# but this is due to the desire to make outdated checks **as fast as
+# possible**. Why? Read the module description.
 outdatedNodeProd = (dir, opts={}, callback=->) ->
-  if opts instanceof Function
-    callback = opts
-    opts = {}
+  if opts instanceof Function then [callback, opts] = [opts, {}]
+  transport = opts.transport ?= autoTransport
   opts.command    ?= 'npm outdated' # should use --production once the npm
                                     # update goes live.

@@ -96,15 +97,18 @@
   outdated  = null

-  fs.exists path.join(dir, 'package.json'), (_exists) ->
-    exists = _exists
+  # We use test -e, which checks for the existance of a file/dir.
+  # For more info see `info test`
+  transport "test -e #{path.join(dir, 'package.json')}", (_err) ->
+    exists = not _err?
+    if err? then return # exec already handled it
     # If exists calls back first, and it's false bail right away.
     if not exists then return callback new Error 'package.json not found'
-    if err? then return # exec already handled it
     # If outdated beat us, it would not callback. So we need to do it
     if outdated? then return callback null, outdated, packages

-  exec opts.command, cwd:dir, (_err, stdout, stderr) ->
+
+  transport opts.command, cwd:dir, (_err, stdout, stderr) ->
     err = _err
     if exists is false then return # exists already called back
     if err? then return callback _npmErrCodeHumanizer err
@@ -116,11 +120,7 @@
     stdout = stdout[...-1]

     # Split the response from npm, which is a list of outdated packages.
-    if stdout != ''
-      packages  = stdout.split('\n')
-    else
-      packages  = []
-
+    packages  = if stdout is '' then [] else stdout.split('\n')
     outdated  = packages.length > 0

     # Only callback if exists already called back true


scroll to top of next tutorial slide

scroll to top of next tutorial slide

--- app/components/step-through.cjsx
+++ app/components/step-through.cjsx
@@ -1,5 +1,8 @@
 React = require 'react'
+ReactDOM = require 'react-dom'
 ReactSwipe = require 'react-swipe'
+animatedScrollTo = require 'animated-scrollto'
+

 module.exports = React.createClass
   displayName: 'StepThrough'
@@ -41,13 +44,21 @@

   goPrevious: ->
     @refs.swiper.swipe.prev()
+    @handleScroll()

   goNext: ->
     @refs.swiper.swipe.next()
+    @handleScroll()

   goTo: (index) ->
     @refs.swiper.swipe.slide index
+    @handleScroll()

   handleStep: (total, index) ->
     @setState
       step: index %% total
+
+  handleScroll: ->
+    node = ReactDOM.findDOMNode(@)
+    mediaCard = node.querySelector(".tutorial-steps div")
+    setTimeout (=> animatedScrollTo mediaCard, node.offsetTop, 0), 500


fix bug

fix bug

--- app/controllers/user_edit.coffee
+++ app/controllers/user_edit.coffee
@@ -29,7 +29,6 @@
     super

     MyUser.bind('refresh change', @change)
-    @active @change

     @addButton('Cancel', @back)
     @addButton('Done', @submit).addClass('right blue')


fix new Layer({scroll:true}), ignoreEvents default was in the way

move @define ignoreEvents property before any scroll properties
fixes motif/company#795


added callback to terminal.runCommand

added callback to terminal.runCommand

--- client/app/CommonViews/workspace/panes/terminalpane.coffee
+++ client/app/CommonViews/workspace/panes/terminalpane.coffee
@@ -19,9 +19,13 @@
     {command} = @getOptions()
     @runCommand command if command

-  runCommand: (command) ->
+  runCommand: (command, callback) ->
     return unless command
-    return @remote.input "#{command}\n"  if @remote
+    if @remote
+      if callback
+        @webterm.once "WebTermEvent", callback
+        command += ";echo $?|kdevent"
+      return @remote.input "#{command}\n"

     if not @remote and not @triedAgain
       @utils.wait 2000, =>


add synctex back in

add synctex back in

--- app/coffee/DockerRunner.coffee
+++ app/coffee/DockerRunner.coffee
@@ -108,8 +108,8 @@
 	_getContainerOptions: (command, image, volumes, timeout, environment) ->
 		timeoutInSeconds = timeout / 1000

-		# if Settings.path?.synctexBinHostPath?
-		# 	volumes[Settings.path.synctexBinHostPath] = "/opt/synctex:ro"
+		if Settings.path?.synctexBinHostPath?
+			volumes[Settings.path.synctexBinHostPath] = "/opt/synctex:ro"

 		dockerVolumes = {}
 		for hostVol, dockerVol of volumes


Refactor: migrated urls plugin to classes

--- app/coffee/plugins/urls.coffee
+++ app/coffee/plugins/urls.coffee
@@ -16,47 +16,42 @@
     obj = _.clone(obj)
     return fmt.replace /%s/g, (match) -> String(obj.shift())

-UrlsProvider = ->
-    data = {
+class UrlsService
+    constructor: (data) ->
+        @data = data
+
+    setHost: (ns, host, scheme) ->
+        @data.host[ns] = host
+        @data.scheme[ns] = scheme
+
+
+class UrlsProvider
+    data: {
         urls: {}
         host: {}
         scheme: {}
     }

-    setHost = (ns, host, scheme) ->
-        data.host[ns] = host
-        data.scheme[ns] = scheme
-
-    setUrls = (ns, urls) ->
+    setUrls: (ns, urls) ->
         if _.toArray(arguments).length != 2
             throw Error("wrong arguments to setUrls")

-        data.urls[ns] = urls
-        service[ns] = ->
+        @data.urls[ns] = urls
+        UrlsService.prototype[ns] = ->
             if _.toArray(arguments).length < 1
                 throw Error("wrong arguments")

             args = _.toArray(arguments)
             name = args.slice(0, 1)[0]
-            url = format(data.urls[ns][name], args.slice(1))
+            url = format(@data.urls[ns][name], args.slice(1))

-            if data.host[ns]
-                return format("%s://%s%s", [data.scheme[ns], data.host[ns], url])
+            if @data.host[ns]
+                return format("%s://%s%s", [@data.scheme[ns], @data.host[ns], url])

             return url

-    service = {}
-    service.data = data
-    service.setUrls = setUrls
-    service.setHost = setHost
-
-    @.setUrls = setUrls
-    @.setHost = setHost
-
-    @.$get = ->
-        return service
-
-    return
+    $get: ->
+        return new UrlsService(@data)

 module = angular.module("gmUrls", [])
 module.provider('$gmUrls', UrlsProvider)


Fix method parameters

Fix method parameters

--- app/core/mixins/Movable.coffee
+++ app/core/mixins/Movable.coffee
@@ -182,8 +182,7 @@
     return @

-  # TODO: (pixel)??
-  stopMovement: (pixel) ->
+  stopMovement: () ->
     @physBody.SetLinearVelocity(new @level.physicsManager.Vec2(0, 0))
     @moving.down        = false
     @moving.up          = false


Search completion; add additional filtering stage.

Two things:
   1. Do not fire off requests to completion engines if the relevancy
   score they are assigned wouldn't be enough to be included.

   2. Fix off-by-one error in prepareSuggestions.

--- background_scripts/completion.coffee
+++ background_scripts/completion.coffee
@@ -513,7 +513,15 @@
       # continuation.
       onComplete suggestions,
         filter: filter
-        continuation: (onComplete) =>
+        continuation: (suggestions, onComplete) =>
+          # Fetch completion suggestions from suggestion engines.
+
+          # We can skip this if any new suggestions we propose cannot score highly enough to make the list
+          # anyway.
+          if 10 <= suggestions.length and relevancy < suggestions[suggestions.length-1].relevancy
+            console.log "skip (cannot make the grade):", suggestions.length, query if SearchEngineCompleter.debug
+            return onComplete []
+
           CompletionSearch.complete searchUrl, queryTerms, (suggestions = []) =>
             console.log "fetched suggestions:", suggestions.length, query if SearchEngineCompleter.debug
             onComplete suggestions.map mkSuggestion
@@ -572,7 +580,7 @@
       if shouldRunContinuations
         jobs = new JobRunner continuations.map (continuation) ->
           (callback) ->
-            continuation (newSuggestions) ->
+            continuation suggestions, (newSuggestions) ->
               suggestions.push newSuggestions...
               callback()

@@ -602,7 +610,7 @@
       for suggestion in suggestions
         url = suggestion.shortenUrl()
         continue if seenUrls[url]
-        break if ++count == @maxResults
+        break if count++ == @maxResults
         seenUrls[url] = suggestion

     # Generate HTML for the remaining suggestions and return them.


removed bullshit binding

removed bullshit binding

--- app/js/util/scrollspeed.coffee
+++ app/js/util/scrollspeed.coffee
@@ -22,5 +22,5 @@
   get_measure: getScrollTop
   on_change: check_scrolling_speed

-Factlink.startFastScrollDetection = =>
+Factlink.startFastScrollDetection = ->
   $(window).on 'scroll', scroll_speed.start_measuring


:bug:Fix student level complete on teacher dashboard (#5111)

LevelSession.submitted property shouldn't be used for level completeness in classroom dashboards.  More applicable to arena ladder logic.

--- app/models/LevelSession.coffee
+++ app/models/LevelSession.coffee
@@ -41,7 +41,7 @@
     @get('submittedCodeLanguage')? and @get('team')?

   completed: ->
-    @get('state')?.complete || @get('submitted') || false
+    @get('state')?.complete || false

   shouldAvoidCorruptData: (attrs) ->
     return false unless me.team is 'humans'


make keybinds work for csx too

make keybinds work for csx too

--- keymaps/omnisharp-atom.cson
+++ keymaps/omnisharp-atom.cson
@@ -15,7 +15,7 @@
   'ctrl-alt-b': 'omnisharp-atom:show-build'
   'ctrl-shift-b': 'omnisharp-atom:build'

-'atom-text-editor:not([mini])[data-grammar~="cs"]':
+'atom-text-editor:not([mini])[data-grammar~="cs"], atom-text-editor:not([mini])[data-grammar~="csx"]':
   'alt-F12': 'omnisharp-atom:go-to-definition'
   'shift-F12': 'omnisharp-atom:find-usages'
   'ctrl-alt-u': 'omnisharp-atom:fix-usings'
@@ -26,7 +26,7 @@
   'ctrl-F12': 'omnisharp-atom:go-to-implementation'
   'f1': 'omnisharp-atom:type-lookup'

-'atom-text-editor.autocomplete-active:not([mini])[data-grammar~="cs"]':
+'.autocomplete-active:not([mini])[data-grammar~="cs"], .autocomplete-active:not([mini])[data-grammar~="csx"]':
   'space': 'omnisharp-atom:intellisense-space'
   '.': 'omnisharp-atom:intellisense-dot'
   'enter': 'autocomplete-plus:confirm'


relicense misc.coffee under permissive BSD

--- salvus/misc.coffee
+++ salvus/misc.coffee
@@ -4,6 +4,30 @@
 #
 ##########################################################################
 #
+###############################################################################
+# Copyright (c) 2013, William Stein
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################

 # true if s.startswith(c)


Update team page

Update team page

--- app/pages/about/team-page.cjsx
+++ app/pages/about/team-page.cjsx
@@ -55,10 +55,6 @@
         bio: '''Astronomer and founder of both Galaxy Zoo and the Zooniverse that grew from it,
         Chris is interested in how galaxies form and evolve, how citizen science can change the
         world, and whether the Chicago Fire can get their act together.'''
-      chrisSnyder:
-        title: 'Project Manager'
-        bio: '''Chris Snyder began working on the Zooniverse team in fall 2012 as a web developer. In July 2013,
-        he became the technical project manager. He received a degree in computer science from the University of Dayton.'''
       christopherDoogue:
         title: 'Project Assistant'
         bio: '''Chris has been happily supporting the Zooniverse Oxford team since Sep. 2014. He has been with the Department of Astrophysics for over 2 years administratively supporting various projects. A former trained actor, he has the ability to look like he's smiling in the face of adversity!'''
@@ -72,11 +68,6 @@
         bio: '''Darren (DZM) serves as a liaison to the Zooniverse community and assists with strategic
         content for projects. A Northwestern University graduate in journalism, he is also a golf addict,
         amateur author, and hopeless animal lover.'''
-      edPaget:
-        title: 'Developer'
-        bio: '''Ed Paget joined Adler's Zooniverse Team as a software developer in August 2012.
-        He previously worked as a freelance programmer and photographer. Ed graduated from
-        Northwestern University with a major in Radio/TV/Film.'''
       grantMiller:
         title: 'Communications Lead'
         bio: '''A former exoplanetary scientist, Grant is now responsible for communicating with our volunteers and researchers. He is also behind the Zooniverse's presence on
@@ -86,11 +77,6 @@
         bio: '''Greg uses machine learning and statistics to help projects analyse the volunteer
         classifications. He has a PhD in Computer Science from the University of Waterloo, Canada.
         In his spare time, Greg loves to eat pancakes with real maple syrup and run ultramarathons.'''
-      heathVanSingel:
-        title: 'Designer'
-        bio: '''Heath is the UX/UI Designer for projects at the Zooniverse where he works to craft
-        thoughtful and engaging user experiences. Apart from design Heath also enjoys illustration,
-        a good sci-fi or fantasy novel, and trips back to Michigan.'''
       jimODonnell:
         title: 'UX Developer'
         bio: '''Professional cynic but his heart's not in it. Web developer for the Zooniverse,
@@ -235,13 +221,6 @@
     bio: counterpart "team.content.chrisLintott.bio"
     image: "/assets/team/chris-l.png"
     location: "oxford"
-  chrisSnyder:
-    name: "Chris Snyder"
-    twitter: "bumishness"
-    title: counterpart "team.content.chrisSnyder.title"
-    bio: counterpart "team.content.chrisSnyder.bio"
-    image: "/assets/team/chriss.png"
-    location: "chicago"
   christopherDoogue:
     name: "Christopher Doogue"
     title: counterpart "team.content.christopherDoogue.title"
@@ -261,13 +240,6 @@
     bio: counterpart "team.content.darrenMcRoy.bio"
     image: "/assets/team/darren.jpg"
     location: "chicago"
-  edPaget:
-    name: "Ed Paget"
-    twitter: "edpaget"
-    title: counterpart "team.content.edPaget.title"
-    bio: counterpart "team.content.edPaget.bio"
-    image: "/assets/team/ed.png"
-    location: "chicago"
   grantMiller:
     name: "Grant Robert MacKinnon Miller"
     twitter: "mrniaboc"
@@ -281,12 +253,6 @@
     bio: counterpart "team.content.gregHines.bio"
     image: "/assets/team/greg.jpg"
     location: "oxford"
-  heathVanSingel:
-    name: "Heath van Singel"
-    title: counterpart "team.content.heathVanSingel.title"
-    bio: counterpart "team.content.heathVanSingel.bio"
-    image: "/assets/team/heath.png"
-    location: "chicago"
   jenGupta:
     name: "Jen Gupta"
     twitter: "jen_gupta"


Always move to end of current line

Always move to end of current line

--- src/selection.coffee
+++ src/selection.coffee
@@ -491,10 +491,9 @@
       insertSpace = nextRow <= @editor.buffer.getLastRow() and
                     @editor.buffer.lineLengthForRow(nextRow) > 0 and
                     @editor.buffer.lineLengthForRow(currentRow) > 0
-
-      if insertSpace
-        @insertText(' ')
-        @cursor.moveToEndOfLine()
+      @insertText(' ') if insertSpace
+
+      @cursor.moveToEndOfLine()

       # Remove leading whitespace from the line below
       @modifySelection =>


add grammar rules for message names

add grammar rules for message names


Fixed #714 with a hack.

Fixed #714 with a hack.

--- app/views/play/level_view.coffee
+++ app/views/play/level_view.coffee
@@ -421,7 +421,7 @@
     return if @alreadyLoadedState
     @alreadyLoadedState = true
     state = @originalSessionState
-    if state.frame
+    if state.frame and @level.get('type') isnt 'ladder'  # https://github.com/codecombat/codecombat/issues/714
       Backbone.Mediator.publish 'level-set-time', { time: 0, frameOffset: state.frame }
     if state.selected
       # TODO: Should also restore selected spell here by saving spellName


See #213. Disable `Beautify Directory` menu option.

--- menus/atom-beautify.cson
+++ menus/atom-beautify.cson
@@ -4,8 +4,8 @@
     'Enable atom-beautify': 'beautify:beautify-editor'
   '.tree-view .file > .name':
     'Beautify File': 'beautify:beautify-file'
-  '.tree-view .directory > .header > .name':
-    'Beautify Directory': 'beautify:beautify-directory'
+#  '.tree-view .directory > .header > .name':
+#    'Beautify Directory': 'beautify:beautify-directory'

 'menu': [
   {


adding "First day on the Internet" kid

adding "First day on the Internet" kid

--- src/scripts/meme_generator.coffee
+++ src/scripts/meme_generator.coffee
@@ -32,6 +32,7 @@
 #   hubot memegen PREPARE YOURSELF <text> - Generates GoT
 #   hubot memegen WHAT IF I TOLD YOU <text> - Generates Morpheus
 #   hubot memegen <text> BETTER DRINK MY OWN PISS - Generates Bear Grylls
+#   hubot memegen INTERNET KID <text>, <text> - Generates First-day-on-the-Internet Kid
 # Author:
 #   skalnik

@@ -140,6 +141,11 @@
         regex: /(memegen)?(.*) (BETTER DRINK MY OWN PISS)/i,
         generatorID: 92,
         imageID: 89714
+      },
+      {
+        regex: /(memegen)? ?INTERNET KID ?([^,]*),?(.*)/i,
+        generatorID: 1095654,
+        imageID: 4714007
       }
     ]


Reset toc on init

Reset toc on init

--- src/scripts/models/content.coffee
+++ src/scripts/models/content.coffee
@@ -33,8 +33,9 @@
       key: 'toc'
       collectionType: Backbone.Collection
     }]
-
+
     initialize: (options = {}) ->
+      toc.reset()
       @set('toc', toc)

       @fetch


webapp/course: info text is wrapped oddly

--- src/smc-webapp/course/common.cjsx
+++ src/smc-webapp/course/common.cjsx
@@ -232,7 +232,12 @@
                  Cancel
             </Button>
             if name.toLowerCase() == 'assign'
-                v.push
What happens when I assign again?

+                # inline-block because buttons above are float:left
+                v.push

+
+                               What happens when I assign again?
+
+

             return v
         else
             <Button key="copy" bsStyle='warning' onClick={=>@setState("#{key}":true)}>


Fix test

Fix test

--- src/spec/helpers/sftp.spec.coffee
+++ src/spec/helpers/sftp.spec.coffee
@@ -105,7 +105,7 @@
       @helpers.safePutFile @_sftp, FILE_LOCAL, FOLDER_REMOTE + "/test#{i}.txt"
     , {concurrency: 5}
     .then =>
-      @_sftp.listFiles @_sftp, FOLDER_REMOTE
+      @helpers.listFiles(@_sftp, FOLDER_REMOTE)
     .then (files) ->
       expect(_.size files).toEqual 100
       done()


console.log removed

console.log removed

--- source/paper-carousel.coffee
+++ source/paper-carousel.coffee
@@ -576,8 +576,6 @@
 				else
 					realMovement = Math.max(realMovement, -maxLimit)

-				console.log window.scrolling, window.touchScroll
-
 				if (window.scrolling == false || window.scrolling == undefined) && (window.touchScroll == false || window.touchScroll == undefined)
 					if touchValue > 2 || touchValue < -2
 						# apply touch movement


Remove duplicate test.

Remove duplicate test.

--- templates/default/test/foo.coffee
+++ templates/default/test/foo.coffee
@@ -1,7 +0,0 @@
-assert = require 'assert'
-foo    = require 'client/js/foo'
-
-describe 'client/js/foo', ->
-  describe 'foo.bar()', ->
-    it 'should return 42', ->
-      assert.equal foo.bar(), 42


add test for troublesome compressed image

--- test/specs/compressedimage.coffee
+++ test/specs/compressedimage.coffee
@@ -43,6 +43,31 @@
       expect(image.getPixel(pixels, 237, 377)).toBeCloseTo(-0.614697, precision)
       expect(image.getPixel(pixels, 393, 27)).toBeCloseTo(0.506017, precision)

+  it 'can ready a (troublesome) FITS compressed image', ->
+    precision = 6
+
+    ready = false
+
+    image = null
+    pixels = null
+    path = 'data/CFHTLS_082_0012_g.fits.fz'
+    fits = new astro.FITS(path, (fits) ->
+      image = fits.getDataUnit()
+      image.getFrame(0, (arr) ->
+        pixels = arr
+        ready = true
+      )
+    )
+
+    waitsFor ->
+      return ready
+
+    runs ->
+      image.getExtent(pixels)
+
+      expect(image.min).toBeCloseTo(-106.448853, precision)
+      expect(image.max).toBeCloseTo(793.284302, precision)
+
 #   it 'can read a frame by spawning a web worker', ->
 #     precision = 6
 #     fits = arr = null


Added tests for always_restart.txt

Added tests for always_restart.txt

--- test/test_rack_application.coffee
+++ test/test_rack_application.coffee
@@ -71,6 +71,68 @@
             test.same pid, newpid
             done -> fs.unlink restart, -> test.done()

+  "handling a request, always_restart.txt present, request": (test) ->
+    test.expect 3
+    always_restart = fixturePath("apps/pid/tmp/always_restart.txt")
+    serveApp "apps/pid", (request, done) ->
+      fs.unlink always_restart, ->
+        request "GET", "/", (body) ->
+          test.ok pid = parseInt body
+          touch always_restart, ->
+            request "GET", "/", (body) ->
+              test.ok newpid = parseInt body
+              test.ok pid isnt newpid
+              done -> fs.unlink always_restart, -> test.done()
+
+  "always_restart.txt present, handling a request, request": (test) ->
+    test.expect 3
+    touch always_restart = fixturePath("apps/pid/tmp/always_restart.txt"), ->
+      serveApp "apps/pid", (request, done) ->
+        request "GET", "/", (body) ->
+          test.ok pid = parseInt body
+          request "GET", "/", (body) ->
+            test.ok newpid = parseInt body
+            test.ok pid isnt newpid
+            done -> fs.unlink always_restart, -> test.done()
+
+  "always_restart.txt present, handling a request, touch restart.txt, request": (test) ->
+    test.expect 3
+    touch always_restart = fixturePath("apps/pid/tmp/always_restart.txt"), ->
+      serveApp "apps/pid", (request, done) ->
+        request "GET", "/", (body) ->
+          test.ok pid = parseInt body
+          touch restart = fixturePath("apps/pid/tmp/restart.txt"), ->
+            request "GET", "/", (body) ->
+              test.ok newpid = parseInt body
+              test.ok pid isnt newpid
+              done -> fs.unlink always_restart, fs.unlink restart, -> test.done()
+
+  "handling the initial request when restart.txt and always_restart.txt is present": (test) ->
+    test.expect 3
+    touch always_restart = fixturePath("apps/pid/tmp/always_restart.txt"), ->
+      touch restart = fixturePath("apps/pid/tmp/restart.txt"), ->
+        serveApp "apps/pid", (request, done) ->
+          request "GET", "/", (body) ->
+            test.ok pid = parseInt body
+            request "GET", "/", (body) ->
+              test.ok newpid = parseInt body
+              test.ok pid isnt newpid
+              done -> fs.unlink restart, fs.unlink always_restart, -> test.done()
+
+  "always_restart.txt present, handling a request, request, request": (test) ->
+    test.expect 5
+    touch always_restart = fixturePath("apps/pid/tmp/always_restart.txt"), ->
+      serveApp "apps/pid", (request, done) ->
+        request "GET", "/", (body) ->
+          test.ok pid = parseInt body
+          request "GET", "/", (body) ->
+            test.ok newpid = parseInt body
+            test.ok pid isnt newpid
+            request "GET", "/", (body) ->
+              test.ok newerpid = parseInt body
+              test.ok newpid isnt newerpid
+              done -> fs.unlink always_restart, -> test.done()
+
   "custom environment": (test) ->
     test.expect 3
     serveApp "apps/env", (request, done) ->


allowed change password

allowed change password

--- config/accounts/config.coffee
+++ config/accounts/config.coffee
@@ -18,7 +18,7 @@
 AccountsTemplates.configure
 	sendVerificationEmail:true
 	showForgotPasswordLink:true
-	enablePasswordChange:false
+	enablePasswordChange:true
 	# enforceEmailVerification:true
 	forbidClientAccountCreation: true
 	showForgotPasswordLink: true


Remove the unzip spec completely.

Remove the unzip spec completely.

--- spec/modules-spec.coffee
+++ spec/modules-spec.coffee
@@ -4,14 +4,6 @@

 describe 'third-party module', ->
   fixtures = path.join __dirname, 'fixtures'
-
-  xdescribe 'unzip', ->
-    unzip = require 'unzip'
-
-    it 'fires close event', (done) ->
-      fs.createReadStream(path.join(fixtures, 'zip', 'a.zip'))
-        .pipe(unzip.Parse())
-        .on('close', done)

   describe 'runas', ->
     it 'can be required in renderer', ->


Improved error feedback when creating waterpoint

--- app/scripts/controllers.coffee
+++ app/scripts/controllers.coffee
@@ -13,9 +13,13 @@
       facility_code: "wpf001"
     $scope.save = () ->
       Waterpoint.save $scope.form, (waterpoint) ->
-        console.log "Successfully created waterpoint", waterpoint
         if waterpoint._status == 'OK'
+          console.log "Successfully created waterpoint", waterpoint
           flash.success = 'Waterpoint successfully created!'
+        if waterpoint._status == 'ERR'
+          console.log "Failed to create waterpoint", waterpoint
+          for field, message of waterpoint._issues
+            flash.error = "#{field}: #{message}"
   .controller 'WaterpointEditCtrl', ($scope, $http, $routeParams, Waterpoint, FacilityForm, flash) ->
     Waterpoint.get id: $routeParams.id, (waterpoint) ->
       $scope.form = waterpoint


Update es-419.coffee

Update es-419.coffee

--- app/locale/es-419.coffee
+++ app/locale/es-419.coffee
@@ -4,7 +4,7 @@
     no_ie: "¡Lo sentimos! CodeCombat no funciona en Internet Explorer 8 o versiones anteriores." # Warning that only shows up in IE8 and older
     no_mobile: "¡CodeCombat no fue diseñado para dispositivos móviles y quizás no funcione!" # Warning that shows up on mobile devices
     play: "Jugar" # The big play button that opens up the campaign view.
-#    play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
+    play_campaign_version: "Jugar Versión Campaña" # Shows up under big play button if you only play /courses
     old_browser: "¡Oh! ¡Oh! Tu navegador es muy antiguo para correr CodeCombat. ¡Lo sentimos!" # Warning that shows up on really old Firefox/Chrome/Safari
     old_browser_suffix: "Puedes probar de todas formas, pero probablemente no funcione."
     ipad_browser: "Malas noticias: CodeCombat no funciona en el navegador de iPad. Buenas noticias: nuestra propia aplicación de iPad esta en espera para ser aprobada por Apple."
@@ -13,14 +13,14 @@
     multiplayer: "Multijugador" # Not currently shown on home page
     for_developers: "Para Desarrolladores" # Not currently shown on home page.
     or_ipad: "O descargar para iPad"
-#    hoc_class_code: "I Have a Class Code"
+    hoc_class_code: "Tengo un Código de Clase"
 #    hoc_enter: "Enter"
 #    hoc_title: "Hour of Code?"

   nav:
     play: "Jugar" # The top nav bar entry where players choose which levels to play
     community: "Comunidad"
-#    courses: "Courses"
+    courses: "Cursos"
     editor: "Editor"
     blog: "Blog"
     forum: "Foro"
@@ -55,7 +55,7 @@

   play:
     play_as: "Jugar Como " # Ladder page
-#    compete: "Compete!" # Course details page
+    compete: "¡Competir!" # Course details page
     spectate: "Observar" # Ladder page
     players: "Jugadores" # Hover over a level on /play
     hours_played: "horas jugadas" # Hover over a level on /play
@@ -78,7 +78,7 @@
     subscription_required: "Requiere Suscripción"
     anonymous: "Jugador Anónimo"
     level_difficulty: "Dificultad: "
-#    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
+    play_classroom_version: "Jugar la Versión de Aula" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "Campaña para principiantes"
     awaiting_levels_adventurer_prefix: "Nosotros libreamos nuevos niveles cada semana"
     awaiting_levels_adventurer: "Registrate como un aventurero"
@@ -119,7 +119,7 @@
     required: "Necesitas entrar a tu cuenta antes de continuar."
     login_switch: "¿Ya tienes una cuenta?"
 #    school_name: "School Name and City"
-#    optional: "optional"
+    optional: "opcional"
 #    school_name_placeholder: "Example High School, Springfield, IL"

   recover:
@@ -226,9 +226,9 @@

   play_level:
 #    completed_level: "Completed Level:"
-#    course: "Course:"
+    course: "Curso:"
     done: "Listo"
-#    next_level: "Next Level:"
+    next_level: "Siguiente Nivel:"
     next_game: "Siguiente juego"
     show_menu: "Mostrar menú de juego"
     home: "Inicio" # Not used any more, will be removed soon.
@@ -620,7 +620,7 @@
     free_1: "Hay más de 110 niveles gratis que cubren cada concepto."
     free_2: "Una suscripción mensual le da acceso a tutoriales en vídeo y niveles extra para practicar."
 #    free_3: "The CodeCombat content is divided into"
-#    free_4: "courses"
+    free_4: "cursos"
 #    free_5: ".  The first course is free, and about an hour of material."
 #    free_6: "Access to the additional courses can be unlocked with a one-time purchase."
     teacher_subs_title: "¡Los amestros obtienen suscripciones gratuitas!" # {change}
@@ -966,8 +966,8 @@
 #    keep_using: "Keep Using"
 #    switch_to: "Switch To"
 #    greetings: "Greetings!"
-#    learn_p: "Learn Python"
-#    learn_j: "Learn JavaScript"
+    learn_p: "Aprender Python"
+    learn_j: "Aprender JavaScript"
 #    language_cannot_change: "Language cannot be changed once students join a class."
 #    back_classrooms: "Back to my classrooms"
 #    back_courses: "Back to my courses"
@@ -977,7 +977,7 @@
 #    remove_student: "remove student"
 #    assign: "Assign"
 #    to_assign: "to assign paid courses."
-#    teacher: "Teacher"
+    teacher: "Maestro"
 #    complete: "Complete"
 #    none: "None"
 #    save: "Save"
@@ -1092,7 +1092,7 @@
 #    active_courses: "active courses"
 #    no_students: "No students yet!"
 #    add_students1: "add students"
-#    view_edit: "view/edit"
+    view_edit: "vee/editar"
 #    students_enrolled: "students enrolled"
 #    length: "Length:"

@@ -1491,16 +1491,16 @@
     campaigns: "Campañas"
     poll: "Encuesta"
     user_polls_record: "Historia de Visitas de Encuestas"
-#    course: "Course"
-#    courses: "Courses"
+    course: "Curso"
+    courses: "Cursos"
 #    course_instance: "Course Instance"
 #    course_instances: "Course Instances"
 #    classroom: "Classroom"
 #    classrooms: "Classrooms"
-#    clan: "Clan"
-#    clans: "Clans"
+    clan: "Clan"
+    clans: "Clanes"
 #    members: "Members"
-#    users: "Users"
+    users: "Usuarios"

   concepts:
     advanced_strings: "Cadenas - Avanzado"


Added user sync data setting and reverting indentation.

--- packages/rocketchat-ldap/config_server.coffee
+++ packages/rocketchat-ldap/config_server.coffee
@@ -2,11 +2,12 @@

 Meteor.startup ->
 	RocketChat.settings.addGroup 'LDAP'
-	RocketChat.settings.add 'LDAP_Enable'     , false    , { type: 'boolean', group: 'LDAP', public: true }
-	RocketChat.settings.add 'LDAP_Url'        , 'ldap://', { type: 'string' , group: 'LDAP' }
-	RocketChat.settings.add 'LDAP_Port'       , '389'    , { type: 'string' , group: 'LDAP' }
-	RocketChat.settings.add 'LDAP_DN'         , ''       , { type: 'string' , group: 'LDAP', i18nLabel: 'LDAP_Dn', public: true }
-	RocketChat.settings.add 'LDAP_Bind_Search', ''       , { type: 'string' , group: 'LDAP' }
+	RocketChat.settings.add 'LDAP_Enable', false, { type: 'boolean', group: 'LDAP', public: true }
+	RocketChat.settings.add 'LDAP_Url', 'ldap://', { type: 'string' , group: 'LDAP' }
+	RocketChat.settings.add 'LDAP_Port', '389', { type: 'string' , group: 'LDAP' }
+	RocketChat.settings.add 'LDAP_DN', '', { type: 'string' , group: 'LDAP', i18nLabel: 'LDAP_Dn', public: true }
+	RocketChat.settings.add 'LDAP_Bind_Search', '', { type: 'string' , group: 'LDAP' }
+	RocketChat.settings.add 'LDAP_Sync_User_Data', false, { type: 'boolean' , group: 'LDAP' }

 timer = undefined


further integration test

further integration test

--- app/scripts/robot/radio.coffee
+++ app/scripts/robot/radio.coffee
@@ -30,17 +30,20 @@
         value: num
         })

-    # SerialPort = require("serialport").SerialPort
-    # radioAddr = "AAAAAAAAAAAAAAAA"
-    # serialPort = new SerialPort("/dev/ttyUSB0",
-    #   baudrate: 57600
-    # )
+    SerialPort = require("serialport").SerialPort
+    radioAddr = "AAAAAAAAAAAAAAAA"
+    serialPort = new SerialPort("/dev/ttyUSB0",
+      baudrate: 57600
+    )

-    # radio = require('kyleradio')
-    # rad = radio.Radio()
+    radio = require('kyleradio')
+    rad = new radio.Radio()

-    # rad.connectXBee(radioAddr, serialPort)
-
+    rad.connectXBee(radioAddr, serialPort)
+    $interval( ->
+      console.log 'try to send shit'
+      rad.send({'PiELESAnalogValues': [127,127,127,127,127,127,127]})
+    , 100)

     return {
       init: ->


Added InsertIntoDOM function to the view.

--- src/view/view.coffee
+++ src/view/view.coffee
@@ -104,10 +104,13 @@
     isInDOM = document.body.contains(parentNode)
     @propagateToSubviews('viewWillAppear') if isInDOM

-    parentNode.appendChild(@node) if parentNode != @node
+    @insertIntoDOM(parentNode)

     @propagateToSubviews('isInDOM', isInDOM)
     @propagateToSubviews('viewDidAppear') if isInDOM
+
+  insertIntoDOM: (parentNode) ->
+    parentNode.appendChild(@node) if parentNode != @node

   removeFromParentNode: ->
     node = @get('node')


add gulpfile reloader task, it can have some work done though

--- app/templates/_Gulpfile.coffee
+++ app/templates/_Gulpfile.coffee
@@ -1,25 +1,28 @@
 # Gulp
-gulp        	= require "gulp"
-coffee      	= require "gulp-coffee"
-concat      	= require "gulp-concat"
-exec        	= require "gulp-exec"
-minifyCSS   	= require "gulp-minify-css"
-plumber     	= require "gulp-plumber"
-rename      	= require "gulp-rename"
-sass        	= require "gulp-sass"
-uglify      	= require "gulp-uglify"
-gutil       	= require "gulp-util"
-watch       	= require "gulp-watch"
-shell       	= require "gulp-shell"
-browserSync 	= require "browser-sync"
-reload      	= browserSync.reload
-imagemin    	= require "gulp-imagemin"
-pngquant    	= require "imagemin-pngquant"
-rsyncwrapper	= require "rsyncwrapper"
-rsync 				= rsyncwrapper.rsync
+gulp        		= require "gulp"
+coffee      		= require "gulp-coffee"
+concat      		= require "gulp-concat"
+exec        		= require "gulp-exec"
+minifyCSS   		= require "gulp-minify-css"
+plumber     		= require "gulp-plumber"
+rename      		= require "gulp-rename"
+sass        		= require "gulp-sass"
+uglify      		= require "gulp-uglify"
+gutil       		= require "gulp-util"
+watch       		= require "gulp-watch"
+shell       		= require "gulp-shell"
+browserSync 		= require "browser-sync"
+reload      		= browserSync.reload
+imagemin    		= require "gulp-imagemin"
+pngquant    		= require "imagemin-pngquant"
+rsyncwrapper		= require "rsyncwrapper"
+rsync 					= rsyncwrapper.rsync
+cp 							= require 'child_process'
+spawn 					= cp.spawn

 # Extra
-extend 				= require "extend"
+extend 					= require "extend"
+defaultProcess	= null

 pkg   = require './package.json'
 conf  = require './Gulpconfig.json'
@@ -77,6 +80,21 @@

 #*------------------------------------*\
+#   $RESTART
+# 	Taken from: http://noxoc.de/2014/06/25/reload-gulpfile-js-on-change/
+#*------------------------------------*/
+gulp.task 'auto-reload', () ->
+	process = undefined
+	restart = () ->
+		if process != undefined
+			process.kill()
+		process = spawn 'gulp', ['default'], {stdio: 'inherit'}
+
+	gulp.watch 'Gulpfile.coffee', restart
+	restart()
+
+
+#*------------------------------------*\
 #   $CONTRIB-COFFEE
 #*------------------------------------*/
 gulp.task "coffee", () ->


bugfix: drawing task choice values

bugfix: drawing task choice values

--- project.coffee
+++ project.coffee
@@ -184,6 +184,7 @@
       choices: [{
         type: Pinpoint
         label: 'Species'
+        value: 'species'
         color: '#333'
         checked: true
         details:[{
@@ -202,6 +203,7 @@
       },{
         type: Pinpoint
         label: 'Inscription'
+        value: 'inscription'
         color: '#333'
         details:[{
           type: 'textarea'
@@ -215,6 +217,7 @@
       },{
         type: Pinpoint
         label: 'Contributor'
+        value: 'contributor'
         color: '#333'
         details:[{
           type: 'text'


Remove child tools for data source menu

Remove child tools for data source menu

--- app/views/settings/data.coffee
+++ app/views/settings/data.coffee
@@ -30,7 +30,7 @@
   updateValidSourceTools: =>
     @intSources = []
     @model.collection?.each (tool) =>
-      unless @model is tool
+      unless @model is tool or @model is tool.sourceTool()
         @intSources.push { name: tool.get('name'), id: tool.id }

 module.exports = DataSettings


Removed unnecessary function (leftover from previous versions of the code).

--- lib/typeresolution.coffee
+++ lib/typeresolution.coffee
@@ -6,15 +6,10 @@
 primitiveTypes = ['boolean', 'string', 'number', 'array', 'enum', 'object']

-# Checks whether given type name is one of primitive types.
-isPrimitiveType = (type) ->
-  type in primitiveTypes
-
-
 # Calls given function with an error in case given type name is not one
 # of primitive types.
 ensurePrimitiveType = (type, cb) ->
-  if not isPrimitiveType type
+  if type not in primitiveTypes
     cb new Error "Unable to resolve type: #{type}"
   else
     cb null


maybe its ready to pre-alpha test

maybe its ready to pre-alpha test

--- app/socket_server.coffee
+++ app/socket_server.coffee
@@ -44,6 +44,18 @@
     message.text = message.text.slice(7)
     return message

+
+help = (message, is_master)->
+    message.event_type = "system_message"
+    message.text = "Command list:
"+
+        "
/me blah-blah — you do blah-blah as event
"+
+        "
/roll XdY+Z — you roll dice
"
+    if is_master
+        message.text += "
/event blah-blah — show blah-blah as global event
"
+    message.text += "
"
+    message.allow_send = false
+    return message
+
 on_message = (socket, message_text)->
     socket.get "data", (err, data)->
         unless data?
@@ -74,6 +86,9 @@
             if message.text.indexOf("/event ") == 0
                 if data.user.name == room.master.name
                     message = master_event message
+
+            if message.text.indexOf("/help") == 0
+                message = help message, data.user.name == room.master.name

@@ -121,6 +136,7 @@
                     socket.broadcast.to(data.room.name).emit "new_player",
                         timestamp: now
                         username: data.displayname
+                        user_id: user._id
                         room: room.name
                     socket.set "data", data
                     socket.emit "connected",


Proper URI construction for API calls

Proper URI construction for API calls

--- scripts/api.coffee
+++ scripts/api.coffee
@@ -8,7 +8,6 @@

 # Todo: Cache resources.
-# Todo: Proper URI construction instead of string concatenations.

 $ = require 'jquery'
@@ -68,14 +67,15 @@
         variations: root.variation_collection.uri

   annotation: (uri) =>
-    @request uri + '?embed=original_data_source,annotated_data_source'
+    @request URI(uri).setQuery 'embed',
+      'original_data_source,annotated_data_source'
     .then ({annotation}) -> annotation

   annotations: ({filter, page_number}={}) =>
-    uri = @uris.annotations +
-          '?embed=original_data_source,annotated_data_source'
-    uri += '&annotated_data_source.user=' +
-           encodeURIComponent @current_user?.uri if filter == 'own'
+    uri = URI(@uris.annotations).setQuery 'embed',
+      'original_data_source,annotated_data_source'
+    if filter == 'own'
+      uri.setQuery 'annotated_data_source.user', @current_user?.uri
     @collection uri, 'annotation', {page_number}

   create_annotation: (data) =>
@@ -95,17 +95,17 @@
           "Unable to authenticate with login '#{@login}' and password '***'"

   coverages: ({sample, page_number}={}) =>
-    uri = @uris.coverages + '?embed=data_source'
-    uri += "&sample=#{ encodeURIComponent sample }" if sample?
+    uri = URI(@uris.coverages).setQuery 'embed', 'data_source'
+    uri.setQuery 'sample', sample if sample?
     @collection uri, 'coverage', {page_number}

   data_source: (uri) =>
-    @request uri + '?embed=user'
+    @request URI(uri).setQuery 'embed', 'user'
     .then ({data_source}) -> data_source

   data_sources: ({filter, page_number}={}) =>
-    uri = @uris.data_sources
-    uri += "?user=#{ encodeURIComponent @current_user?.uri }" if filter == 'own'
+    uri = URI @uris.data_sources
+    uri.setQuery 'user', @current_user?.uri if filter == 'own'
     @collection uri, 'data_source', {page_number}

   create_data_source: (data) =>
@@ -142,14 +142,14 @@
     @request uri, method: 'DELETE'

   sample: (uri) =>
-    @request uri + '?embed=user,groups'
+    @request URI(uri).setQuery embed: 'user,groups'
     .then ({sample}) -> sample

   samples: ({filter, group, page_number}={}) =>
-    uri = @uris.samples
-    uri += "?user=#{ encodeURIComponent @current_user?.uri }" if filter == 'own'
-    uri += '?public=true' if filter == 'public'
-    uri += "?groups=#{ encodeURIComponent group }" if group?
+    uri = URI @uris.samples
+    uri.setQuery 'user', @current_user?.uri if filter == 'own'
+    uri.setQuery 'public', 'true' if filter == 'public'
+    uri.setQuery 'groups', group if group?
     @collection uri, 'sample', {page_number}

   create_sample: (data) =>
@@ -168,8 +168,8 @@
     .then ({token}) -> token

   tokens: ({filter, page_number}={}) =>
-    uri = @uris.tokens
-    uri += "?user=#{ encodeURIComponent @current_user?.uri }" if filter == 'own'
+    uri = URI @uris.tokens
+    uri.setQuery 'user', @current_user?.uri if filter == 'own'
     @collection uri, 'token', {page_number}

   create_token: (data) =>
@@ -202,8 +202,8 @@
     @request uri, method: 'DELETE'

   variations: ({sample, page_number}={}) =>
-    uri = @uris.variations + '?embed=data_source'
-    uri += "&sample=#{ encodeURIComponent sample }" if sample?
+    uri = URI(@uris.variations).setQuery 'embed', 'data_source'
+    uri.setQuery 'sample', sample if sample?
     @collection uri, 'variation', {page_number}

   variant: (uri, {query, region}={}) =>
@@ -213,8 +213,7 @@
     json =
       queries: [name: 'QUERY', expression: query]
       region: region
-    uri += "?__json__=#{ encodeURIComponent (JSON.stringify json) }"
-    @request uri
+    @request URI(uri).setQuery '__json__', JSON.stringify(json)
     .then ({variant}) ->
       # We only support one query, so we flatten the query results.
       variant.coverage = variant.annotations.QUERY.coverage
@@ -231,8 +230,8 @@
     json =
       queries: [name: 'QUERY', expression: query]
       region: region
-    uri += "?__json__=#{ encodeURIComponent (JSON.stringify json) }"
-    @collection uri, 'variant', {page_number}
+    @collection URI(uri).setQuery('__json__', JSON.stringify(json)),
+      'variant', {page_number}
     .then ({items, pagination}) ->
       # We only support one query, so we flatten the query results.
       for item in items
@@ -266,8 +265,7 @@
       pagination: {total: 0, current: 0}

   request: (uri, options={}) =>
-    uri = URI(uri).absoluteTo(@root).toString()
-    xhr = $.ajax uri,
+    xhr = $.ajax URI(uri).absoluteTo(@root).toString(),
       beforeSend: (r) =>
         addAuth r, @login, @password
         addVersion r


whitespace

whitespace

--- app/assets/javascripts/uploadcare/widget/dialog.js.coffee
+++ app/assets/javascripts/uploadcare/widget/dialog.js.coffee
@@ -22,15 +22,15 @@

       $ .Deferred ->
           $.extend this, dialogUiMixin
-
+
           @settings = settings
-
+
           @_createDialog()
-
+
           @always @_closeDialog
         .pipe((args...) -> ns.toUploader(settings, args...))
         .promise()
-
+

     dialogUiMixin =
       _createDialog: ->
@@ -106,7 +106,3 @@
               .show()

         @notify @currentTab
-
-
-
-


Set all user values as files

Set all user values as files

--- app/assets/javascripts/uploadcare/widget/widget.js.coffee
+++ app/assets/javascripts/uploadcare/widget/widget.js.coffee
@@ -8,7 +8,6 @@
     namespace,
     utils,
     uploads,
-    files,
     jQuery: $
   } = uploadcare

@@ -72,11 +71,13 @@

       value: (value) ->
         if value?
-          if value.info
-            @__setFile(value)
-          else if @element.val() != value
-            @element.val(value)
-            @reloadInfo()
+          if @element.val() != value
+            @__setFile(
+              if value.info
+                value
+              else
+                uploadcare.fileFrom(@settings, 'uploaded', value)
+            )
           this
         else
           @element.val()


chore(web): don't put html files to dist

--- apps/actor-web/gulpfile.coffee
+++ apps/actor-web/gulpfile.coffee
@@ -75,9 +75,6 @@
     .pipe connect.reload()

 gulp.task 'html', ->
-  gulp.src ['./app/**/*.html']
-    .pipe gulp.dest './dist/app/'
-    .pipe connect.reload()
   gulp.src ['./index2.html']
     .pipe gulp.dest './dist'
     .pipe connect.reload()


Filter any command that contains 'pjcbot help'

--- scripts/pjc.coffee
+++ scripts/pjc.coffee
@@ -6,7 +6,7 @@

   robot.listenerMiddleware (context, next, done) ->
     # console.log context.response.message
-    if context.response.message.text == 'pjcbot help'
+    if ~context.response.message.text.indexOf('pjcbot help')
       context.response.send context.response.random lulz
       context.response.send "I'm sorry, @#{context.response.message.user.name}, I can't let you do that."
       done()


Add a renderError method on widget that is called when something bad happens during datasources retreival

--- src/client/widget.coffee
+++ src/client/widget.coffee
@@ -80,6 +80,8 @@

     beforeRender: (data)-> data

+    renderError: ->
+
     log: (msg)=>
       if @options.debug
         console.warn(@options.name, ":", @options.id, msg)
@@ -101,7 +103,9 @@
         widgetDeferred = @sandbox.data.when.apply(undefined, promises)
         templateDeferred = @sandbox.template.load(@templates, @ref)
         @data = {}
-        $.when(widgetDeferred, templateDeferred).done (data, tpls)=>
+        readyDfd = $.when(widgetDeferred, templateDeferred)
+        readyDfd.fail _.bind(@renderError, @)
+        readyDfd.done (data, tpls)=>
           args = data
           _.map keys, (k,i)=>
             @data[k] = args[i]


Call the prototype method directly.

Call the prototype method directly.

h/t @maxbrunsfeld

--- src/workspace.coffee
+++ src/workspace.coffee
@@ -47,7 +47,7 @@
     # Etch, in which case it'd be `new`d. And when it's `new`d, `this` is always
     # the newly created object.
     realThis = this
-    @buildTextEditor = (params) -> realThis.buildTextEditor_(params)
+    @buildTextEditor = -> Workspace.prototype.buildTextEditor.apply(realThis, arguments)

     @panelContainers =
       top: new PanelContainer({location: 'top'})
@@ -556,7 +556,7 @@
   # Extended: Create a new text editor.
   #
   # Returns a {TextEditor}.
-  buildTextEditor_: (params) ->
+  buildTextEditor: (params) ->
     params = _.extend({
       @config, @notificationManager, @packageManager, @clipboard, @viewRegistry,
       @grammarRegistry, @project, @assert, @applicationDelegate


Use a PID file

Use a PID file

--- gitcommander.coffee
+++ gitcommander.coffee
@@ -2,7 +2,7 @@
 path = require "path"
 nconf = require "nconf"

-if process.env.XDG_CONFIG_HOME?
+if "XDG_CONFIG_HOME" of process.env
   CONFIG_HOME = process.env.XDG_CONFIG_HOME
 else
   CONFIG_HOME = path.join process.env.HOME, ".config"
@@ -16,6 +16,24 @@
 GIT_OPTS = nconf.get "git"
 RECENCY = nconf.get "recency"
 TIMEOUT = nconf.get "timeout"
+
+# write pidfile
+PIDFILE = nconf.get "pidfile"
+console.log "* Writing PID file #{PIDFILE}."
+fs = require "fs"
+fs.writeFileSync PIDFILE, process.pid
+
+# delete pidfile on exit
+process.on "exit", (code) ->
+  console.log "* Deleting PID file #{PIDFILE}."
+  fs.unlinkSync PIDFILE
+
+# call exit on SIGINT and SIGTERM
+exitHandler = (signal) ->
+  console.log "* Received #{signal}. Exiting..."
+  process.exit(0)
+process.on "SIGINT", -> exitHandler("SIGINT")
+process.on "SIGTERM", -> exitHandler("SIGTERM")

 # setup github api
 GitHubApi = require "github"


Improved placeholder support

Improved placeholder support

--- grammars/marko.cson
+++ grammars/marko.cson
@@ -34,7 +34,7 @@
     include: "#tag-html"
   }
   {
-    include: "#placeholder"
+    include: "#placeholder-patterns"
   }
   {
     include: "#scriptlet"
@@ -56,7 +56,19 @@
         captures:
           "1":
             name: "support.function.marko-attribute"
-        match: "\\s(for|if|else-if|w-[a-zA-Z0-9:_-]+|marko-[a-zA-Z0-9:_.-]+lasso-[a-zA-Z0-9:_.-]+)(?=(\\s|$|[>(]|/>))"
+        match: "\\s(for|if|else-if|unless)(?=([(]))"
+      }
+      {
+        captures:
+          "1":
+            name: "support.function.marko-attribute"
+        match: "\\s(else|w-[a-zA-Z0-9:_-]+|marko-[a-zA-Z0-9:_.-]+)(?=(\\s|$|[>(]|/>))"
+      }
+      {
+        captures:
+          "1":
+            name: "support.function.marko-attribute"
+        match: "\\s(w-[a-zA-Z0-9:_-]+|lasso-[a-zA-Z0-9:_.-]+)(?=(\\s|$|[>(=]|/>))"
       }
       {
         captures:
@@ -272,7 +284,7 @@
         name: "constant.character.escape.js"
       }
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
     ]
   "expression-string-single":
@@ -291,7 +303,7 @@
         name: "constant.character.escape.js"
       }
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
     ]
   "expression-ternary-if":
@@ -321,7 +333,7 @@
         include: "#comment-html"
       }
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
     ]
   "html-line-concise":
@@ -341,7 +353,7 @@
         include: "#comment-html"
       }
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
     ]
   "open-tag-end":
@@ -359,7 +371,7 @@
         include: "#tag-html"
       }
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
       {
         include: "#scriptlet"
@@ -371,7 +383,7 @@
     end: "(?=</)"
     patterns: [
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
       {
         include: "source.js"
@@ -383,7 +395,7 @@
     end: "(?=</)"
     patterns: [
       {
-        include: "#placeholder"
+        include: "#placeholder-patterns"
       }
       {
         include: "source.css"
@@ -400,6 +412,24 @@
     patterns: [
       {
         include: "#expression"
+      }
+    ]
+  "placeholder-escaped":
+    comment: "\\${"
+    match: "\\\\[$][!]?[{]"
+  "placeholder-escaped-escaped":
+    comment: "\\\\${"
+    match: "\\\\\\\\(?=[$][!]?[{])"
+  "placeholder-patterns":
+    patterns: [
+      {
+        include: "#placeholder-escaped-escaped"
+      }
+      {
+        include: "#placeholder-escaped"
+      }
+      {
+        include: "#placeholder"
       }
     ]
   scriptlet:


config: remove paymentwebhook

config: remove paymentwebhook

--- config/workers.coffee
+++ config/workers.coffee
@@ -134,22 +134,6 @@
         locations       : [ { location: "/xhr" } ]
       healthCheckURL    : "http://localhost:#{KONFIG.social.port}/healthCheck"
       versionURL        : "http://localhost:#{KONFIG.social.port}/version"
-
-    paymentwebhook      :
-      group             : "socialapi"
-      ports             :
-        incoming        : KONFIG.paymentwebhook.port
-      supervisord       :
-        stopwaitsecs    : 20
-        command         :
-          run           : "#{GOBIN}/paymentwebhook -kite-init=true"
-          watch         : "make -C %(ENV_KONFIG_PROJECTROOT)s/go/src/socialapi paymentwebhookdev"
-      healthCheckURL    : "http://localhost:#{KONFIG.paymentwebhook.port}/healthCheck"
-      versionURL        : "http://localhost:#{KONFIG.paymentwebhook.port}/version"
-      nginx             :
-        locations       : [
-          { location    : "= /-/payments/stripe/webhook" },
-        ]

     vmwatcher           :
       group             : "environment"


'analog' parameter deleted in vanalogpad

--- lib/_vgamepadcontrol.coffee
+++ lib/_vgamepadcontrol.coffee
@@ -79,7 +79,6 @@
             y           = if (param.y?)             then param.y            else SCREEN_HEIGHT - ((100 / 2) * scale)
             visible     = if (param.visible?)       then param.visible      else true
             kind        = if (param.kind?)          then param.kind         else 0
-            analog      = if (param.analog?)        then param.analog       else false

             image       = if (param.image?)         then param.image        else undefined
             buttonscale = if (param.buttonscale?)   then param.buttonscale  else 1
@@ -88,17 +87,11 @@
         # パッドの色を設定
         switch (kind)
             when 0
-                if (analog)
-                    padname = "_apad_w"
-                    padname2 = "_apad2_w"
-                else
-                    padname = "_pad_w"
+                padname = "_apad_w"
+                padname2 = "_apad2_w"
             when 1
-                if (analog)
-                    padname = "_apad_b"
-                    padname2 = "_apad2_b"
-                else
-                    padname = "_pad_b"
+                padname = "_apad_b"
+                padname2 = "_apad2_b"

         if (!image?)
             switch (kind)
@@ -111,23 +104,22 @@
         else
             buttonname = image

-        if (analog)
-            @vgamecursor = addObject
-                image: padname2
-                x: @x
-                y: @y
-                width: 40
-                height: 40
-                scaleX: scale
-                scaleY: scale
-                visible: false
-                animlist: [
-                    [100, [0]]
-                ]
-                scene: _SYSTEMSCENE
+        @vgamecursor = addObject
+            image: padname2
+            x: @x
+            y: @y
+            width: 40
+            height: 40
+            scaleX: scale
+            scaleY: scale
+            visible: false
+            animlist: [
+                [100, [0]]
+            ]
+            scene: _SYSTEMSCENE

         @vgamepad = addObject
-            motionObj: if (analog) then _vanalogpad else _vdigipad
+            motionObj: _vanalogpad
             image: padname
             x: @x
             y: @y


Don't Hard Code Tab Lengths

Don't Hard Code Tab Lengths

A package should never enforce a tab length that ignores what the user has defined. In addition, a tab length of 2 violates Rust formatting standards.


Fixes grunt task

Fixes grunt task

--- grunt/uglify.coffee
+++ grunt/uglify.coffee
@@ -1,14 +1,12 @@
 module.exports =
   options:
     report: 'gzip'
-  all:
-    files:
-      'dist/<%= package.name %>.all.min.js': 'dist/<%= package.name %>.all.js'
   compact:
     files: [{
       expand: true
-      cwd: 'dist/files/'
-      src: '**/*.js'
-      dest: 'dist/files/'
+      cwd: 'dist/'
+      src: ['**/*.js']
+      dest: 'dist/'
       ext: '.min.js'
+      extDot: 'last'
     }]


Atom config

Atom config

Signed-off-by: Salim Djerbouh <64b2b6d12bfe4baae7dad3d018f8cbf6b0e7a044@caddydz.me>

--- src/atom/config.cson
+++ src/atom/config.cson
@@ -1,67 +1,67 @@
 "*":
-  "atom-beautify":
+	"atom-beautify":
 	general:
-	  beautifyEntireFileOnSave: false
-  autosave:
-	enabled: true
-  core:
-	autoHideMenuBar: true
-	automaticallyUpdate: false
-	closeDeletedFileTabs: true
-	closeEmptyWindows: false
+		beautifyEntireFileOnSave: false
+	autosave:
+		enabled: true
+	core:
+		autoHideMenuBar: true
+		automaticallyUpdate: false
+		closeDeletedFileTabs: true
+		closeEmptyWindows: false
 	disabledPackages: [
-	  "wrap-guide"
-	  "semantic-ui"
-	  "selector-to-tag"
+		"wrap-guide"
+		"semantic-ui"
+		"selector-to-tag"
 	]
 	openEmptyEditorOnStart: false
-	projectHome: "/home/caddy/Documents"
+	projectHome: "/home/caddy/Code"
 	telemetryConsent: "no"
 	themes: [
-	  "atom-material-ui"
-	  "atom-material-syntax"
+		"atom-material-ui"
+		"atom-material-syntax"
 	]
 	titleBar: "custom"
 	useProxySettingsWhenCallingApm: false
-  editor:
-	fontFamily: "Fira Code"
-	fontSize: 20
-	scrollPastEnd: true
-	softWrap: true
-	zoomFontWhenCtrlScrolling: true
-  "exception-reporting":
+	editor:
+		fontFamily: "Fira Code"
+		fontSize: 20
+		scrollPastEnd: true
+		softWrap: true
+		zoomFontWhenCtrlScrolling: true
+	"exception-reporting":
 	userId: "bd96517d-f96f-40a5-8f69-d480ed222c89"
-  "linter-jshint":
+	"linter-jshint":
 	lintInlineJavaScript: true
-  "linter-ui-default":
+	"linter-ui-default":
 	panelHeight: 69
 	showPanel: true
-  "selector-to-tag":
+	"selector-to-tag":
 	activeForFileTypes: [
-	  "htm"
-	  "html"
-	  "kit"
-	  "shtml"
-	  "tmpl"
-	  "tpl"
-	  "xhtml"
-	  "php"
-	  "vue"
-	  "js"
-	  "blade.php"
+		"htm"
+		"html"
+		"kit"
+		"shtml"
+		"tmpl"
+		"tpl"
+		"xhtml"
+		"php"
+		"vue"
+		"js"
+		"blade.php"
 	]
 	closeSelfclosingTags: true
 	expandBlockTags: true
-  wakatime:
-	apikey: "Saved in your ~/.wakatime.cfg file"
-	debug: true
-  welcome:
-	showOnStartup: false
+	wakatime:
+		apikey: "Saved in your ~/.wakatime.cfg file"
+		debug: true
+	welcome:
+		showOnStartup: false
 ".blade.html.php":
-  editor:
-	commentEnd: " --}}"
-	commentStart: "{{-- "
+	editor:
+		commentEnd: " --}}"
+		commentStart: "{{-- "
 ".blade.html.php.text":
-  editor:
-	commentEnd: " --}}"
-	commentStart: "{{-- "
+	editor:
+		commentEnd: " --}}"
+		commentStart: "{{-- "


fsfile: added a missing method - by @fatihacet

--- client/app/lib/util/fs/fsfile.coffee
+++ client/app/lib/util/fs/fsfile.coffee
@@ -194,6 +194,10 @@

   abort: -> @emit "AbortRequested"

+
+  isDummyFile: -> return @path.indexOf('localfile:/Untitled.txt') is 0
+
+
   save: (contents = '', callback = null, useEncoding = yes) ->

     @emit "fs.save.started"


use backbone global event bus

use backbone global event bus

--- client/code/view/tool_content.coffee
+++ client/code/view/tool_content.coffee
@@ -1,7 +1,7 @@
 class Cu.View.ToolContent extends Backbone.View

   initialize: ->
-    @on 'tool:installed', @onInstalled, this
+    Backbone.on 'tool:installed', @onInstalled, this

   render: ->
     @$el.html """
Loading tool
"""


added missing fields to fetch script

added missing fields to fetch script

--- data/fetch.coffee
+++ data/fetch.coffee
@@ -27,6 +27,8 @@
   "subtype",
   "text",
   "cost",
+  "advancementcost",
+  "agendapoints",
   "baselink",
   "influencelimit",
   "minimumdecksize",
@@ -42,6 +44,7 @@
   "cyclenumber",
   "side",
   "uniqueness",
+  "memoryunits",
   "strength",
   "trash"
 ]


变更调用父类的this

变更调用父类的this

--- src/biz/asset.coffee
+++ src/biz/asset.coffee
@@ -21,7 +21,7 @@
 _util.inherits(Asset, _store.BaseEntity)

 Asset.prototype.find = (condition, callback)->
-  Asset.super_.prototype.find.call this, condition, (err, result)->
+  Asset.super_.prototype.find.call _asset, condition, (err, result)->
     _.each result.items, (item)->
       item.url = "/assets/#{item.project_id}/#{item.file_name}"

@@ -30,7 +30,7 @@
 Asset.prototype.readFile = (req, res, next)->
   project_id = req.params.project_id
   filename = req.params.filename
-  fullpath = _path.join _utility.rootPath, _config.assets, project_id, filename
+  fullpath = _path.join _utility.rootPath, "asset", project_id, filename
   res.sendfile fullpath

 #处理上传文件
@@ -62,7 +62,8 @@
     _air.save relation, (err, relation_id)->
   ###

-module.exports = new Asset(_schema)
+_asset = new Asset(_schema)
+module.exports = _asset

 #保存素材
 saveAsset = (tempFile, project_id)->


fix spell

fix spell

--- spec/text-object-spec.coffee
+++ spec/text-object-spec.coffee
@@ -550,7 +550,7 @@
             mode: ['visual', 'characterwise'] # FIXME to 'characterwise'

         describe "as operator target", ->
-          it "change inser-pair", ->
+          it "change inner-pair", ->
             ensure "c i B",
               textC: """
               {
@@ -558,7 +558,7 @@
               }
               """
               mode: 'insert'
-          it "delete inser-pair", ->
+          it "delete inner-pair", ->
             ensure "d i B",
               textC: """
               {
@@ -644,7 +644,7 @@
             mode: ['visual', 'characterwise'] # FIXME to 'characterwise'

         describe "as operator target", ->
-          it "change inser-pair", ->
+          it "change inner-pair", ->
             ensure "c a B",
               textC: """
               |
@@ -652,7 +652,7 @@
               hello
               """
               mode: 'insert'
-          it "delete inser-pair", ->
+          it "delete inner-pair", ->
             ensure "d a B",
               textC: """
               |


Fixes #49 by stopin propogation of the mousedown event in the popupparameter editor box

--- web/scripts/playerCodeEditor.coffee
+++ web/scripts/playerCodeEditor.coffee
@@ -117,7 +117,7 @@
             else
                 line = @editor.createBlankFunctionHeader(command) + ';'
                 funct = codeEditor.insertCommand
-
+
             button = jQuery '<button>', {
                 id: command,
                 value: command,
@@ -220,8 +220,8 @@
                 usesRemaining = remaining[command]
             else
                 usesRemaining = @commands[command]['usesRemaining']
-
-
+
+
             button.attr 'title',@toUsesRemainingText(usesRemaining, @commands[command].maxUses)
             if usesRemaining <= 0
                 button.attr 'disabled', true
@@ -240,8 +240,8 @@
         return 'Can only appear once!' if usesRemaining==1 and maxUses==1
         return 'Can only appear one more time!' if usesRemaining==1
         return"Can be used #{usesRemaining} more times"
-
-
+
+
     moveEditorButtons: =>
         row = @editor.editor.getCursorPosition().row
         maxrows = @editor.editSession.getLength()
@@ -350,6 +350,11 @@
             @parameterPopUp.css 'top', "12px"
             @parameterPopUp.css 'left', gutterOffset + 5

+            # Prevents the ace editor from stealing focus
+            @parameterPopUp.mousedown (mousedownEvent) ->
+                mousedownEvent.stopPropagation()
+                return
+
             @parameterPopUp.show()
             setTimeout (-> jQuery("##{command}-parameter-#{1}").focus(); return), 0
             clickEvent.stopPropagation()
@@ -455,7 +460,7 @@
             @codeText = @initialText

         @enableKeyboardShortcuts()
-
+
         @resetState()
         @onChangeCallback = null
         @editor.on 'change', @onChange
@@ -467,7 +472,7 @@
             code += '\n' + @hiddenSuffix
         return code

-
+
     gotoLine: (row) ->
         column = @editor.getCursorPosition().column
         @editor.gotoLine row, column, true
@@ -561,8 +566,8 @@

     insertLine: ({text, line, currentRow}) ->
         maxRow = @editSession.getLength()
-        currentRow = Math.max(currentRow, @codePrefixLength-1)
-        currentRow = Math.min(currentRow, maxRow-@codeSuffixLength-1  )
+        currentRow = Math.max(currentRow, @codePrefixLength-1)
+        currentRow = Math.min(currentRow, maxRow-@codeSuffixLength-1  )
         currentLine = text.getLine currentRow

         if @commands.hasOwnProperty line
@@ -602,9 +607,9 @@
         @editor.clearSelection()
         @editor.resize()
         @reIndentCode()
-
-        @gotoLine @codePrefixLength + 1 + @findFirstNonCommentLine(@initialText)
-
+
+        @gotoLine @codePrefixLength + 1 + @findFirstNonCommentLine(@initialText)
+
         @editor.renderer.scrollToRow @codePrefixLength
         for name, command of @commands
             command['usesRemaining'] = command['maxUses']


enabled keyboardshortcut for moving lines up/down in editor

--- web/scripts/playerCodeEditor.coffee
+++ web/scripts/playerCodeEditor.coffee
@@ -27,12 +27,17 @@
         @resetText()
         @editor.focus()

+        @enableKeyBoardShortcuts()
         @setUpInsertCommands()
         @addButtonEventListeners()

     getCommandFromLine: (line) ->
         re = /^(.+)\(/
         return re.exec(line)[1]
+
+    enableKeyBoardShortcuts: ->
+        @editor.commands.commands.movelinesup['readOnly'] = true
+        @editor.commands.commands.movelinesdown['readOnly'] = true

     setUpInsertCommands: ->
         ###


Extend createTab to open specific pages.

Example:

    map a createTab http://edition.cnn.com/ http://www.bbc.co.uk/news

which creates two new tabs, but preloaded with these specific URLs.

`2a` creates four new tabs, two copies of each.

Limitation:

- We cannot control the order of the tabs, so we might get CNN then BBC,
  or BBC then CNN.  This happens because command options are stored in
  an object, and we cannot control the order of the keys.

Also, with:

    map a createTab http://www.bbc.co.uk/news http://www.bbc.co.uk/news

we only get one new tab (same reason as above).

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -146,14 +146,30 @@
 # mapped in commands.coffee.
 BackgroundCommands =
   createTab: mkRepeatCommand (request, callback) ->
-    request.url ?= do ->
-      url = Settings.get "newTabUrl"
-      if url == "pages/blank.html"
-        # "pages/blank.html" does not work in incognito mode, so fall back to "chrome://newtab" instead.
-        if request.tab.incognito then "chrome://newtab" else chrome.runtime.getURL newTabUrl
+    request.urls ?=
+      if request.url
+        # If the request contains a URL, then use it.
+        [request.url]
       else
-        url
-    TabOperations.openUrlInNewTab request, (tab) -> callback extend request, {tab, tabId: tab.id}
+        # Otherwise, if we have a registryEntry containing URLs, then use them.
+        urlList = (opt for own opt of request.registryEntry?.options ? {} when Utils.isUrl opt)
+        if 0 < urlList.length
+          urlList
+        else
+          # Otherwise, just create a new tab.
+          url = Settings.get "newTabUrl"
+          if url == "pages/blank.html"
+            # "pages/blank.html" does not work in incognito mode, so fall back to "chrome://newtab" instead.
+            [if request.tab.incognito then "chrome://newtab" else chrome.runtime.getURL newTabUrl]
+          else
+            [url]
+    urls = request.urls[..]
+    do openNextUrl = (request) ->
+      if 0 < urls.length
+        TabOperations.openUrlInNewTab (extend request, {url: urls.pop()}), (tab) ->
+          openNextUrl extend request, {tab, tabId: tab.id}
+      else
+        callback request
   duplicateTab: mkRepeatCommand (request, callback) ->
     chrome.tabs.duplicate request.tabId, (tab) -> callback extend request, {tab, tabId: tab.id}
   moveTabToNewWindow: ({count, tab}) ->


No need to delay. Change transiton style.

--- js/flight.coffee
+++ js/flight.coffee
@@ -99,17 +99,17 @@
       @translate(targetPage, "X", "-" + screenWidth, "0ms")
       window.setTimeout =>
         @translate(currentPage, "X", "100%")
-      , 10
+      , 0
     else
       @translate(targetPage,"X", screenWidth, "0ms")
       window.setTimeout =>
         @translate(currentPage, "X", "-100%")
-      , 10
+      , 0

     window.setTimeout =>
       @translate(targetPage, "X", "0%" )
       @back = false
-    , 10
+    , 0

   # Private: Perform a slide from bottom transition.
   #
@@ -167,7 +167,7 @@
   # Returns nothing.
   translate: (page, axis, distance, duration) ->
     duration = @speed unless duration?
-    page.style.webkitTransition = "#{duration} ease"
+    page.style.webkitTransition = "#{duration} ease-in-out"
     page.style.webkitTransform = "translate#{axis}(#{distance})"

   # Private: Display the current page.


Moved into end-to-end subdirectory.

Moved into end-to-end subdirectory.

--- test/cli-test.coffee
+++ test/cli-test.coffee
@@ -1,483 +0,0 @@
-{assert} = require 'chai'
-{exec} = require 'child_process'
-express = require 'express'
-
-pjson = require '../package.json'
-
-HOSTNAME = 'localhost'
-PORT = 3333
-SERVER = "http://#{HOSTNAME}:#{PORT}"
-
-TEMPLATE_DIR = './templates'
-DFLT_TEMPLATE_FILE = "#{TEMPLATE_DIR}/hooks.js"
-FIXTURE_DIR = './test/fixtures'
-RAML_DIR = "#{FIXTURE_DIR}"
-HOOK_DIR = "#{FIXTURE_DIR}"
-SCHEMA_DIR = "#{FIXTURE_DIR}/schemas"
-
-CMD_PREFIX = ''
-ABAO_BIN = './bin/abao'
-MOCHA_BIN = './node_modules/mocha/bin/mocha'
-
-stderr = ''
-stdout = ''
-report = ''
-exitStatus = null
-
-receivedRequest = {}
-
-execCommand = (cmd, callback) ->
-  stderr = ''
-  stdout = ''
-  report = ''
-  exitStatus = null
-
-  cli = exec CMD_PREFIX + cmd, (error, out, err) ->
-    stdout = out
-    stderr = err
-    try
-      report = JSON.parse out
-
-    if error
-      exitStatus = error.code
-
-  cli.on 'close', (code) ->
-    exitStatus = code if exitStatus == null and code != undefined
-    callback()
-
-describe 'Command line interface', () ->
-
-  describe 'when run with "one and done" options', (done) ->
-
-    describe 'when RAML argument unnecessary', () ->
-
-      describe 'when invoked with "--reporters" option', () ->
-        reporters = ''
-
-        before (done) ->
-          execCommand "#{MOCHA_BIN} --reporters", () ->
-            reporters = stdout
-            execCommand "#{ABAO_BIN} --reporters", done
-
-        it 'exit status should be 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should print same output as `mocha --reporters`', () ->
-          assert.equal stdout, reporters
-
-
-      describe 'when invoked with "--version" option', () ->
-        before (done) ->
-          cmd = "#{ABAO_BIN} --version"
-
-          execCommand cmd, done
-
-        it 'should exit with status 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should print version number to stdout', () ->
-          assert.equal stdout.trim(), pjson.version
-
-
-      describe 'when invoked with "--help" option', () ->
-        before (done) ->
-          cmd = "#{ABAO_BIN} --help"
-
-          execCommand cmd, done
-
-        it 'should exit with status 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should print usage to stdout', () ->
-          assert.equal stdout.split('\n')[0], 'Usage:'
-
-    describe 'when RAML argument required', () ->
-
-      describe 'when invoked with "--names" option', () ->
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --names"
-
-          execCommand cmd, done
-
-        it 'exit status should be 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should print names', () ->
-          assert.include stdout, 'GET /machines -> 200'
-
-        it 'should not run tests', () ->
-          assert.notInclude stdout, '0 passing'
-
-
-      describe 'when invoked with "--generate-hooks" option', () ->
-        describe 'by itself', () ->
-          before (done) ->
-            ramlFile = "#{RAML_DIR}/single-get.raml"
-            cmd = "#{ABAO_BIN} #{ramlFile} --generate-hooks"
-
-            execCommand cmd, done
-
-          it 'exit status should be 0', () ->
-            assert.equal exitStatus, 0
-
-          it 'should print skeleton hookfile', () ->
-            assert.include stdout, '// ABAO hooks file'
-
-          it 'should not run tests', () ->
-            assert.notInclude stdout, '0 passing'
-
-
-        describe 'with "--template" option', () ->
-          before (done) ->
-            templateFile = "#{TEMPLATE_DIR}/hookfile.js"
-            ramlFile = "#{RAML_DIR}/single-get.raml"
-            cmd = "#{ABAO_BIN} #{ramlFile} --generate-hooks --template #{templateFile}"
-
-            execCommand cmd, done
-
-          it 'exit status should be 0', () ->
-            assert.equal exitStatus, 0
-
-          it 'should print skeleton hookfile', () ->
-            assert.include stdout, '// ABAO hooks file'
-
-          it 'should not run tests', () ->
-            assert.notInclude stdout, '0 passing'
-
-      describe 'when invoked with "--template" but without "--generate-hooks" option', () ->
-        before (done) ->
-          templateFile = "#{TEMPLATE_DIR}/hookfile.js"
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --template #{templateFile}"
-
-          execCommand cmd, done
-
-        it 'exit status should be 1', () ->
-          assert.equal exitStatus, 1
-
-        it 'should print error message to stderr', () ->
-          assert.include stderr, 'Implications failed:'
-          assert.include stderr, 'template -> generate-hooks'
-
-
-  describe 'when RAML file not found', (done) ->
-    before (done) ->
-      ramlFile = "#{RAML_DIR}/nonexistent_path.raml"
-      cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER}"
-
-      execCommand cmd, done
-
-    it 'should exit with status 1', () ->
-      assert.equal exitStatus, 1
-
-    it 'should print error message to stderr', () ->
-      # See https://travis-ci.org/cybertk/abao/jobs/76656192#L479
-      # iojs behaviour is different from nodejs
-      assert.include stderr, 'Error: ENOENT'
-
-
-  describe 'arguments with existing RAML and responding server', () ->
-    describe 'when invoked without "--server" option', () ->
-      describe 'when RAML file does not specify "baseUri"', () ->
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/no-base-uri.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --reporter json"
-
-          execCommand cmd, done
-
-        it 'should exit with status 1', () ->
-          assert.equal exitStatus, 1
-
-        it 'should print error message to stderr', () ->
-          assert.include stderr, 'no API endpoint specified'
-
-      describe 'when RAML file does specify "baseUri"', () ->
-
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --reporter json"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              type: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'exit status should be 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should print count of tests run', () ->
-          assert.equal 1, report.tests.length
-          assert.equal 1, report.passes.length
-
-        it 'should print correct title for response', () ->
-          assert.equal report.tests[0].fullTitle, 'GET /machines -> 200 Validate response code and body'
-
-    describe 'when executing the command and the server is responding as specified in the RAML', () ->
-      before (done) ->
-        ramlFile = "#{RAML_DIR}/single-get.raml"
-        cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --reporter json"
-
-        app = express()
-
-        app.get '/machines', (req, res) ->
-          res.setHeader 'Content-Type', 'application/json'
-          machine =
-            type: 'bulldozer'
-            name: 'willy'
-          response = [machine]
-          res.status(200).send response
-
-        server = app.listen PORT, () ->
-          execCommand cmd, () ->
-            server.close()
-
-        server.on 'close', done
-
-      it 'exit status should be 0', () ->
-        assert.equal exitStatus, 0
-
-      it 'should print count of tests run', () ->
-        assert.equal 1, report.tests.length
-        assert.equal 1, report.passes.length
-
-      it 'should print correct title for response', () ->
-        assert.equal report.tests[0].fullTitle, 'GET /machines -> 200 Validate response code and body'
-
-    describe 'when executing the command and RAML includes other RAML files', () ->
-      before (done) ->
-        ramlFile = "#{RAML_DIR}/include_other_raml.raml"
-        cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER}"
-
-        app = express()
-
-        app.get '/machines', (req, res) ->
-          res.setHeader 'Content-Type', 'application/json'
-          machine =
-            type: 'bulldozer'
-            name: 'willy'
-          response = [machine]
-          res.status(200).send response
-
-        server = app.listen PORT, () ->
-          execCommand cmd, () ->
-            server.close()
-
-        server.on 'close', done
-
-      it 'exit status should be 0', () ->
-        assert.equal exitStatus, 0
-
-      it 'should print count of tests run', () ->
-        assert.include stdout, '1 passing'
-
-    describe 'when called with arguments', () ->
-
-      describe 'when invoked with "--reporter" option', () ->
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --reporter spec"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              type: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'should print using the specified reporter', () ->
-          assert.include stdout, '1 passing'
-
-      describe 'when invoked with "--header" option', () ->
-
-        receivedRequest = {}
-
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --header Accept:application/json"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            receivedRequest = req
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              type: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'should have an additional header in the request', () ->
-          assert.equal receivedRequest.headers.accept, 'application/json'
-
-        it 'exit status should be 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should print count of tests run', () ->
-          assert.include stdout, '1 passing'
-
-
-      describe 'when invoked with "--hookfiles" option', () ->
-
-        receivedRequest = {}
-
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --hookfiles=#{HOOK_DIR}/*_hooks.*"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            receivedRequest = req
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              type: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'should modify the transaction with hooks', () ->
-          assert.equal receivedRequest.headers['header'], '123232323'
-          assert.equal receivedRequest.query['key'], 'value'
-
-        it 'should print message to stdout and stderr', () ->
-          assert.include stdout, 'before-hook-GET-machines'
-          assert.include stderr, 'after-hook-GET-machines'
-
-
-      describe 'when invoked with "--hooks-only" option', () ->
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --hooks-only"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              type: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'exit status should be 0', () ->
-          assert.equal exitStatus, 0
-
-        it 'should not run test without hooks', () ->
-          assert.include stdout, '1 pending'
-
-      describe 'when invoked with "--timeout" option', () ->
-        cost = ''
-
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/single-get.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --timeout 100"
-
-          app = express()
-
-          t0 = ''
-          app.get '/machines', (req, res) ->
-            t0 = new Date
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              cost = new Date - t0
-              server.close()
-
-          server.on 'close', done
-
-        it 'exit status should be 1', () ->
-          assert.equal exitStatus, 1
-
-        it 'should exit before timeout', () ->
-          assert.ok cost < 200
-
-        it 'should not run test without hooks', () ->
-          assert.include stdout, '0 passing'
-
-      describe 'when invoked with "--schema" option', () ->
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/with-json-refs.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --schemas=#{SCHEMA_DIR}/*.json"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              type: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'exit status should be 0', () ->
-          assert.equal exitStatus, 0
-
-      describe 'when invoked with "--schema" option and expecting error', () ->
-        before (done) ->
-          ramlFile = "#{RAML_DIR}/with-json-refs.raml"
-          cmd = "#{ABAO_BIN} #{ramlFile} --server #{SERVER} --schemas=#{SCHEMA_DIR}/*.json"
-
-          app = express()
-
-          app.get '/machines', (req, res) ->
-            res.setHeader 'Content-Type', 'application/json'
-            machine =
-              typO: 'bulldozer'
-              name: 'willy'
-            response = [machine]
-            res.status(200).send response
-
-          server = app.listen PORT, () ->
-            execCommand cmd, () ->
-              server.close()
-
-          server.on 'close', done
-
-        it 'exit status should be 1', () ->
-          assert.equal exitStatus, 1
-


cooldown finilazation

cooldown finilazation

--- test/cooldown.coffee
+++ test/cooldown.coffee
@@ -7,7 +7,7 @@
       bullet:
         target: 3
         approachBy: 1
-        value: 95
+        value: 100

   obj.include(Cooldown)


Fix alignment of the remove button for point rules

--- components/default-components.coffee
+++ components/default-components.coffee
@@ -60,31 +60,6 @@

-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.
-

-

-

-                            Add Rule
-                            <form class="form-inline">
-

-                                Add
-                                <input ng-model="newRule.points" type="text" class="form-control">
-                                points
-

-                            </form>
-

-

-                            if this field
-                            <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value" aria-describedby="basic-addon2">
-                            +
-

-
{{rulesErrorMessage}}

@@ -195,18 +170,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -340,18 +313,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -501,18 +472,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -626,18 +595,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -761,18 +728,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -894,18 +859,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -1039,18 +1002,16 @@

 0">
                             Active Rules
-

+

                               Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                 Add
                                 <input type="text" class="form-control" ng-model="newRule.points">
                                 points

-

@@ -1170,18 +1131,16 @@

 0">
                                 Active Rules
-

+

                                   Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                     Add
                                     <input type="text" class="form-control" ng-model="newRule.points">
                                     points

-

@@ -1389,18 +1348,16 @@

 0">
                                     Active Rules
-

+

                                       Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}.

-

-

+

                                         Add
                                         <input type="text" class="form-control" ng-model="newRule.points">
                                         points

-


adjusted mincha times for 9 Ab and Ereb 9 Ab

--- js/mincha.coffee
+++ js/mincha.coffee
@@ -47,7 +47,7 @@
     mincha: (round_down_to_5_minutes(if hebrew_date.isShabbat() then begin_seudat_shelishit_samuch_lemincha_ketana(hebrew_date, zmanim).subtract('hours', 2) else sunset.subtract('hours', 1))),
     arbit: if hebrew_date.isShabbat() then sunset else (if hebrew_date.is1stDayOfYomTob() || hebrew_date.isErebShabbat() then null else (show_mosaei_yom_tob(sunset, zmanim); round_down_to_5_minutes(moment(zmanim.set_hakochabim).subtract('minutes', 10))))
   else if hebrew_date.is9Ab()
-    mincha: moment(sunset).subtract('minutes', 40), arbit: sunset
+    mincha: moment(sunset).subtract('minutes', 45), arbit: sunset
   else if hebrew_date.isTaanitEster()
     mincha: moment(sunset).subtract('minutes', 30), arbit: sunset
   else if hebrew_date.isTaanit()
@@ -63,7 +63,7 @@
       $('.not-ereb-9-ab').addClass('hidden')
       mincha: round_down_to_5_minutes(moment(sunset).subtract('minutes', 100)), arbit: sunset.add('minutes', 90)
     else
-      mincha: moment(sunset).subtract('minutes', 40), arbit: sunset
+      mincha: round_down_to_5_minutes(moment(sunset).subtract('minutes', 55)), arbit: sunset
   else if hebrew_date.isPurim()
     {}
   else if hebrew_date.is6thDayOfPesach()


removing JSON.parse altogether until there's a real need

--- packages/tower-net/shared/route.coffee
+++ packages/tower-net/shared/route.coffee
@@ -106,10 +106,10 @@
       if capture && !params[key]?
         capture = decodeURIComponent(capture)
         # need a way to convert :id to integer if it's an integer...
-        try
-          params[key] = if params.format == 'json' then JSON.parse(capture) else capture
-        catch error
-          params[key] = capture
+        # try
+        #   params[key] = if params.format == 'json' then JSON.parse(capture) else capture
+        # catch error
+        params[key] = capture

     controller      = @controller
     params.action   = controller.action if controller


Clampable#clampToBounds

Clampable#clampToBounds

--- src/clampable.coffee
+++ src/clampable.coffee
@@ -10,4 +10,4 @@
     Object.extend(I.clampData, data)

   clampToBounds: (bounds) ->
-    bounds ||= +    bounds ||= Rectangle 0,


clampable

clampable

--- src/clampable.coffee
+++ src/clampable.coffee
@@ -5,6 +5,6 @@

   # Add events and methods here
   self.bind "afterUpdate", ->
-
+    for property, data of I.clampData
   clamp: ->


Clampable#clampToBounds

Clampable#clampToBounds

--- src/clampable.coffee
+++ src/clampable.coffee
@@ -26,7 +26,7 @@
   ###*
   @name clampToBounds
   @methodOf Clampable#
-  @param {Rectangle} [bounds] The bounds to clamp the object
+  @param {Rectangle} [bounds] The bounds to clamp the object's position
   ###
   clampToBounds: (bounds) ->
     bounds ||= Rectangle x: 0, y: 0, width: App.width, height: App.height


check project path when create post

check project path when create post

--- lib/post-create-view.coffee
+++ lib/post-create-view.coffee
@@ -49,8 +49,16 @@
     @editorLabel.text(editorLabel)

   createPost: (title) ->
+    return unless title
+
     hexoPath = atom.project.getPath()
-    return unless title and hexoPath
+    projectPathError =
+      css: 'warning'
+      line: 'Please open your Hexo folder as the root project!'
+
+    if not hexoPath
+      atom.workspaceView.trigger 'hexo:show-results', projectPathError
+      return

     command = 'hexo'
     args = ['new', @layout, title]
@@ -61,10 +69,7 @@
     stdout = (output) =>
       if -1 != output.indexOf 'Usage'
         @detach()
-        data =
-          css: 'warning'
-          line: 'Please open your Hexo folder as the root project!'
-        atom.workspaceView.trigger 'hexo:show-results', data
+        atom.workspaceView.trigger 'hexo:show-results', projectPathError
       else
         postFile = output[output.indexOf(atom.project.getPath())..]
         postFile = postFile.replace '\n', ''


fix translation 'update to' in control button

--- lib/preferences-util.coffee
+++ lib/preferences-util.coffee
@@ -51,8 +51,11 @@
     @defS = window.I18N.defS.Settings
     sv = document.querySelector('.settings-view')
     for btn in sv.querySelectorAll('.meta-controls .install-button')
-      @applyTextWithOrg(btn, @defS["control-btns"].install)
-      # TODO i18n btn if content starts with "Udate to"
+      unless @isAlreadyLocalized(btn)
+        buttonText = if btn.textContent.startsWith('Update to')
+        then @defS["control-btns"].update + (version = btn.textContent.substr(9))
+        else @defS["control-btns"].install
+        @applyTextWithOrg(btn, buttonText)
     for btn in sv.querySelectorAll('.meta-controls .settings')
       @applyTextWithOrg(btn, @defS["control-btns"].setting)
     for btn in sv.querySelectorAll('.meta-controls .uninstall-button')


require KodingError

require KodingError

--- workers/social/lib/social/models/messages/opinion/index.coffee
+++ workers/social/lib/social/models/messages/opinion/index.coffee
@@ -15,6 +15,8 @@
   {extend} = require 'underscore'

   {log} = console
+
+  KodingError = require '../../error'

   @share()


Removed selfBuild() from non-debug mode

Removed selfBuild() from non-debug mode

--- src/core/_esy.coffee
+++ src/core/_esy.coffee
@@ -13,7 +13,6 @@
     if esy.debug
       @selfBuild (new File($.fileName)).parent.parent.path
     else
-      @selfBuild (new File($.fileName)).parent.parent.path
       @updater = new EsyUpdater
         repo: "seblavoie/esy"
         file: "esy.jsx"


KDToggleButton: fix git merge failure

KDToggleButton: fix git merge failure

--- client/Framework/components/buttons/KDToggleButton.coffee
+++ client/Framework/components/buttons/KDToggleButton.coffee
@@ -10,7 +10,7 @@

     super options, data

-    @setState options.defaultState, no
+    @setState options.defaultState

   getStateIndex:(name)->

@@ -22,27 +22,37 @@
         if name is state.title
           return index

-  decorateState:(name, userEvent)->
+  decorateState:(name)->
     @setTitle @state.title
-    @setIconClass @state.iconClass if @state.iconClass?
+    @setIconClass @state.iconClass  if @state.iconClass?
+
+    if @state.cssClass? or @lastUsedCssClass?
+      @unsetClass @lastUsedCssClass  if @lastUsedCssClass?
+      @setClass @state.cssClass
+      @lastUsedCssClass = @state.cssClass
+    else
+      delete @lastUsedCssClass

   getState:-> @state

-  setState:(name, userEvent = yes)->
+  setState:(name)->

     {states} = @getOptions()
     @stateIndex = index = @getStateIndex name
     @state      = states[index]
-    @decorateState name, userEvent
+    @decorateState name

     @setCallback states[index].callback.bind @, @toggleState.bind @

   toggleState:(err)->

-    {states} = @getOptions()
+    {states}  = @getOptions()
     nextState = states[@stateIndex + 1] or states[0]
     unless err
       @setState nextState.title
     else
-      warn err.msg or "there was an error, couldn't switch to #{nextState} state!"
+      unless err.name is 'AccessDenied'
+        warn err.message or \
+          "There was an error, couldn't switch to #{nextState.title} state!"
+
     @hideLoader?()


InvitedItemView: Minor code refactor. [ci skip]

--- client/admin/lib/views/invitations/inviteditemview.coffee
+++ client/admin/lib/views/invitations/inviteditemview.coffee
@@ -24,13 +24,15 @@

   showSettings: ->

+    return  unless @isPendingView()
+
     @settings.toggleClass 'hidden'
     @toggleClass 'settings-visible'

   revoke: ->

-    return  unless @getOptions().statusType is 'pending'
+    return  unless @isPendingView()

     @revokeButton.showLoader()

@@ -45,7 +47,7 @@

   resend: ->

-    return  unless @getOptions().statusType is 'pending'
+    return  unless @isPendingView()

     @resendButton.showLoader()

@@ -58,6 +60,11 @@
         title  = 'Unable to resend the invitation. Please try again.'

       return new KDNotificationView { title, duration }
+
+
+  isPendingView: ->
+
+    return  @getOptions().statusType is 'pending'

   createViews: ->