passport = require 'passport'
debug = require('debug')('meshblu-google-authenticator:routes')
url = require 'url'

class Router
  constructor: (@app) ->

  register: =>
    @app.get  '/', (request, response) => response.status(200).send status: 'online'

    @app.get '/login', @storeCallbackUrl, passport.authenticate 'google', scope: ['profile', 'email']

    @app.get '/oauthcallback', passport.authenticate('google', { failureRedirect: '/login' }), @afterPassportLogin

  afterPassportLogin: (request, response) =>
    {callbackUrl} = request.cookies
    delete request.cookies.callbackUrl
    return response.status(401).send(new Error 'Invalid User') unless request.user
    return response.status(201).send(request.user) unless callbackUrl?
    uriParams = url.parse callbackUrl
    uriParams.query ?= {}
    uriParams.query.uuid = request.user.uuid
    uriParams.query.token = request.user.token
    return response.redirect(url.format uriParams)

  defaultRoute: (request, response) =>
    response.render 'index'

  storeCallbackUrl: (request, response, next) =>
    if request.query.callbackUrl?
      request.cookies.callbackUrl = request.query.callbackUrl
    else
      delete request.cookies.callbackUrl
    next()

module.exports = Router

passport = require 'passport'
debug = require('debug')('meshblu-google-authenticator:routes')
url = require 'url'

class Router
  constructor: (@app) ->

  register: =>
    @app.get  '/', (request, response) => response.status(200).send status: 'online'

    @app.get '/login', @storeCallbackUrl, passport.authenticate 'google', scope: ['profile', 'email']

    @app.get '/oauthcallback', passport.authenticate('google', { failureRedirect: '/login' }), @afterPassportLogin

  afterPassportLogin: (request, response) =>
    {callbackUrl} = request.cookies
    response.cookie 'callbackUrl', null, maxAge: -1
    return response.status(401).send(new Error 'Invalid User') unless request.user
    return response.status(201).send(request.user) unless callbackUrl?
    uriParams = url.parse callbackUrl
    uriParams.query ?= {}
    uriParams.query.uuid = request.user.uuid
    uriParams.query.token = request.user.token
    return response.redirect(url.format uriParams)

  defaultRoute: (request, response) =>
    response.render 'index'

  storeCallbackUrl: (request, response, next) =>
    if request.query.callbackUrl?
      response.cookie 'callbackUrl', request.query.callbackUrl, maxAge: 60 * 60 * 1000
    else
      response.cookie 'callbackUrl', null, maxAge: -1
    next()

module.exports = Router

Use the undocumented cookies api

Use the undocumented cookies api


MergeConflictsView = require './merge-conflicts-view'
SideView = require './side-view'
NavigationView = require './navigation-view'
Conflict = require './conflict'

module.exports =

  activate: (state) ->
    atom.workspaceView.command "merge-conflicts:detect", ->
      MergeConflictsView.detect()

    atom.workspaceView.eachEditorView (view) ->
      if view.attached and view.getPane()?
        for c in Conflict.all(view.getEditor())
          oursView = new SideView(c.ours)
          oursView.installIn view

          theirsView = new SideView(c.theirs)
          theirsView.installIn view

          navView = new NavigationView(c)
          navView.installIn view

  deactivate: ->

  serialize: ->

MergeConflictsView = require './merge-conflicts-view'
SideView = require './side-view'
NavigationView = require './navigation-view'
Conflict = require './conflict'

module.exports =

  activate: (state) ->
    atom.workspaceView.command "merge-conflicts:detect", ->
      MergeConflictsView.detect()

    atom.workspaceView.eachEditorView (view) ->
      if view.attached and view.getPane()?
        for c in Conflict.all(view.getEditor())
          oursView = new SideView(c.ours, view)
          theirsView = new SideView(c.theirs, view)
          navView = new NavigationView(c, view)

  deactivate: ->

  serialize: ->

Use the new CoveringView API in MergeConflict.


$ ->
  $('.reminder_active').on 'change', ->
    $('.reminder_days_before').prop "disabled", !@.checked

  select2_options =
    theme: 'bootstrap'
    placeholder: 'Selecione os usuários'
    maximumSelectionLength: 7

  $('.select_users').select2 select2_options

  $('.js-account').click (e)->
    path = '/main_account.json'
    account_id = $(@).data('account-id')

    $.getJSON(path, { account_id: account_id })
      .done (data)->
        console.log data

$ ->
  $('.reminder_active').on 'change', ->
    $('.reminder_days_before').prop "disabled", !@.checked

  $('.public').on 'change', ->
    $('.select_users').prop "disabled", !@.checked

  select2_options =
    theme: 'bootstrap'
    placeholder: 'Selecione os usuários'
    maximumSelectionLength: 7

  $('.select_users').select2 select2_options

  $('.js-account').click (e)->
    path = '/main_account.json'
    account_id = $(@).data('account-id')

    $.getJSON(path, { account_id: account_id })
      .done (data)->
        console.log data

Add disable select_users when public is false


kd = require 'kd'
KDCustomHTMLView = kd.CustomHTMLView
KodingSwitch = require 'app/commonviews/kodingswitch'
CustomLinkView = require 'app/customlinkview'
module.exports = class IDEChatHeadWatchItemView extends KDCustomHTMLView

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

    options.partial ?= 'Watch'

    super options, data

    { delegate, isWatching } = @getOptions()

    @addSubView new KodingSwitch
      cssClass     : 'tiny'
      defaultValue : isWatching
      callback     : delegate.bound 'setWatchState'

    @addSubView new CustomLinkView
      title        : ''
      cssClass     : 'info'
      href         : 'http://learn.koding.com/guides/collaboration/#what-does-quot-watch-quot-mode-mean-'
      target       : '_blank'

Delete white spaces at end of file

Delete white spaces at end of file


'use strict'

@start = (limit) ->
  window.startDate = new Date().getTime()
  window.elapsedSeconds = 0
  window.seconds = 0
  window.minutes = 0
  window.limit = limit
  window.timerID = setInterval(timeCounter, 1000)
  return

@stop = ->
  clearInterval timerID
  return

timeCounter = ->
  if elapsedSeconds >= limit
    stop()
    return

  time = new Date().getTime() - startDate

  window.elapsedSeconds = parseInt(Math.floor(time / 100) / 10)

  allTheTime = elapsedSeconds
  minutes = parseInt(allTheTime/60)
  allTheTime -= minutes * 60
  seconds = parseInt(allTheTime)

  document.getElementById('seconds').innerHTML = seconds
  document.getElementById('minutes').innerHTML = minutes

  return

'use strict'

@start = (limit) ->
  window.startDate = new Date().getTime()
  window.elapsedSeconds = 0
  window.seconds = 0
  window.minutes = 0
  window.limit = limit
  window.timerID = setInterval(timeCounter, 1000)
  return

@stop = ->
  clearInterval timerID
  return

timeCounter = ->
  if elapsedSeconds >= limit
    stop()
    return

  time = new Date().getTime() - startDate

  window.elapsedSeconds = parseInt(Math.floor(time / 100) / 10)

  allTheTime = elapsedSeconds
  minutes = parseInt(allTheTime/60)
  allTheTime -= minutes * 60
  seconds = parseInt(allTheTime)

  minutes = '0' + minutes if minutes < 10
  seconds = '0' + seconds if seconds < 10

  document.getElementById('seconds').innerHTML = seconds
  document.getElementById('minutes').innerHTML = minutes

  return

Adjust minutes and seconds counters to have a zero on the left when they are less than 10.


jQuery ->
  ($ '#account-next-step').on 'click', (e) ->
    do e.preventDefault
    do ($ '#account-form').submit

  if ($ '#user_qae_info_source_other').length
    toggleOther = (checkbox) ->
      if checkbox.is(':checked')
        ($ '#qae_info_source_other').removeClass('visuallyhidden')
      else
        ($ '#qae_info_source_other').addClass('visuallyhidden')

    toggleOther($ '#user_qae_info_source_other')

    ($ '#user_qae_info_source_other').on 'change', ->
      toggleOther($ @)

jQuery ->
  ($ '#account-next-step').on 'click', (e) ->
    do e.preventDefault
    do ($ '#account-form').submit

  if $('#user_qae_info_source').size() > 0
    toggleOther = (select) ->
      if select.val() == 'other'
        ($ '#qae_info_source_other').removeClass('visuallyhidden')
      else
        ($ '#qae_info_source_other').addClass('visuallyhidden')

    toggleOther($ '#user_qae_info_source')

    ($ '#user_qae_info_source').on 'change', ->
      toggleOther($ @)

Fix "How did you hear about The Queen's Awards?" conditional JS


class window.DP.Realtime
  init: ->
    if typeof Pusher == 'function'
      @pusher = new Pusher(DP.PUSHER_KEY)
      @channel = @pusher.subscribe DP.Round.url
      @channel.bind('new:charge', _.bind(@newCharge, this))
      console.log(["Subscribing to real-time", @pusher, @channel])

  newCharge: ->
    console.log(["REAL-TIME: New Charge", arguments])
    @reloadDonations()

  reloadDonations: (data)->
    if !data
      $.get('/round_status/' + DP.Round.url, {}, @renderDonations)
    else
      @renderDonations(data)

  renderDonations: (data)->
    console.log(["Round status", data])
    $('.donations').html(data.donations_template)
    $('.payment-info').html(data.payment_info_template)
    @secondsLeft = data.seconds_left
    if data.closed
      window.location.href = window.location.href

  renderTimer: ->
    if @secondsLeft <= 0
      window.location.href = window.location.href

    $timer = $('.timer')
    minutes = Math.floor(@secondsLeft / 60)
    seconds = @secondsLeft % 60
    if seconds <= 9
      seconds = "0" + seconds
    $timer.html(minutes + ":" + seconds + " time left")
    @secondsLeft -= 1

class window.DP.Realtime
  constructor: ->
    if typeof Pusher == 'function'
      @pusher = new Pusher(DP.PUSHER_KEY)
      @channel = @pusher.subscribe DP.Round.url
      @channel.bind('new:charge', _.bind(@newCharge, this))
      console.log(["Subscribing to real-time", @pusher, @channel])

  newCharge: ->
    console.log(["REAL-TIME: New Charge", arguments])
    @reloadDonations()

  reloadDonations: (data)->
    if !data
      $.get('/round_status/' + DP.Round.url, {}, @renderDonations)
    else
      @renderDonations(data)

  renderDonations: (data)->
    console.log(["Round status", data])
    $('.donations').html(data.donations_template)
    $('.payment-info').html(data.payment_info_template)
    @secondsLeft = data.seconds_left
    if data.closed
      window.location.href = window.location.href

  renderTimer: ->
    if @secondsLeft <= 0
      window.location.href = window.location.href

    $timer = $('.timer')
    minutes = Math.floor(@secondsLeft / 60)
    seconds = @secondsLeft % 60
    if seconds <= 9
      seconds = "0" + seconds
    $timer.html(minutes + ":" + seconds + " time left")
    @secondsLeft -= 1

Use constructor instead of init

Use constructor instead of init


$ ->
  saveSequence = (sequence) ->
    if sequence?
      localStorage.setItem('sequence', sequence)
    true

  loadSequence = ->
    localStorage.getItem('sequence')

  input    = $("input#fragment")
  button   = $("#methods button")
  sequence = loadSequence()

  if sequence?
    input.val(sequence)

    unless window.location.search
      button.click()

  button.on "click", ->
    val = input.val()
    saveSequence(val)

  false

$ ->
  saveSequence = (sequence) ->
    if sequence?
      localStorage.setItem('sequence', sequence)
    true

  loadSequence = ->
    localStorage.getItem('sequence')

  button = $("#methods button")
  input  = $("input#fragment")

  $(window).on "load", (e) ->
    search = window.location.search

    if search
      val = input.val()
      saveSequence(val)
    else
      sequence = loadSequence()

      if sequence?
        input.val(sequence)
        button.click()

  button.on "click", ->
    val = input.val()
    saveSequence(val)

  false

Save sequence if location.search exists

Save sequence if location.search exists

ブラウザで直接アドレス(URL)を指定した場合も、
次からはその画面を開けるようにするために、location.search を見て検索条件を保持するようにした


child_process = require 'child_process'

module.exports =
	activate: (state) ->
		atom.commands.add 'atom-workspace', 'wp-phptidy:run': => @run()

	run: ->
		editor = atom.workspace.getActivePaneItem()
		editor.save()

		file = editor?.buffer.file
		filepath = file?.path

		if filepath.length
		  child_process.exec(__dirname + '/../vendor/wp-phptidy.php replace ' + filepath)

child_process = require 'child_process'

module.exports =
	activate: (state) ->
		atom.commands.add 'atom-workspace', 'wp-phptidy:run': => @run()

	run: ->
		editor = atom.workspace.getActivePaneItem()
		editor.save()

		file = editor?.buffer.file
		filepath = file?.path

		if filepath.length
		  child_process.exec('php ' + __dirname + '/../vendor/wp-phptidy.php replace ' + filepath)

Fix for executing PHP on Windows

Fix for executing PHP on Windows


Crafty.c 'Mine',
  init: ->
    @requires 'Color, Enemy'

  mine: (attr = {}) ->
    @attr _.defaults(attr,
      w: 25, h: 25, health: 200)
    @origin 'center'
    @color '#555555'

    @enemy()
    this

Crafty.c 'Mine',
  init: ->
    @requires 'Color, Enemy'

  mine: (attr = {}) ->
    @attr _.defaults(attr,
      w: 25, h: 25, health: 200)
    @origin 'center'
    @color '#111111'

    @enemy()
    this

Increase contrast of mine agains background


window.Game = class Game
  constructor: (grid, moves, status, winner) ->
    console.log 'Game ctor'
    @gameBoard = new GameBoard($('#canvas'), $('#canvasOverlay'), {
      grid: grid,
      moves: moves,
      winner: winner,
      afterMoveAnimation: $.proxy(this.afterMove, this)
    })
    @setFinished(winner) if status == 'finished'

  afterMove: ->
    gameBoard = @gameBoard
    console.log 'afterMove'
    if gameBoard.nextColour == 1
      gameBoard.activate false
      console.log gameBoard.grid
      game = this
      $.ajax {
        dataType: "json",
        type: "POST",
        contentType: "application/json",
        data: JSON.stringify { grid: gameBoard.grid, moves: gameBoard.moves }
        beforeSend: (xhr) -> xhr.setRequestHeader("X-Http-Method-Override", "PUT")
        success: (result) ->
          console.log result
          new_move = result.moves[result.moves.length - 1]
          if result.status == 'finished'
            game.setFinished(result.winner)
          else
            gameBoard.move new_move[1]
            gameBoard.activate true
      }

  setFinished: (winner) ->
    if winner
      $('.messagePanel').text "Game over, #{winner} won"
    else
      $('.messagePanel').text "Game over, drawn"
    @gameBoard.activate false

window.Game = class Game
  constructor: (grid, moves, status, winner) ->
    console.log 'Game ctor'
    @gameBoard = new GameBoard($('#canvas'), $('#canvasOverlay'), {
      grid: grid,
      moves: moves,
      winner: winner,
      afterMoveAnimation: $.proxy(this.afterMove, this)
    })
    @setFinished(winner) if status == 'finished'

  afterMove: ->
    gameBoard = @gameBoard
    console.log 'afterMove'
    if gameBoard.nextColour == 1
      gameBoard.activate false
      console.log gameBoard.grid
      game = this
      $.ajax {
        dataType: "json",
        type: "POST",
        contentType: "application/json",
        data: JSON.stringify { grid: gameBoard.grid, moves: gameBoard.moves }
        beforeSend: (xhr) -> xhr.setRequestHeader("X-Http-Method-Override", "PUT")
        success: (result) ->
          console.log result
          new_move = result.moves[result.moves.length - 1]
          if result.status == 'finished'
            gameBoard.move new_move[1] if result.winner == 'yellow'
            game.setFinished(result.winner)
          else
            gameBoard.move new_move[1]
            gameBoard.activate true
      }

  setFinished: (winner) ->
    if winner
      $('.messagePanel').text "Game over, #{winner} won"
    else
      $('.messagePanel').text "Game over, drawn"
    @gameBoard.activate false

Fix bug - yellows last move not displayed when he wins


'use strict'

class Game

    constructor: ->
        peer = new Peer 'server', {host: 'localhost', port: 9999}
        conn = peer.connect 'device'

        conn.on 'open', =>
            conn.send 'Conneced.'
        conn.on 'data', (id) =>
            console.log id

        @resizeWindow()
        $(window).resize =>
            @resizeWindow()

        dartsUi = new DartsUi $('#darts-ui')[0]
        dartsUi.setListener (score, ratio) ->
            console.log score + ', ' + ratio + ' = ' + score * ratio

    resizeWindow: ->
        bodyHeight = $('body').height()
        headerHeight = $('.header').height() + 11
        footerHeight = $('.footer').height() + 11
        canvasHeight = bodyHeight - headerHeight - footerHeight - 20
        $('#darts-ui').width(canvasHeight).height(canvasHeight)

window.Game = Game

'use strict'

class Game

    constructor: ->
        peer = new Peer 'server', {host: 'localhost', port: 9999}
        conn = peer.connect 'device'

        conn.on 'open', =>
            conn.send 'Conneced.'
        conn.on 'data', (id) =>
            console.log id

        @resizeWindow()
        $(window).resize =>
            @resizeWindow()

        dartsUi = new DartsUi $('#darts-ui')[0]
        dartsUi.setListener (score, ratio) ->
            console.log score + ', ' + ratio + ' = ' + score * ratio

    resizeWindow: ->
        bodyHeight = $('body').height()
        headerHeight = $('.header').height() + 11
        footerHeight = $('.footer').height() + 11
        canvasHeight = bodyHeight - headerHeight - footerHeight
        length = (Math.min $('body').width(), canvasHeight) - 20
        $('#darts-ui').width(length).height(length)

window.Game = Game

Change darts-ui size to fit screen

Change darts-ui size to fit screen


window.Echotron ||= {}
Echotron.Echoes ||= {}
Echotron.Echoes.foreground ||= []
Echotron.Echoes.midground  ||= []
Echotron.Echoes.background ||= []

class Echotron.Echo extends THREE.Object3D
  uniformAttrs: {}

  # Override, calling super. Setup your Echo however you need.
  constructor: ->
    super
    @active = yes
    @initUniforms()

  # Setup list of uniforms sent to shaders.
  initUniforms: ->
    @uniforms = {}
    for name, type of @uniformAttrs
      @uniforms[name] =
        type:  type
        value: null

      # Define an accessor property on the prototype
      unless name of this
        do (name, type) =>
          Object.defineProperty @constructor::, name,
            get: -> @uniforms[name].value
            set: (val) -> @uniforms[name].value = val

    return

  # Tells this layer to start to die. It will no longer receive song events,
  # and will be pruned when @alive() returns false.
  kill: ->
    @active = no

  # Called by LayerStack
  expired: ->
    not @active and not @alive()

  # Override. Should return false when the layer can be destoryed.
  alive: -> @active

  # Override. Do stuff on beats.
  onBeat: ->

  # Override. Do stuff on bars.
  onBar: ->

  # Override. Do stuff on segment.
  onSegment: ->

  # Override. Do stuff on bars.
  onTatum: ->

  # Override. Update state per frame.
  update: (elapsed) ->

window.Echotron ||= {}
Echotron.Echoes ||= {}
Echotron.Echoes.foreground ||= []
Echotron.Echoes.midground  ||= []
Echotron.Echoes.background ||= []

class Echotron.Echo extends THREE.Object3D
  uniformAttrs: {}

  # Override, calling super. Setup your Echo however you need.
  constructor: ->
    super
    @active = yes
    @initUniforms()

    # Call a non-constructor init function.
    @initialize?()

  # Setup list of uniforms sent to shaders.
  initUniforms: ->
    @uniforms = {}
    for name, type of @uniformAttrs
      @uniforms[name] =
        type:  type
        value: null

      # Define an accessor property on the prototype
      unless name of this
        do (name, type) =>
          Object.defineProperty @constructor::, name,
            get: -> @uniforms[name].value
            set: (val) -> @uniforms[name].value = val

    return

  # Tells this layer to start to die. It will no longer receive song events,
  # and will be pruned when @alive() returns false.
  kill: ->
    @active = no

  # Called by LayerStack
  expired: ->
    not @active and not @alive()

  # Override. Should return false when the layer can be destoryed.
  alive: -> @active

  # Override. Do stuff on beats.
  onBeat: ->

  # Override. Do stuff on bars.
  onBar: ->

  # Override. Do stuff on segment.
  onSegment: ->

  # Override. Do stuff on bars.
  onTatum: ->

  # Override. Update state per frame.
  update: (elapsed) ->

Initialize can be implemented instead of implementing the constructor on a layer. Meaning super isn't required.


program = require 'commander'

program
  .command('new [name]')
  .description('create a new app and/or extension')
  .usage('[name] [options]')
  .option('-t, --template [name]', 'template to use')
  .option('-c, --config [config file]', 'config file to use')
  .action (name, opts={}) ->
    if not name
      return console.log 'Name of project required'
    require('./generator') name, opts

program
  .command('watch [name]')
  .description('watch for changes and reload')
  .action (opts={}) ->
    require('./watch') opts

help = -> console.log program.helpInformation()

program.parse process.argv

help() unless program.args.length

program = require('commander')
  .version(require('../package.json').version)

help = -> console.log program.helpInformation()

program
  .command('new [name]')
  .description('create a new app and/or extension')
  .usage('[name] [options]')
  .option('-t, --template [name]', 'template to use')
  .option('-c, --config [config file]', 'config file to use')
  .action (name, opts={}) ->
    if not name
      return console.log 'Name of project required'
    require('./generator') name, opts

program
  .command('watch [name]')
  .description('watch for changes and reload')
  .action (opts={}) ->
    require('./watch') opts

program
  .command('install')
  .description('install an app or extension')
  .option('-b, --browser [location]', 'Path to browser to use')
  .action (opts={}) ->
    switch process.platform
      when 'darwin'
        {exec} = require 'child_process'
        browser = opts.browser or 'Google\\ Chrome'
        exec "pkill #{browser}", ->
          exec "open -a #{browser} --args --load-extension=#{process.cwd()}"
      else
        console.log 'Unable to install extensions on your platform'

program.parse process.argv

help() unless program.args.length

Add command to automatically install extensions.


Rectangle = require './drawing-tools/rectangle'
Details = require './tasks/details'

module.exports =
  id: 'bhl'
  background: 'background.jpg'

  producer: 'Missouri Botanical Garden & Zooniverse'
  title: 'Illustrated Life'
  summary: 'Help catalogue scientific illustrations'
  description: 'Short description'

  pages: [{
    'About': '''

All about the project

This is where we\'ll go into detail.

Lorem ipsum dolor sir amet.

Break it into sections, add pictures, whatever.

    '''
  }]

  tasks:
    illustration:
      type: 'drawing'
      question: 'Draw rectangles around the illustrations on this page.'
      choices: [{
        type: Rectangle
        label: 'Mark the illustrations'
        color: '#333333'
      }]
      next: 'details'
    details:
      type: 'details'
      question: 'Add information about the illustrations.'
      choices: [{
        label: 'Type'
        value: ''
      },{
        label: 'Artist'
        value: ''
      }]
      next: 'details'

  firstTask: 'illustration'

Rectangle = require './drawing-tools/rectangle'
Details = require './tasks/details'

module.exports =
  id: 'bhl'
  background: 'background.jpg'

  producer: 'Missouri Botanical Garden & Zooniverse'
  title: 'Illustrated Life'
  summary: 'Help catalogue scientific illustrations'
  description: 'Short description'

  pages: [{
    'About': '''

All about the project

This is where we\'ll go into detail.

Lorem ipsum dolor sir amet.

Break it into sections, add pictures, whatever.

    '''
  }]

  tasks:
    illustrations:
      type: 'radio'
      question: 'Are there any illustrations on this page?'
      choices: [{
        label: 'Yes'
        value: 'yes'
        next: 'illustration'
      },{
        label: 'No'
        value: 'no'
      }]
    illustration:
      type: 'drawing'
      question: 'Draw rectangles around the illustrations on this page.'
      choices: [{
        type: Rectangle
        label: 'Mark the illustrations'
        color: '#333333'
      }]
      next: 'details'
    details:
      type: 'details'
      question: 'Add information about the illustrations.'
      choices: [{
        label: 'Type'
        value: ''
      },{
        label: 'Artist'
        value: ''
      }]
      next: 'details'

  firstTask: 'illustrations'

Add 'Are there any illustrations?' question


module.exports.listen = (port) ->
  createApp().listen port

createApp = () ->
  express = require 'express'
  bodyParser = require 'body-parser'
  errors = require './errors'

  allowCrossDomain = (request, response, next) ->
    response.header 'Access-Control-Allow-Origin', '*'
    response.header(
      'Access-Control-Allow-Methods',
      'GET,PUT,POST,DELETE,OPTIONS'
    )
    response.header(
      'Access-Control-Allow-Headers',
      'Content-Type, Content-Length, X-Requested-With'
    )
    #response.header('Access-Control-Allow-Credentials', 'true')
    if 'OPTIONS' == request.method
      response.send 200
    else
      next()

  defaultHeaders = (request, response, next) ->
    response.header 'Content-Type', 'application/json; charset=utf-8'
    next()

  serverErrorHandling = (err, request, response, next) ->
    if err
      if err instanceof errors.HttpError
        response.send err.statusCode, err.message
      else
        response.send 500

  jsonParser = (request, response, next) ->
    bodyParser.json() request, response, (err) ->
      if err
        next new errors.BadRequest {error: 'Invalid JSON'}
      next(err)

  app = express()
  app.use allowCrossDomain
  app.use defaultHeaders
  app.use jsonParser
  app.use require './request_handler'

  require('./api')(app)

  app.use serverErrorHandling

  return app

module.exports.listen = (port) ->
  createApp().listen port

createApp = () ->
  express = require 'express'
  bodyParser = require 'body-parser'
  errors = require './errors'

  allowCrossDomain = (request, response, next) ->
    response.header 'Access-Control-Allow-Origin', '*'
    response.header(
      'Access-Control-Allow-Methods',
      'GET,PUT,POST,DELETE,OPTIONS'
    )
    response.header(
      'Access-Control-Allow-Headers',
      'Content-Type, Content-Length, X-Requested-With'
    )
    #response.header('Access-Control-Allow-Credentials', 'true')
    if 'OPTIONS' == request.method
      response.send 200
    else
      next()

  defaultHeaders = (request, response, next) ->
    response.header 'Content-Type', 'application/json; charset=utf-8'
    next()

  serverErrorHandling = (err, request, response, next) ->
    if err
      if err instanceof errors.HttpError
        response.send err.statusCode, err.message
      else
        response.send 500

  jsonParser = (request, response, next) ->
    bodyParser.json() request, response, (err) ->
      if err
        next new errors.BadRequest {error: 'Invalid JSON'}
      else
        next()

  app = express()
  app.use allowCrossDomain
  app.use defaultHeaders
  app.use jsonParser
  app.use require './request_handler'

  require('./api')(app)

  app.use serverErrorHandling

  return app

Fix the console logging from invalid json


module.exports = {

  name: "JSX"
  namespace: "jsx"
  fallback: ['js']

  ###
  Supported Grammars
  ###
  grammars: [
    "JSX"
    "JavaScript (JSX)"
    "Babel ES6 JavaScript"
    "JavaScript with JSX"
  ]

  ###
  Supported extensions
  ###
  extensions: [
    "jsx",
    "js"
  ]

  defaultBeautifier: "JS Beautify"

  options:
    e4x:
      type: 'boolean'
      default: true
      description: "Support e4x/jsx syntax"

}

module.exports = {

  name: "JSX"
  namespace: "jsx"
  fallback: ['js']

  ###
  Supported Grammars
  ###
  grammars: [
    "JSX"
    "JavaScript (JSX)"
    "Babel ES6 JavaScript"
    "JavaScript with JSX"
  ]

  ###
  Supported extensions
  ###
  extensions: [
    "jsx",
    "js"
  ]

  defaultBeautifier: "Pretty Diff"

  options:
    e4x:
      type: 'boolean'
      default: true
      description: "Support e4x/jsx syntax"

}

Change JSX default beautifier back to Pretty Diff


AtomPackage = require './atom-package'
Package = require './package'

### Internal: Loads and resolves packages. ###

module.exports =
class ThemePackage extends AtomPackage

  getType: -> 'theme'

  getStylesheetType: -> 'theme'

  enable: ->
    atom.config.pushAtKeyPath('core.themes', @metadata.name)

  disable: ->
    atom.config.removeAtKeyPath('core.themes', @metadata.name)

  load: ->
    @measure 'loadTime', =>
      try
        @metadata ?= Package.loadMetadata(@path)
      catch e
        console.warn "Failed to load theme named '#{@name}'", e.stack ? e
    this

  activate: ->
    @measure 'activateTime', =>
      @loadStylesheets()
      @activateNow()

AtomPackage = require './atom-package'
Package = require './package'

### Internal: Loads and resolves packages. ###

module.exports =
class ThemePackage extends AtomPackage

  getType: -> 'theme'

  getStylesheetType: -> 'theme'

  enable: ->
    themes = atom.config.get('core.themes')
    themes = [@metadata.name].concat(themes)
    atom.config.set('core.themes', themes)

  disable: ->
    atom.config.removeAtKeyPath('core.themes', @metadata.name)

  load: ->
    @measure 'loadTime', =>
      try
        @metadata ?= Package.loadMetadata(@path)
      catch e
        console.warn "Failed to load theme named '#{@name}'", e.stack ? e
    this

  activate: ->
    @measure 'activateTime', =>
      @loadStylesheets()
      @activateNow()

Prepend newly enabled themes, not append


React              = require 'react'
{PureRenderMixin}  = require('react/addons').addons
cx                 = require 'classname'
styleMixin         = require 'mixins/style-mixin'

module.exports = React.createClass
  mixins: [
    styleMixin require('./style.scss')
    PureRenderMixin
  ]

  getIconTypeClass: ->
    if @props.type?
      "cc-icon-#{@props.type}"
    else
      ''
  render: ->
    className = cx
      'cc-icon':                 yes
      "#{@props.size or ''}":    yes
      "#{do @getIconTypeClass}": yes

Add an empty line to separate methods

Add an empty line to separate methods


gulp = require 'gulp'

coffee = require 'gulp-coffee'
concat = require 'gulp-concat'
gutil = require 'gulp-util'
uglify = require 'gulp-uglify'
wrap = require 'gulp-wrap-umd'

gulp.task 'build', ->
	sink = concat('main.js')

	gulp.src('lib/base64-binary.js')
		.pipe(sink, end: false)

	gulp.src('src/validateSSH.coffee')
		.pipe(coffee(bare: true)).on('error', gutil.log)
		.pipe(sink)

	sink
		.pipe(wrap
			exports: 'validateOpenSSHKey'
		)
		.pipe(uglify())
		.pipe(gulp.dest('./dist/'))

gulp.task 'default', ->
	gulp.run 'build'

	gulp.watch [
		'lib/base64-binary.js',
		'src/validateSSH.coffee'
	], (event) ->
		gulp.run 'build'

gulp = require 'gulp'

coffee = require 'gulp-coffee'
concat = require 'gulp-concat'
gutil = require 'gulp-util'
uglify = require 'gulp-uglify'
wrap = require 'gulp-wrap-umd'

gulp.task 'caffeinate', ->
	gulp.src('src/*.coffee')
		.pipe(coffee(bare: true)).on('error', gutil.log)
		.pipe(gulp.dest('./tmp/build'))

	gulp.src('test/*.coffee')
		.pipe(coffee()).on('error', gutil.log)
		.pipe(gulp.dest('./tmp'))

gulp.task 'build', [ 'caffeinate' ], ->
	gulp.src([ 'lib/*.js', 'tmp/build/*.js' ])
		.pipe(concat('main.js'))
		.pipe(wrap
			exports: 'validateOpenSSHKey'
		)
		.pipe(uglify())
		.pipe(gulp.dest('./dist/'))

gulp.task 'default', ->
	gulp.run 'build'

	gulp.watch [
		'lib/base64-binary.js',
		'src/validateSSH.coffee'
	], (event) ->
		gulp.run 'build'

Enforce order of build tasks.

Enforce order of build tasks.

Fixes issue with race condition on build.


'.text.restructuredtext':
  'image':
    'prefix': 'image'
    'body': '.. image:: ${1:path}\n$0'
  'link':
    'prefix': 'link'
    'body': '\\`${1:Title} <${2:http://link}>\\`_$0'
  'section 1':
    'prefix': 'sec'
    'body': '${1:subsection name}\n================$0\n'
  'section 2':
    'prefix': 'subs'
    'body': '${1:subsection name}\n****************$0\n'
  'section 3':
    'prefix': 'sss'
    'body': '${1:subsection name}\n----------------$0\n'
  'code block':
    'prefix': 'code'
    'body': '.. code-block::\n\n\t$1'

Add snippet for inserting a vanilla code-block


class PG.Legend

  defaults:
    className: "legend"

  constructor: (container, @graphs, options) ->
    @container = $(container)
    @options = $.extend @defaults, options
    @element = $("

").addClass(@options.className)
    @container.append @element

    @legend = new Rickshaw.Graph.Legend
      graph: @graphs[0]
      element: @element.get(0)
      naturalOrder: yes

    instance = @
    @graphSeries = {}
    for line, i in @legend.lines
      $label = $(line.element).find("span").first()
      $label.attr "rel", line.series.name
      @graphSeries[line.series.name] =
        series   : _.map @graphs, (graph) -> graph.series[graph.series.length - 1 - i]
        disabled : no
      $label.on "click", ->
        instance.toggle $(this)

  toggle: ($label) ->
    $line = $label.parent(".line")
    name = $label.attr("rel")
    graphSeries = @graphSeries[name]

    if graphSeries.disabled
      graphSeries.disabled = no
      series.disabled = no for series in graphSeries.series
      $label.removeClass "#{@options.className}__label_disabled"
      $line.removeClass "disabled"
    else
      return if _.every(_.pluck(_.without(@graphSeries, graphSeries), "disabled"))
      graphSeries.disabled = yes
      series.disabled = yes for series in graphSeries.series
      $label.addClass "#{@options.className}__label_disabled"
      $line.addClass "disabled"
    @updateGraphs()

  updateGraphs: ->
    graph.update() for graph in @graphs

class PG.Legend

  defaults:
    className: "legend"

  constructor: (container, @graphs, options) ->
    @container = $(container)
    @options = $.extend @defaults, options
    @element = $("

").addClass(@options.className)
    @container.append @element

    @legend = new Rickshaw.Graph.Legend
      graph: @graphs[0]
      element: @element.get(0)
      naturalOrder: yes

    instance = @
    @graphSeries = {}
    for line, i in @legend.lines
      $label = $(line.element).find("span").first()
      $label.attr "rel", line.series.name
      @graphSeries[line.series.name] =
        series   : _.map @graphs, (graph) -> graph.series[i]
        disabled : no
      $label.on "click", ->
        instance.toggle $(this)

  toggle: ($label) ->
    $line = $label.parent(".line")
    name = $label.attr("rel")
    graphSeries = @graphSeries[name]

    if graphSeries.disabled
      graphSeries.disabled = no
      series.disabled = no for series in graphSeries.series
      $label.removeClass "#{@options.className}__label_disabled"
      $line.removeClass "disabled"
    else
      return if _.every(_.pluck(_.without(@graphSeries, graphSeries), "disabled"))
      graphSeries.disabled = yes
      series.disabled = yes for series in graphSeries.series
      $label.addClass "#{@options.className}__label_disabled"
      $line.addClass "disabled"
    @updateGraphs()

  updateGraphs: ->
    graph.update() for graph in @graphs

Make graphs <-> series mapping use naturalOrder too


# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

roundUpBy = (value, round_to) ->
  return round_to * Math.ceil(value / round_to)

$ ->
  metricsInview = new (Waypoint.Inview)(
    element: $('.metric-box')[0]
    enter: (direction) ->
      $(".metric-box strong").each (index) ->
        $this = $(this)
        $target_count = parseInt($this.text().replace(/\,/g, ''))

        jQuery(counter: 0).animate { counter: $target_count },
          duration: 400 + index * 200
          easing: "easeInOutQuint"
          step: ->
            $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
          complete: ->
            jQuery(counter: $target_count).animate { counter: (3 + $target_count) },
              duration: 1300 + index * 600
              easing: "easeOutQuint"
              step: ->
                $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
                return
            return
        return
      # only run this once
      this.destroy()
  )

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

roundUpBy = (value, round_to) ->
  return round_to * Math.ceil(value / round_to)

$ ->
  metricsInview = new (Waypoint.Inview)(
    element: $('.metric-box')[0]
    enter: (direction) ->
      $(".metric-box strong").each (index) ->
        $this = $(this)
        $target_count = parseInt($this.text().replace(/\,/g, ''))

        jQuery(counter: 0).animate { counter: $target_count },
          duration: 400 + index * 200
          easing: "easeInOutQuint"
          step: ->
            $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
          complete: ->
            jQuery(counter: $target_count).animate { counter: (40 + $target_count) },
              duration: 400
              easing: "easeOutQuint"
              step: ->
                $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
                return
            return
        return
      # only run this once
      this.destroy()
  )

Make the easing smoother at the end

Make the easing smoother at the end


window.App ||= {}

App.Visualization = require './visualization.js'
App.Story         = require './story.js'
App.Trix          = require 'script!trix'

$(document).ready ->

  # Activate tooltips
  $('[data-toggle="tooltip"]').tooltip()

  $body = $('body')

  # visualizations
  if $body.hasClass 'visualizations'
    # /visualizations/:id
    # /visualizations/:id/edit
    appVisualization = new App.Visualization $('body').data('visualization-id'), $body.hasClass('edit')
    appVisualization.render()
    $( window ).resize appVisualization.resize
  # stories
  else if $body.hasClass 'stories'
    # /stories/:id
    # /stories/:id/edit
    appStory = new App.Story $('body').data('story-id'), $('body').data('visualization-id'), $body.hasClass('edit')
    appStory.render()
    $( window ).resize appStory.resize

  # Add file input feedback
  # based on http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/
  $(document).on 'change', '.btn-file :file', () ->
      label     = $(this).val().replace(/\\/g, '/').replace(/.*\//, '')
      $(this).parent().siblings('.btn-file-output').html label

window.App ||= {}

App.Visualization = require './visualization.js'
App.Story         = require './story.js'
App.Trix          = require 'script!trix'

$(document).ready ->

  $body = $('body')

  # visualizations
  if $body.hasClass 'visualizations'
    # /visualizations/:id
    # /visualizations/:id/edit
    appVisualization = new App.Visualization $('body').data('visualization-id'), $body.hasClass('edit')
    appVisualization.render()
    $( window ).resize appVisualization.resize
  # stories
  else if $body.hasClass 'stories'
    # /stories/:id
    # /stories/:id/edit
    appStory = new App.Story $('body').data('story-id'), $('body').data('visualization-id'), $body.hasClass('edit')
    appStory.render()
    $( window ).resize appStory.resize

  # Activate tooltips
  $('[data-toggle="tooltip"]').tooltip()

  # Setup select-all checkbox in Chapter new/edit
  $('#relations_select_all').change (e) ->
    $('.table tbody input[type=checkbox]').prop 'checked', $(this).prop('checked')

  # Add file input feedback
  # based on http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/
  $(document).on 'change', '.btn-file :file', () ->
      label     = $(this).val().replace(/\\/g, '/').replace(/.*\//, '')
      $(this).parent().siblings('.btn-file-output').html label

Implement global selection in relations table from New Chapter

Closes #136


noflo = require "noflo"

class DuplicateProperty extends noflo.Component
    constructor: ->
        @properties = {}

        @inPorts =
            property: new noflo.ArrayPort()
            in: new noflo.Port()
        @outPorts =
            out: new noflo.Port()

        @inPorts.property.on "data", (data) =>
            @setProperty data

        @inPorts.in.on "begingroup", (group) =>
            @outPorts.out.beginGroup group
        @inPorts.in.on "data", (data) =>
            @addProperties data
        @inPorts.in.on "endgroup", =>
            @outPorts.out.endGroup()
        @inPorts.in.on "disconnect", =>
            @outPorts.out.disconnect()

    setProperty: (prop) ->
        if typeof prop is "object"
            @prop = prop
            return

        propParts = prop.split "="
        @properties[propParts[0]] = propParts[1]

    addProperties: (object) ->
        for original, newprop of @properties
            object[newprop] = object[original]

        @outPorts.out.send object

exports.getComponent = -> new DuplicateProperty

noflo = require "noflo"

class DuplicateProperty extends noflo.Component
    constructor: ->
        @properties = {}
        @separator = '/'

        @inPorts =
            property: new noflo.ArrayPort()
            separator: new noflo.Port()
            in: new noflo.Port()
        @outPorts =
            out: new noflo.Port()

        @inPorts.property.on "data", (data) =>
            @setProperty data
        @inPorts.separator.on "data", (data) =>
            @separator = data

        @inPorts.in.on "begingroup", (group) =>
            @outPorts.out.beginGroup group
        @inPorts.in.on "data", (data) =>
            @addProperties data
        @inPorts.in.on "endgroup", =>
            @outPorts.out.endGroup()
        @inPorts.in.on "disconnect", =>
            @outPorts.out.disconnect()

    setProperty: (prop) ->
        if typeof prop is "object"
            @prop = prop
            return

        propParts = prop.split "="
        if propParts.length > 2
            @properties[propParts.pop()] = propParts
            return

        @properties[propParts[1]] = propParts[0]

    addProperties: (object) ->
        for newprop, original of @properties
            if typeof original is "string"
                object[newprop] = object[original]
                continue

            newValues = []
            for originalProp in original
                newValues.push object[originalProp]
            object[newprop] = newValues.join @separator

        @outPorts.out.send object

exports.getComponent = -> new DuplicateProperty

Support for merging multiple properties into one


events = require "events"

class Port extends events.EventEmitter
    constructor: (name) ->
        @name = name
        @socket = null
        @from = null

    attach: (socket) ->
        throw new Error "#{@name}: Socket already attached #{@socket.getId()} - #{socket.getId()}" if @socket
        @socket = socket

        @attachSocket socket

    attachSocket: (socket) ->
        @emit "attach", socket

        @from = socket.from
        socket.on "connect", =>
            @emit "connect", socket
        socket.on "data", (data) =>
            @emit "data", data
        socket.on "disconnect", =>
            @emit "disconnect", socket

    detach: (socket) ->
        @emit "detach", @socket
        @from = null
        @socket = null

    send: (data, id) ->
        return @socket.send data if @isConnected()

        @socket.once "connect", =>
            @socket.send data
        @socket.connect id

    connect: (id) ->
        throw new Error "No connection available" unless @socket
        @socket.connect id

    disconnect: ->
        return unless @socket
        @socket.disconnect()

    isConnected: ->
        unless @socket
            return false
        @socket.isConnected()

exports.Port = Port

events = require "events"

class Port extends events.EventEmitter
    constructor: (name) ->
        @name = name
        @socket = null
        @from = null

    attach: (socket) ->
        throw new Error "#{@name}: Socket already attached #{@socket.getId()} - #{socket.getId()}" if @socket
        @socket = socket

        @attachSocket socket

    attachSocket: (socket) ->
        @emit "attach", socket

        @from = socket.from
        socket.on "connect", =>
            @emit "connect", socket
        socket.on "data", (data) =>
            @emit "data", data
        socket.on "disconnect", =>
            @emit "disconnect", socket

    detach: (socket) ->
        @emit "detach", @socket
        @from = null
        @socket = null

    send: (data, id) ->
        throw new Error "No connection available" unless @socket

        return @socket.send data if @isConnected()

        @socket.once "connect", =>
            @socket.send data
        @socket.connect id

    connect: (id) ->
        throw new Error "No connection available" unless @socket
        @socket.connect id

    disconnect: ->
        return unless @socket
        @socket.disconnect()

    isConnected: ->
        unless @socket
            return false
        @socket.isConnected()

exports.Port = Port

Throw an error if sending to an unattached port


$.fn.edit = ->
  form = new Phalange( el: @ )
  @

class Phalange extends Backbone.View
  initialize: ->
    @text = @$el.text()

  events:
    "click": "append"
    "submit": "submit"
    "blur": "submit"

  submit: ->
    @text = @_input().val()
    @$el.trigger 'phalange:submit', @text
    @hideForm()
    @setText()

  setText: ->
    @$el.text @_input().val()

  hideForm: ->
    @_phalange().hide()

  append: ->
    @$el.text ''
    @$el.append @_$form() unless @_phalange_present()

  _phalange_present: ->
    @_phalange().length is 1

  _phalange: ->
    @$el.find('.phalange-form')

  _input: ->
    @$el.find('input')

  _$form: ->
    template = """
      <form class= 'phalange-form' action='javascript:void(0)'>
        <input type='text' value="#{@text}">
        </input>
      </form>
    """
    $(template)

module?.exports = Phalange

$.fn.edit = ->
  form = new Phalange( el: @ )
  @

class Phalange extends Backbone.View
  initialize: ->
    @text = @$el.text()

  events:
    "click": "append"
    "submit": "submit"
    "blur input": "submit"

  submit: ->
    @text = @_input().val()
    @$el.trigger 'phalange:submit', @text
    @hideForm()
    @setText()

  setText: ->
    @$el.text @_input().val()

  hideForm: ->
    @_phalange().hide()

  append: ->
    @$el.text ''
    @$el.append @_$form() unless @_phalange_present()

  _phalange_present: ->
    @_phalange().length is 1

  _phalange: ->
    @$el.find('.phalange-form')

  _input: ->
    @$el.find('input')

  _$form: ->
    template = """
      <form class= 'phalange-form' action='javascript:void(0)'>
        <input type='text' value="#{@text}">
        </input>
      </form>
    """
    $(template)

if module?
  module.exports = Phalange
else
  window.Phalange = Phalange

Add to window when in the browser, listen for blur


class EditorPane extends Pane

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

    options.cssClass = KD.utils.curry "editor-pane", options.cssClass

    super options, data

    @createEditor()

  createEditor: ->
    {file, content} = @getOptions()
    isLocalFile     = no

    unless file instanceof FSFile
      return new Error "File must be an instance of FSFile"

    unless content
      return new Error "You must pass file content to EditorPane"

    @ace = new Ace { delegate : this }, file
    @addSubView @ace
    @ace.once "ace.ready", =>
      @getEditor().setValue content, 1
      @ace.setReadOnly yes  if @getOptions().readOnly

  getEditor: ->
    return @ace.editor

  getValue: ->
    return  @getEditor().getSession().getValue()

class EditorPane extends Pane

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

    options.cssClass = KD.utils.curry "editor-pane", options.cssClass

    super options, data

    @createEditor()

  createEditor: ->
    {file, content} = @getOptions()
    isLocalFile     = no

    unless file instanceof FSFile
      return new Error "File must be an instance of FSFile"

    unless content
      return new Error "You must pass file content to EditorPane"

    @ace = new AceView { delegate: this }, file
    @addSubView @ace
    @ace.once "ace.ready", =>
      @getEditor().setValue content, 1
      @ace.setReadOnly yes  if @getOptions().readOnly

  getEditor: ->
    return @ace.editor

  getValue: ->
    return  @getEditor().getSession().getValue()

Use AceView which is bundled editor of Koding for EditorPane.


$(document).ready ->
  # Photo grid
  photoGrid = $(".photo-grid")
  photoGrid.on "reload:grid", ->
    opts = wookmarkOptions(calculateGridWidth())
    photoGrid.find(".photo, .user-block").wookmark(opts)

  photoGrid.trigger "reload:grid"

  $(window).resize ->
    photoGrid.trigger "reload:grid"

  # Description size tweaking on photo show
  image = $(".display .image img")
  description = image.siblings(".description")
  if image.length > 0
    image.on "resize:description", ->
      if description.length > 0
        description.innerWidth(image.width())
        if description.is(":hidden")
          description.fadeIn()

    $(".display").imagesLoaded ->
      image.trigger "resize:description"

    $(window).resize ->
      image.trigger "resize:description"

$(document).ready ->
  # Photo grid
  photoGrid = $(".photo-grid")
  photoGrid.on "reload:grid", ->
    opts = wookmarkOptions(calculateGridWidth())
    photoGrid.find(".photo, .user-block").wookmark(opts)

  photoGrid.imagesLoaded ->
    photoGrid.trigger "reload:grid"

  $(window).resize ->
    photoGrid.trigger "reload:grid"

  # Description size tweaking on photo show
  image = $(".display .image img")
  description = image.siblings(".description")
  if image.length > 0
    image.on "resize:description", ->
      if description.length > 0
        description.innerWidth(image.width())
        if description.is(":hidden")
          description.fadeIn()

    $(".display").imagesLoaded ->
      image.trigger "resize:description"

    $(window).resize ->
      image.trigger "resize:description"

Fix for photo grid overlap

Fix for photo grid overlap


CSV = require('csv')
Q = require('q')

argv = require('optimist')
  .usage('Usage: $0 --types product-types.csv --attributes product-types-attributes.csv')
  .demand(['types', 'attributes'])
  .argv

ProductTypeGenerator = require('../main').ProductTypeGenerator

###
Reads a CSV file by given path and returns a promise for the result.
@param {string} path The path of the CSV file.
@return Promise of csv read result.
###
readCsvPromise = (path) ->
  deferred = Q.defer()
  CSV().from.path(path)
  .to (data) ->
    deferred.resolve(data)
  .on "error", (error) ->
    deferred.reject(new Error(error))
  deferred.promise

promises = Q.all [readCsvPromise(argv.types), readCsvPromise(argv.attributes)]

Q.spread promises, (types, attributes) ->
  generator = new ProductTypeGenerator
  generator.run types, attributes, (success) ->
    process.exit 1 unless success

CSV = require('csv')
Q = require('q')

argv = require('optimist')
  .usage('Usage: $0 --types product-types.csv --attributes product-types-attributes.csv')
  .demand(['types', 'attributes'])
  .argv

ProductTypeGenerator = require('../main').ProductTypeGenerator

###
Reads a CSV file by given path and returns a promise for the result.
@param {string} path The path of the CSV file.
@return Promise of csv read result.
###
readCsvPromise = (path) ->
  deferred = Q.defer()
  CSV().from.path(path)
  .to (data) ->
    deferred.resolve(data)
  .on "error", (error) ->
    deferred.reject(new Error(error))
  deferred.promise

promises = Q.all [readCsvPromise(argv.types), readCsvPromise(argv.attributes)]

promises.spread (types, attributes) ->
  generator = new ProductTypeGenerator
  generator.run types, attributes, (success) ->
    process.exit 1 unless success

Use instance method instead static method.


import fetch from 'isomorphic-fetch';

port = (process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || '3000')
ip = (process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1')
export API_URL = (if (typeof window == 'undefined') then ('http://' + ip + ':' + port) else '') + '/api/'

export callApiWithBody = (endpoint, method, headers, body) ->
    response = await fetch(API_URL + endpoint, {
        credentials: 'same-origin',
        method: method,
        headers,
        body
    })
    try
        return await response.json()
    catch
        return {}

export default callApi = (endpoint, data) ->
    method = if data then 'POST' else 'GET'
    headers = {
        'Content-Type': 'application/json'
    }
    body = JSON.stringify(data)
    return callApiWithBody(endpoint, method, headers, body)

import fetch from 'isomorphic-fetch';

port = (process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || '3000')
ip = (process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1')
protocol = (if process.env.FORCE_HTTPS then 'https' else 'http')
export API_URL = (if (typeof window == 'undefined') then (protocol + '://' + ip + ':' + port) else '') + '/api/'

export callApiWithBody = (endpoint, method, headers, body) ->
    response = await fetch(API_URL + endpoint, {
        credentials: 'same-origin',
        method: method,
        headers,
        body
    })
    try
        return await response.json()
    catch
        return {}

export default callApi = (endpoint, data) ->
    method = if data then 'POST' else 'GET'
    headers = {
        'Content-Type': 'application/json'
    }
    body = JSON.stringify(data)
    return callApiWithBody(endpoint, method, headers, body)

Call https api if we are on https

Call https api if we are on https


# Export Google WebFont Config
window.WebFontConfig =
    # Load some fonts from google
    google:
        families: []

    # ... you can do something here if you'd like
    active: () ->

# Create script tag matching protocol
s = document.createElement 'script'
s.src = "#{if document.location.protocol is 'https:' then 'https' else 'http'}://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"
s.type = 'text/javascript'
s.async = 'true'

# Insert it before the first script tag
s0 = (document.getElementsByTagName 'script')[0]
s0.parentNode.insertBefore s, s0

$ ->
    console.log "Document ready."
    startRenderer()
    startNetworking()
    startInput()

Bring in code to load google fonts

Bring in code to load google fonts


class ViewerAppController extends KDViewController

  KD.registerAppClass this,
    name         : "Viewer"
    route        : "/Develop"
    multiple     : yes
    openWith     : "forceNew"
    behavior     : "application"
    preCondition :

      condition  : (options, cb)->
        {path, vmName} = options
        return cb true  unless path
        path = FSHelper.plainPath path
        publicPath = path.replace \
          ///.*\/(.*\.#{KD.config.userSitesDomain})\/(.*)///, 'http://$1/$2'

        cb publicPath isnt path, {path: publicPath}

      failure    : (options, cb)->
        correctPath = \
          "/home/#{KD.nick()}/Sites/#{KD.nick()}.#{KD.config.userSitesDomain}/"
        KD.getSingleton("appManager").notify "File must be under: #{correctPath}"

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

    options.view = new PreviewerView
      params     : options.params

    options.appInfo =
      title         : "Preview"
      cssClass      : "ace"

    super options, data

  open:(path)->
    @getView().openPath path

class ViewerAppController extends KDViewController

  KD.registerAppClass this,
    name         : "Viewer"
    route        : "/Develop"
    multiple     : yes
    openWith     : "forceNew"
    behavior     : "application"
    preCondition :

      condition  : (options, cb)->
        {path, vmName} = options
        return cb true  unless path
        path = FSHelper.plainPath path
        publicPath = path.replace \
          ///.*\/(.*\.#{KD.config.userSitesDomain})\/(.*)///, 'http://$1/$2'

        cb publicPath isnt path, {path: publicPath}

      failure    : (options, cb)->
        correctPath = \
          "/home/#{KD.nick()}/Web/"
        KD.getSingleton("appManager").notify "File must be under: #{correctPath}"

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

    options.view = new PreviewerView
      params     : options.params

    options.appInfo =
      title         : "Preview"
      cssClass      : "ace"

    super options, data

  open:(path)->
    @getView().openPath path

Change folder to match new osKite default


goog.provide 'app.react.pages.NotFound'

class app.react.pages.NotFound

  ###*
    @constructor
  ###
  constructor: ->
    {div,h1,p} = React.DOM

    @create = React.createClass

      render: ->
        div className: 'notfound',
          h1 null, "This page isn't available"
          p null, "The link may be broken, or the page may have been removed."

goog.provide 'app.react.pages.NotFound'

class app.react.pages.NotFound

  ###*
    @param {app.Routes} routes
    @param {app.react.Touch} touch
    @constructor
  ###
  constructor: (routes, touch) ->
    {div,h1,p} = React.DOM
    {a} = touch.none 'a'

    @create = React.createClass

      render: ->
        div className: 'notfound',
          h1 null, "This page isn't available"
          p null, 'The link may be broken, or the page may have been removed.'
          a href: routes.home.createUrl(), 'Continue here please.'

Add link to home for 404 page.

Add link to home for 404 page.


openMultiPageModal = require '../../../components/multi_page_modal/index.coffee'
SpecialistView = require '../../../components/contact/general_specialist.coffee'

module.exports.init = ->
  $('.js-contact-specialist').click (e) ->
    e.preventDefault()
    new SpecialistView

  $('.js-multi-page-modal').click (e) ->
    e.preventDefault()
    openMultiPageModal $(this).data('id')

openMultiPageModal = require '../../../components/multi_page_modal/index.coffee'
SpecialistView = require '../../../components/contact/general_specialist.coffee'
FeebackView = require '../../../components/contact/feedback.coffee'

module.exports.init = ->
  $('.js-contact-specialist').click (e) ->
    e.preventDefault()
    new SpecialistView

  $('.js-contact-feedback').click (e) ->
    e.preventDefault()
    new FeebackView

  $('.js-multi-page-modal').click (e) ->
    e.preventDefault()
    openMultiPageModal $(this).data('id')

Add handler to invoke feedback modal

Add handler to invoke feedback modal


# Copyright 2012 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ##core/zone
#
# Provides a default handler for the `events.zone.update` event, attached to the
# document body.
define ["core/spi", "core/events"],
  (spi, events) ->
    spi.domReady ->
      spi.body().on events.zone.update, (event) ->
        zone = spi.wrap this

        zone.trigger events.zone.willUpdate

        # TODO: purge existing children?

        zone.update event.memo

        zone.show() unless zone.visible()

        zone.trigger events.zone.didUpdate

    # No meaningful value is returned.
    true

# Copyright 2012 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ##core/zone
#
# Provides a default handler for the `events.zone.update` event, attached to the
# document body.
define ["core/spi", "core/events"],
  (spi, events) ->
    spi.domReady ->
      spi.body().on events.zone.update, (event) ->

        this.trigger events.zone.willUpdate

        # TODO: purge existing children?

        this.update event.memo

        this.show() unless this.visible()

        this.trigger events.zone.didUpdate

    # No meaningful value is returned.
    return

Adjust initialization for this being the matched element's ElementWrapper


$ ->
  $('#currency').change ->
    $.ajax(
      type: 'POST'
      url: $(this).data('href')
      data:
        currency: $(this).val()
    ).done ->
      window.location.reload()

$ ->
  $('#currency').on 'change', ->
    $.ajax(
      type: 'POST'
      url: $(this).data('href')
      data:
        currency: $(this).val()
    ).done ->
      window.location.reload()

Use jQuery "on" for event hook.

Use jQuery "on" for event hook.


ValidationMixin =
  getInitialState: ->
    validationErrors: []
    hasErrors: false

  componentDidMount: ->
    if @props.validators
      @loadValidators()

  loadValidators: ->
    @validators = _.map @props.validators, (options, name) =>
      new window.validators[name].constructor(options)

  validate: (value, callback) ->
    if @props.validators
      newErrors = _.map @validators, (validator) =>
        validator.validate value, @props.displayName

      # There is probably a better way to do this
      newErrors = _.flatten newErrors
      newErrors = _.without newErrors, null, undefined

      @setState
        validationErrors: newErrors
        hasErrors: (newErrors.length != 0)
        , callback()
    else
      callback() if callback

module.exports = ValidationMixin

ValidationMixin =
  getInitialState: ->
    validationErrors: []
    hasErrors: false

  validate: (value, callback) ->
    if @props.validators
      newErrors = _.map @props.validators, (validator) =>
        validator.validate value, @props.displayName

      # There is probably a better way to do this
      newErrors = _.flatten newErrors
      newErrors = _.without newErrors, null, undefined

      @setState
        validationErrors: newErrors
        hasErrors: (newErrors.length != 0)
        , callback()
    else
      callback() if callback

module.exports = ValidationMixin

Update Validators to pass Instances instead of references


#= require ./abstract_binding

class Batman.DOM.ViewBinding extends Batman.DOM.AbstractBinding
  skipChildren: true
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  constructor: (definition) ->
    @superview = definition.view
    super

  dataChange: (viewClassOrInstance) ->
    return unless viewClassOrInstance?
    if viewClassOrInstance.isView
      @view = viewClassOrInstance
    else
      @view = new viewClassOrInstance

    @yieldName = "<#{@view.constructor.name}-#{@view._batmanID()}>"
    @superview.declareYieldNode(@yieldName, @node)
    @superview.subviews.set(@yieldName, @view)

  die: ->
    @superview.unset(@yieldName)
    @superview = null
    @view = null
    super

#= require ./abstract_binding

class Batman.DOM.ViewBinding extends Batman.DOM.AbstractBinding
  skipChildren: true
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  constructor: (definition) ->
    @superview = definition.view
    super

  dataChange: (viewClassOrInstance) ->
    return unless viewClassOrInstance?
    if viewClassOrInstance.isView
      @view = viewClassOrInstance
    else
      @view = new viewClassOrInstance

    @yieldName = "<#{@view.constructor.name || 'UnknownView'}-#{@view._batmanID()}>"
    @superview.declareYieldNode(@yieldName, @node)
    @superview.subviews.set(@yieldName, @view)

  die: ->
    @superview.unset(@yieldName)
    @superview = null
    @view = null
    super

Handle constructor.name being undefined in ViewBinding.


module.exports  =
  current: 'ami-bf235ad5'

  # Ordered by creation date
  list: [
    'ami-5dd50436'
    'ami-bf235ad5'
  ]

module.exports  =
  current: 'ami-4d552d27'

  # Ordered by creation date
  list: [
    'ami-5dd50436'
    'ami-bf235ad5'
    'ami-4d552d27'
  ]

Update test instance AMI identifier

Update test instance AMI identifier


microflo = (target) ->
    build = [
        "make -f ./node_modules/microflo-emscripten/Makefile"
        target
        "BUILD_DIR=build"
        "MICROFLO=./node_modules/.bin/microflo"
        "GRAPH=graph.fbp"
        "MICROFLO_SOURCE_DIR=`pwd`/node_modules/microflo/microflo"
        "LIBRARY=`pwd`/components/arduino-standard.json"
    ]
    return build.join ' '

module.exports = ->
  # Project configuration
  @initConfig

    # lint
    coffeelint:
      code:
        files:
          src: ['lib/*.coffee', 'spec/*.coffee']
        options:
          max_line_length:
            value: 100
            level: 'warn'
          no_trailing_semicolons:
            level: 'warn'

    # TODO: Browser build

    exec:
        microflo_emscripten: microflo "build-emscripten"

    mochaTest:
      nodejs:
        src: ['spec/*.coffee']
        options:
          reporter: 'spec'
          require: 'coffee-script/register'
          grep: process.env.TESTS

  # Grunt plugins used for building
  @loadNpmTasks 'grunt-exec'

  # Grunt plugins used for testing
  @loadNpmTasks 'grunt-mocha-test'

  # Our local tasks
  @registerTask 'build', [
    'exec:microflo_emscripten'
  ]

  @registerTask 'test', [
    'build'
    'mochaTest'
  ]

  @registerTask 'default', ['test']

microflo = (target) ->
    build = [
        "make -f ./node_modules/microflo-emscripten/Makefile"
        target
        "BUILD_DIR=build"
        "MICROFLO=./node_modules/.bin/microflo"
        "GRAPH=graph.fbp"
        "MICROFLO_SOURCE_DIR=`pwd`/node_modules/microflo/microflo"
        "PROJECT_DIR=`pwd`/node_modules/microflo-emscripten"
        "LIBRARYOPTION='--library `pwd`/components/arduino-standard.json'"
    ]
    return build.join ' '

module.exports = ->
  # Project configuration
  @initConfig

    # lint
    coffeelint:
      code:
        files:
          src: ['lib/*.coffee', 'spec/*.coffee']
        options:
          max_line_length:
            value: 100
            level: 'warn'
          no_trailing_semicolons:
            level: 'warn'

    # TODO: Browser build

    exec:
        microflo_emscripten: microflo "build-emscripten"

    mochaTest:
      nodejs:
        src: ['spec/*.coffee']
        options:
          reporter: 'spec'
          require: 'coffee-script/register'
          grep: process.env.TESTS

  # Grunt plugins used for building
  @loadNpmTasks 'grunt-exec'

  # Grunt plugins used for testing
  @loadNpmTasks 'grunt-mocha-test'

  # Our local tasks
  @registerTask 'build', [
    'exec:microflo_emscripten'
  ]

  @registerTask 'test', [
    'build'
    'mochaTest'
  ]

  @registerTask 'default', ['test']

Grunt: Fix options passed to microflo-emscripten


describe "Lanes.Models.Collection", ->

    it "it triggers promise on loading", (done) ->
        Model = Lanes.Test.defineModel
            props: { id: 'integer', title: 'string' }

        LT.syncSucceedWith([
            { id: 1, title: 'first value'  }
            { id: 2, title: 'second value' }
        ])
        collection = Model.where(name: 'foo')
        expect(collection.requestInProgress).toBeDefined()
        collection.whenLoaded ->
            expect( collection.isLoaded() ).toBe(true)
            done()

    it "triggers length when changed", ->
        Model = Lanes.Test.defineModel
            props: { id: 'integer', title: 'string' }

        collection = new Model.Collection
        spy = jasmine.createSpy('onLengthChange')
        collection.on("change:length", spy)
        model = collection.add({ id: 1, title: 'first' })
        expect(spy).toHaveBeenCalled()
        spy.calls.reset()
        collection.remove(model)
        expect(spy).toHaveBeenCalled()
        spy.calls.reset()
        collection.reset([{ id:11, title: 'last'}])
        expect(spy).toHaveBeenCalled()

    it 'prevents duplicates when copying from', ->
        Model = Lanes.Test.defineModel
            props: { id: 'integer', title: 'string' }
        collection = new Model.Collection
        a = collection.add({ id: 1, title: 'first'  })
        b = collection.add({ id: 2, title: 'second' })
        c = collection.add({ id: 3, title: 'third'  })
        a.copyFrom(c)
        expect(collection.pluck('id')).toEqual([2, 3, 1])

Test duplicate prevention when copying

Test duplicate prevention when copying


module.exports =
  configDefaults:
    showOnRightSideOfStatusBar: false

  activate: ->
    atom.workspaceView.command('grammar-selector:show', createGrammarListView)
    atom.packages.once('activated', createGrammarStatusView)

createGrammarListView = ->
  editor = atom.workspace.getActiveEditor()
  if editor?
    GrammarListView = require './grammar-list-view'
    view = new GrammarListView(editor)
    view.attach()

createGrammarStatusView = ->
  {statusBar} = atom.workspaceView
  if statusBar?
    GrammarStatusView = require './grammar-status-view'
    view = new GrammarStatusView(statusBar)
    view.attach()

module.exports =
  configDefaults:
    showOnRightSideOfStatusBar: true

  activate: ->
    atom.workspaceView.command('grammar-selector:show', createGrammarListView)
    atom.packages.once('activated', createGrammarStatusView)

createGrammarListView = ->
  editor = atom.workspace.getActiveEditor()
  if editor?
    GrammarListView = require './grammar-list-view'
    view = new GrammarListView(editor)
    view.attach()

createGrammarStatusView = ->
  {statusBar} = atom.workspaceView
  if statusBar?
    GrammarStatusView = require './grammar-status-view'
    view = new GrammarStatusView(statusBar)
    view.attach()

Put grammar selector on the right side by default

This will make it play nicer with showing more information after the
character position on the left side such as the character count.

Refs atom/status-bar#31


kd   = require 'kd'

nick    = require 'app/util/nick'
Tracker = require 'app/util/tracker'

module.exports = (machine) ->

  return  unless analytics
  return  unless typeof analytics.user is 'function'

  { initialTurnOn } = analytics.user().traits()
  return  if initialTurnOn

  initialTurnOn = yes
  analytics.identify nick(), { initialTurnOn }
  execute machine

execute = (machine) ->

  track Tracker.BUTTON_CLICKED

  kd.singletons.computeController.once 'MachineBuilt', (event) ->

    { machineId } = event

    return  if machineId isnt machine._id

    track Tracker.MODAL_DISPLAYED

track = (action) ->
  Tracker.track action, { category: Tracker.CATEGORY_TURN_ON_VM }

kd   = require 'kd'

nick    = require 'app/util/nick'
Tracker = require 'app/util/tracker'

module.exports = (machine) ->

  fetchStorage (storage) ->

    turnedOnMachine = storage.getValue 'TurnedOnMachine'

    return  if turnedOnMachine

    storage.setValue 'TurnedOnMachine', yes
    execute machine

fetchStorage = (callback) ->

  { appStorageController } = kd.singletons
  storage = appStorageController.storage 'Environments', '1.0'

  storage.ready -> callback storage

execute = (machine) ->

  track Tracker.BUTTON_CLICKED

  kd.singletons.computeController.once 'MachineBuilt', (event) ->

    { machineId } = event

    return  if machineId isnt machine._id

    track Tracker.MODAL_DISPLAYED

track = (action) ->
  Tracker.track action, { category: Tracker.CATEGORY_TURN_ON_VM }

Store initial machine turn on state in AppStorage


Q = require 'q'

# Provides a set of methods for voting data CRUD operations
class API
  constructor: (@db) ->
    throw "must provide db connection" unless @db

  createUser: (name) ->
    # Q.nfcall(
    #   @db.models.User.create,
    #   name: name
    # )

    # @db.models.User.create({
      # name: name
    # }, (err, user) ->

    deferred = Q.defer()
    user = new @db.models.User({name: name})
    user.save (err) ->
      if err
        deferred.reject(new Error(err))
      else
        deferred.resolve(user)

    deferred.promise

  incrementVote: ->

  decrementVote: (voteId) ->

  listUsers: (userId) ->

module.exports = API

Q = require 'q'

# Provides a set of methods for voting data CRUD operations
class API
  constructor: (@db) ->
    throw "must provide db connection" unless @db
    @models = @db.models

  createUser: (name) ->
    create = Q.nbind(
      @models.User.create,
      @models.User
    )
    create name: name

  incrementVote: ->

  decrementVote: (voteId) ->

  listUsers: (userId) ->

module.exports = API

Use Q nbind to make this cleaner

Use Q nbind to make this cleaner


{toggleQuotes} = require 'toggle-quotes'
{CompositeDisposable} = require 'atom'

module.exports =
  config:
    quoteCharacters:
      type: 'string'
      default: '"\''

  activate: ->
    @subscriptions.add atom.commands.add 'atom-text-editor', 'toggle-quotes:toggle', ->
      if editor = atom.workspace.getActiveTextEditor()
        toggleQuotes(editor)

  deactivate: ->
    @subscriptions.dispose()

{toggleQuotes} = require 'toggle-quotes'

module.exports =
  config:
    quoteCharacters:
      type: 'string'
      default: '"\''

  activate: ->
    @subscription = atom.commands.add 'atom-text-editor', 'toggle-quotes:toggle', ->
      if editor = atom.workspace.getActiveTextEditor()
        toggleQuotes(editor)

  deactivate: ->
    @subscription.dispose()

Use disposable returned from atom.commands.add


# tool tips

d3panels.tooltip_create = (selection, options) ->
    selection.append("div")
             .attr("class", "d3panels-tooltip")
             .style("opacity", 0)

d3panels.tooltip_activate = (objects, tipdiv, options) ->
    objects.on("mouseover", (d) ->
          tipdiv.html(d.tooltip)

          h = tipdiv.node().getBoundingClientRect().height

          tipdiv.style("left", (d3.event.pageX + d.r*3)+"px")
                .style("top", (d3.event.pageY - h/2)+"px")
                .transition()
                .duration(0)
                .style("opacity", 0.9))

    objects.on("mouseout", (d) ->
              tipdiv.transition()
                  .duration(1000)
                  .style("opacity", 0))

d3panels.tooltip_destroy = (tipdiv) ->
    tipdiv.remove()

# tool tips

d3panels.tooltip_create = (selection, options) ->
    d3.select("body").append("div")
             .attr("class", "d3panels-tooltip #{options.tipclass}")
             .style("opacity", 1)

d3panels.tooltip_activate = (objects, tipdiv, options, tooltip_func) ->
    objects.on("mouseover.d3panels-tooltip", (d,i) ->
          mouseX = d3.event.pageX
          mouseY = d3.event.pageY

          tipdiv.html(tooltip_func(d,i))

          tipbox_height = tipdiv.node().getBoundingClientRect().height

          tipdiv.style("left", "#{(mouseX + 10)}px")
                .style("top", "#{(mouseY - tipbox_height/2)}px")
                .transition()
                .duration(0)
                .style("opacity", 0.9))

    objects.on("mouseout.d3panels-tooltip", (d) ->
              tipdiv.transition()
                  .duration(1000)
                  .style("opacity", 0))

d3panels.tooltip_destroy = (tipdiv) ->
    tipdiv.remove()

Fix problems with initial tooltip code

Fix problems with initial tooltip code


avatarResponder = require('./avatar_responder')
Campfire.Transcript.messageTemplates = require('./message_templates')

window.Chicisimo =
  Responders: []

Campfire.USER_ACTIONS = ['enter','leave','kick','conference_created','lock','unlock','topic_change','allow_guests','disallow_guests']

swizzle(Campfire.Message, {
  authorElement: ($super) ->
    return $super().select('span.author')[0] if Campfire.USER_ACTIONS.include(this.kind)
    $super()
})

Campfire.Chicisimo = Class.create({
  initialize: (chat) ->
    chat.transcript.messages.forEach(this.executeResponders)

    chat.layoutmanager.layout()

    chat.windowmanager.scrollToBottom()
  ,onMessagesInserted: (messages) ->
    scrolledToBottom = chat.windowmanager.isScrolledToBottom()

    messages.forEach(this.executeResponders)

    chat.windowmanager.scrollToBottom() if scrolledToBottom
  ,executeResponders: (message) ->
    Chicisimo.Responders.forEach((responder) -> responder(message) )
})

Chicisimo.Responders.push(avatarResponder)
Campfire.Responders.push("Chicisimo")
window.chat.installPropaneResponder("Chicisimo", "chicisimo")

avatarResponder = require('./avatar_responder')
Campfire.Transcript.messageTemplates = require('./message_templates')

window.Chicisimo =
  Responders: []

Campfire.USER_ACTIONS = ['enter','leave','kick','conference_created','lock','unlock','topic_change','allow_guests','disallow_guests']

swizzle(Campfire.Message, {
  authorElement: ($super) ->
    return $super().select('span.author')[0] if Campfire.USER_ACTIONS.include(this.kind)
    $super()
})

Campfire.Chicisimo = Class.create(
  initialize: (chat) ->
    chat.transcript.messages.forEach(this.executeResponders)

    chat.layoutmanager.layout()

    chat.windowmanager.scrollToBottom()
  ,onMessagesInserted: (messages) ->
    scrolledToBottom = chat.windowmanager.isScrolledToBottom()

    messages.forEach(this.executeResponders)

    chat.windowmanager.scrollToBottom() if scrolledToBottom
  ,executeResponders: (message) ->
    Chicisimo.Responders.forEach((responder) -> responder(message))
)

Chicisimo.Responders.push(avatarResponder)
Campfire.Responders.push("Chicisimo")
window.chat.installPropaneResponder("Chicisimo", "chicisimo")

Remove whitespace and unnecessary parens


angular.module('admin.payments').directive "stripeElements", ($injector, AdminStripeElements) ->
  restrict: 'E'
  template: "\

\

\
             "
  scope:
    selected: "="

  link: (scope, elem, attr)->
    if $injector.has('stripeObject')
      stripe = $injector.get('stripeObject')

      card = stripe.elements().create 'card',
        hidePostalCode: false
        style:
          base:
            fontFamily: "Roboto, Arial, sans-serif"
            fontSize: '16px'
            color: '#5c5c5c'
            '::placeholder':
              color: '#6c6c6c'
      card.mount(elem.find('.card-element').get(0))

      # Elements validates user input as it is typed. To help your customers
      # catch mistakes, you should listen to change events on the card Element
      # and display any errors:
      card.addEventListener 'change', (event) ->
        displayError = elem.find('.card-errors').get(0)
        if event.error
          displayError.textContent = event.error.message
        else
          displayError.textContent = ''

        return

      scope.$watch "selected", (value) ->
        if (value)
          AdminStripeElements.stripe = stripe
          AdminStripeElements.card = card

angular.module('admin.payments').directive "stripeElements", ($injector, AdminStripeElements) ->
  restrict: 'E'
  template: "
\

\

\

"
  scope:
    selected: "="

  link: (scope, elem, attr)->
    if $injector.has('stripeObject')
      stripe = $injector.get('stripeObject')

      card = stripe.elements().create 'card',
        hidePostalCode: false
        style:
          base:
            fontFamily: "Roboto, Arial, sans-serif"
            fontSize: '16px'
            color: '#5c5c5c'
            '::placeholder':
              color: '#6c6c6c'
      card.mount(elem.find('.card-element').get(0))

      # Elements validates user input as it is typed. To help your customers
      # catch mistakes, you should listen to change events on the card Element
      # and display any errors:
      card.addEventListener 'change', (event) ->
        displayError = elem.find('.card-errors').get(0)
        if event.error
          displayError.textContent = event.error.message
        else
          displayError.textContent = ''

        return

      scope.$watch "selected", (value) ->
        if (value)
          AdminStripeElements.stripe = stripe
          AdminStripeElements.card = card

Remove id "card-element" as well

Remove id "card-element" as well


'name': 'Weave.jl markdown'
scopeName: 'source.weave.md'
'fileTypes': [
  'jmd'
  'jmdw'
  'mdw'
]
patterns: [
    {
      'include' : 'source.weave.noweb'
    }
    {
    'begin': '^([`~]{3,})(\\{|\\{\\.|)(julia)(;|)\\s*(.*?)(\\}|)\\s*$'
    'beginCaptures':
      '1':
        'name': 'markup.heading.weave.md'
      '3':
        'name': 'markup.bold.weave.md'
      '5':
        'contentName' : 'source.embedded.julia'
        'patterns': [
          {
            'include': 'source.julia'
          }
        ]
    'end': '^[`~]{3,}\\s*$'
    'endCaptures':
      '0':
        'name': 'markup.heading.weave.md'
    'contentName': 'source.embedded.julia'
    'patterns': [
      {
        'include': 'source.julia'
      }
    ]
    }
    {
      'include': 'source.gfm'
    }
    {
      'include': 'text.md'
    }
]

'name': 'Weave.jl markdown'
'scopeName' : 'source.weave.md'
'fileTypes': [
  'jmd'
  'jmdw'
  'mdw'
]
'patterns': [
    {
      'include' : 'source.weave.noweb'
    }
    {
    'begin': '^([`~]{3,})(\\{|\\{\\.|)(julia)(;|)\\s*(.*?)(\\}|)\\s*$'
    'beginCaptures':
      '1':
        'name': 'markup.heading.weave.md'
      '3':
        'name': 'markup.bold.weave.md'
      '5':
        'contentName' : 'source.embedded.julia'
        'patterns': [
          {
            'include': 'source.julia'
          }
        ]
    'end': '^[`~]{3,}\\s*$'
    'endCaptures':
      '0':
        'name': 'markup.heading.weave.md'
    'contentName': 'source.embedded.julia'
    'patterns': [
      {
        'include': 'source.julia'
      }
    ]
    }
    {
      'begin' : '^(!)\\s(.*)'
      'beginCaptures':
        '1' :
            'name' : 'markup.bold.weave.md'
        '2':
          'contentName': 'source.embedded.julia'
          'patterns' : [
                  {
                    'include': 'source.julia'
                  }
                ]
      'end' : '$'
    }
    {
      'include': 'source.gfm'
    }
    {
      'include': 'text.md'
    }
]

Add support for new inline code format

Add support for new inline code format


Link = require('react-router').Link

module.exports = React.createClass
  displayName: 'HelloWorld'
  render: ->

Hello world!

You're looking at the Coffeescript React Quickstart project by Kyle Mathews.

It has a number of nice goodies included like:

Full Coffeescript support provided by coffee-react-transform

Live reloading for both CSS and Javascript! This really speeds up your development. Live reload of Javascript enabled by the react-hot-loader project.

Gulpfile with both development and production tasks to simplify building your project.

Starter Sass project with sensible defaults. Check them out on the <Link to="styleguide">styleguide page</Link>

Link = require('react-router').Link

module.exports = React.createClass
  displayName: 'HelloWorld'
  render: ->

Hello world!

You're looking at the Coffeescript React Quickstart project by Kyle Mathews.

It has a number of nice goodies included like:

Live reloading for both CSS and Javascript! This really speeds up your development. Live reloading is powered by the Webpack module bundler and the react-hot-loader projects.

Full Coffeescript for React support provided by coffee-react-transform

Amazing URL-driven-development (UDD) with the react-router project

Uses Gulp for building CSS and Javascript. Run `cult watch` for rebuilding css/js on the fly while developing and `cult build` to create minified versions to deploy to production.

Starter Sass project with sensible defaults. Check them out on the <Link to="styleguide">styleguide page</Link>

Uses the best of breed grid system Susy.

Add list of 'batteries included' for demo page


Species.TaxonConceptDocumentsRoute = Ember.Route.extend
  renderTemplate: ->
    @getDocuments()
    @render('taxon_concept/documents')

  getDocuments: ->
    model = this.modelFor("taxonConcept")
    $.ajax(
      url: "/api/v1/documents?taxon_concept_id=" + model.get('id'),
      success: (data) ->
        model.set('cites_cop_docs', data.cites_cop_docs)
        model.set('ec_srg_docs', data.ec_srg_docs)
        model.set('cites_ac_docs', data.cites_ac_docs)
        model.set('cites_pc_docs', data.cites_pc_docs)
        model.set('other_docs', data.other_docs)
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error:" + textStatus)
    )

Species.TaxonConceptDocumentsRoute = Ember.Route.extend
  renderTemplate: ->
    @getDocuments()
    @render('taxon_concept/documents')

  getDocuments: ->
    model = this.modelFor("taxonConcept")
    $.ajax(
      url: "/api/v1/documents?taxon-concepts-ids=" + model.get('id'),
      success: (data) ->
        model.set('cites_cop_docs', data.cites_cop_docs)
        model.set('ec_srg_docs', data.ec_srg_docs)
        model.set('cites_ac_docs', data.cites_ac_docs)
        model.set('cites_pc_docs', data.cites_pc_docs)
        model.set('other_docs', data.other_docs)
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error:" + textStatus)
    )

Update document search usage in taxon concept's page


class Workbench.Views.SensorMapView extends Backbone.Marionette.ItemView
  template: false

  initialize: ->
    @zoom = 13

  onDestroy: ->
    @map.remove() if @map

  onShow: ->
    if @el.id is ""
      console.warn "No Map Element"
    else
      @location = [@model.get("latitude"), @model.get("longitude")]
      @map = L.map(@el.id).setView(@location, @zoom)
      L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        attribution: t('map.attribution')
      }).addTo(@map)

      L.marker(@location).addTo(@map)

class Workbench.Views.SensorMapView extends Backbone.Marionette.ItemView
  template: false

  initialize: ->
    @zoom = 13

  onDestroy: ->
    @map.remove() if @map

  onShow: ->
    if @el.id is ""
      console.warn "No Map Element"
    else
      @location = [@model.get("latitude"), @model.get("longitude")]
      @map = L.map(@el.id).setView(@location, @zoom)
      L.tileLayer(Workbench.tile_url, {
        attribution: Workbench.tile_attribution
      }).addTo(@map)

      L.marker(@location).addTo(@map)

Use master map tile selection for sensor map


module.exports =
class BroadcastTarget
  editor: null
  listener: null
  isMarkdownPreview: false

  constructor: ->
    @editor = atom.workspace.activePaneItem

    @isMarkdownPreview = @editor[0]?

    @editor.on 'markdown-preview:markdown-changed', =>
      @listener?()

  setListener: (listener) ->
    @listener = listener

  getContent: ->
    return if @isMarkdownPreview then @getMarkdownPreviewContent() else @getOtherContent()

  getMarkdownPreviewContent: ->
    content = @editor[0].outerHTML
    if atom.config.get 'broadcast.getEmojisFromCheatSheetSite'
      content = content.replace /[\w-\.\/]+pngs/g, @urlToCheatSheetSite
    else
      content = content.replace /[\w-\.\/]+node_modules\/roaster\/node_modules/g, ''

  getOtherContent: ->
    content = @editor.getText?()
    return '<pre>' + content + '</pre>'

module.exports =
class BroadcastTarget
  editor: null
  listener: null
  isMarkdownPreview: false

  constructor: ->
    @editor = atom.workspace.activePaneItem

    @isMarkdownPreview = @editor[0]?

    @editor.on 'markdown-preview:markdown-changed', =>
      @listener?()

  setListener: (listener) ->
    @listener = listener

  getContent: ->
    return if @isMarkdownPreview then @getMarkdownPreviewContent() else @getOtherContent()

  getMarkdownPreviewContent: ->
    content = @editor[0].outerHTML
    if atom.config.get 'broadcast.getEmojisFromCheatSheetSite'
      content = content.replace /[\w-\.\/]+pngs/g, @urlToCheatSheetSite
    else
      content = content.replace /[\w-\.\/]+node_modules\/roaster\/node_modules/g, ''

  getOtherContent: ->
    content = @editor.getText?()
    .replace /</g, '<'
    .replace />/g, '>'

    return '<pre>' + content + '</pre>'

Fix an issue that '<' and '>' were not shown correctly


'exception-reporting':
  'userId': 'ee24cf00-f793-9081-be2a-2cdae5536b7f'
'release-notes':
  'viewedVersion': '0.64.0'
'welcome':
  'showOnStartup': false
'metrics':
  'userId': '51eeb6113c1ae801c9aade9b6d679aa5189ced25'
'editor':
  'fontFamily': 'Source Code Pro'
  'fontSize': 14
  'preferredLineLength': 100
  'showInvisibles': true
'core':
  'projectHome': '/Volumes/Data/Users/Lee/Source'
  'themes': [
    'atom-dark-ui'
    'railscasts-syntax'
  ]
  'ignoredNames': [
    '.git'
    '.svn'
    '.DS_Store'
  ]
  'disabledPackages': []
'whitespace':
  'ensureSingleTrailingNewline': true
'auto-copyright':
  'owner': 'Lifted Studios'
'spell-check':
  'grammars': [
    'source.gfm'
    'text.git-commit'
    'text.plain'
  ]

Add selectors for spell checking.

Add selectors for spell checking.


"*":
  core:
    telemetryConsent: "limited"
    themes: [
      "one-light-ui"
      "one-light-syntax"
    ]
  editor:
    fontFamily: "'SF Mono', Menlo, Consolas, DejaVu Sans Mono, monospace"
    fontSize: 12
    lineHeight: 1.7
  "one-dark-ui":
    tabCloseButton: "Left"
  "one-light-ui":
    tabCloseButton: "Left"

"*":
  core:
    disabledPackages: [
      "exception-reporting"
    ]
    telemetryConsent: "limited"
    themes: [
      "one-light-ui"
      "one-light-syntax"
    ]
  editor:
    fontFamily: "'SF Mono', Menlo, Consolas, DejaVu Sans Mono, monospace"
    fontSize: 12
    lineHeight: 1.7
  "one-dark-ui":
    tabCloseButton: "Left"
  "one-light-ui":
    tabCloseButton: "Left"

Disable 'exceptino-reporting' so userId GUID isn’t checked in


globals = require 'globals'

module.exports =

  getOperation : (current, selected) ->

    arr = [
      @planTitle.FREE
      @planTitle.HOBBYIST
      @planTitle.DEVELOPER
      @planTitle.PROFESSIONAL
    ]

    current  = arr.indexOf current
    selected = arr.indexOf selected

    return switch
      when selected >  current then @operation.UPGRADE
      when selected is current then @operation.INTERVAL_CHANGE
      when selected <  current then @operation.DOWNGRADE

  planInterval:
    MONTH       : 'month'
    YEAR        : 'year'

  planTitle:
    FREE         : 'free'
    HOBBYIST     : 'hobbyist'
    DEVELOPER    : 'developer'
    PROFESSIONAL : 'professional'

  provider:
    STRIPE : 'stripe'
    PAYPAL : 'paypal'
    KODING : 'koding'

  operation:
    UPGRADE         : 1
    INTERVAL_CHANGE : 0
    DOWNGRADE       : -1

  FAILED_ATTEMPT_LIMIT: 3
  TOO_MANY_ATTEMPT_BLOCK_KEY: 'BlockForTooManyAttempts'
  TOO_MANY_ATTEMPT_BLOCK_DURATION: globals.config.paymentBlockDuration

  error:
    ERR_USER_NOT_CONFIRMED: 'You need to confirm your email to purchase a Koding subscription.'

  events:
    WORKFLOW_STARTED: 'workflowStarted'
    WORKFLOW_COULD_NOT_START: 'workflowCouldNotStart'

globals = require 'globals'

module.exports =

  getOperation : (current, selected) ->

    arr = [
      @planTitle.FREE
      @planTitle.HOBBYIST
      @planTitle.DEVELOPER
      @planTitle.PROFESSIONAL
    ]

    current  = arr.indexOf current
    selected = arr.indexOf selected

    return switch
      when selected >  current then @operation.UPGRADE
      when selected is current then @operation.INTERVAL_CHANGE
      when selected <  current then @operation.DOWNGRADE

  planInterval:
    MONTH       : 'month'
    YEAR        : 'year'

  planTitle:
    FREE         : 'free'
    HOBBYIST     : 'hobbyist'
    DEVELOPER    : 'developer'
    PROFESSIONAL : 'professional'

  provider:
    STRIPE : 'stripe'
    PAYPAL : 'paypal'
    KODING : 'koding'

  operation:
    UPGRADE         : 1
    INTERVAL_CHANGE : 0
    DOWNGRADE       : -1

  FAILED_ATTEMPT_LIMIT: 3
  TOO_MANY_ATTEMPT_BLOCK_KEY: 'BlockForTooManyAttempts'
  TOO_MANY_ATTEMPT_BLOCK_DURATION: globals.config.paymentBlockDuration

  error:
    ERR_USER_NOT_CONFIRMED: 'You need to confirm your email to purchase a Koding subscription.'

  events:
    WORKFLOW_STARTED: 'WorkflowStarted'
    WORKFLOW_COULD_NOT_START: 'WorkflowCouldNotStart'

Change camel case event names.

Change camel case event names.


"*":
  "exception-reporting":
    userId: "30e6f2d0-42d3-ab77-4984-dde4c431f019"
  welcome:
    showOnStartup: false
  core: {}
  editor:
    invisibles: {}
    fontFamily: "Hack"
  autosave:
    enabled: true
  "git-diff":
    showIconsInEditorGutter: true
  "ruby-test":
    testFramework: "minitest"
    rspecAllCommand: "vagrant ssh -c \"rspec --tty spec\""
    rspecFileCommand: "vagrant ssh -c \"rspec --tty {relative_path}\""
    rspecSingleCommand: "vagrant ssh -c \"rspec --tty {relative_path}:{line_number}\""
  "git-blame": {}

"*":
  "exception-reporting":
    userId: "30e6f2d0-42d3-ab77-4984-dde4c431f019"
  welcome:
    showOnStartup: false
  core:
    projectHome: "/Users/randy/src"
    audioBeep: false
  editor:
    invisibles: {}
    fontFamily: "Hack"
    preferredLineLength: 100
    showIndentGuide: true
  autosave:
    enabled: true
  "git-diff":
    showIconsInEditorGutter: true
  "ruby-test":
    testFramework: "minitest"
    rspecAllCommand: "vagrant ssh -c \"rspec --tty spec\""
    rspecFileCommand: "vagrant ssh -c \"rspec --tty {relative_path}\""
    rspecSingleCommand: "vagrant ssh -c \"rspec --tty {relative_path}:{line_number}\""
  "git-blame": {}

Tweak a few Atom settings

Tweak a few Atom settings


React = require 'react'
ReactDOM = {render} = require 'react-dom'
{Router, Route, Link} = require 'react-router'
createBrowserHistory = require 'history/lib/createBrowserHistory'
routes = require './router'

routes = require './router'
history = createBrowserHistory()

if process.env.NON_ROOT isnt 'true' and window.location? and window.location.hash isnt ""
  window.location.pathname = window.location.hash.slice(1)

history.listen (location) ->
  window.dispatchEvent new CustomEvent 'locationchange'

location = if process.env.NON_ROOT == "true"
    null
  else
    Router.HistoryLocation

render <Router history={history}>{routes}</Router>,
  document.getElementById('panoptes-main-container')

logDeployedCommit = require './lib/log-deployed-commit'
logDeployedCommit()

React = require 'react'
ReactDOM = {render} = require 'react-dom'
{Router, Route, Link} = require 'react-router'
{useBasename} = require 'history'
createBrowserHistory = require 'history/lib/createBrowserHistory'
routes = require './router'

routes = require './router'

basename = if process.env.DEPLOY_SUBDIR? then "/panoptes-front-end/#{process.env.DEPLOY_SUBDIR}/" else ''

history = useBasename(createBrowserHistory)({basename})

if process.env.NON_ROOT isnt 'true' and window.location? and window.location.hash isnt ""
  window.location.pathname = window.location.hash.slice(1)

history.listen (location) ->
  window.dispatchEvent new CustomEvent 'locationchange'

location = if process.env.NON_ROOT == "true"
    null
  else
    Router.HistoryLocation

render <Router history={history}>{routes}</Router>,
  document.getElementById('panoptes-main-container')

logDeployedCommit = require './lib/log-deployed-commit'
logDeployedCommit()

Add basename to history for subdirectory deploys


{$$} = require 'space-pen'
SelectList = require 'select-list'
$ = require 'jquery'
_ = require 'underscore'

module.exports =
class CommandPaletteView extends SelectList
  @activate: (rootView) ->
    @instance = new CommandPaletteView(rootView)

  @viewClass: ->
    "#{super} command-palette"

  filterKey: 'eventDescription'

  previouslyFocusedElement: null
  keyBindings: null

  initialize: (@rootView) ->
    @command 'command-palette:toggle', =>
      @cancel()
      false
    super

  attach: ->
    super

    @keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement))

    events = []
    for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events())
      events.push({eventName, eventDescription}) if eventDescription

    events = _.sortBy events, (e) -> e.eventDescription

    @setArray(events)
    @appendTo(@rootView)
    @miniEditor.setText('')
    @miniEditor.focus()

  itemForElement: ({eventName, eventDescription}) ->
    keyBindings = @keyBindings
    $$ ->
      @li class: 'event', 'data-event-name': eventName, =>
        @div eventDescription, class: 'event-description'
        @div class: 'right', =>
          @div eventName, class: 'event-name'
          for binding in keyBindings[eventName] ? []
            @div binding, class: 'key-binding'
        @div class: 'clear-float'

  confirmed: ({eventName}) ->
    @cancel()
    @previouslyFocusedElement.trigger(eventName)

  cancelled: ->

{$$} = require 'space-pen'
SelectList = require 'select-list'
$ = require 'jquery'
_ = require 'underscore'

module.exports =
class CommandPaletteView extends SelectList
  @activate: (rootView) ->
    @instance = new CommandPaletteView(rootView)

  @viewClass: ->
    "#{super} command-palette"

  filterKey: 'eventDescription'

  previouslyFocusedElement: null
  keyBindings: null

  initialize: (@rootView) ->
    @command 'command-palette:toggle', =>
      @cancel()
      false
    super

  attach: ->
    super

    @keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement))

    events = []
    for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events())
      events.push({eventName, eventDescription}) if eventDescription

    events = _.sortBy events, (e) -> e.eventDescription

    @setArray(events)
    @appendTo(@rootView)
    @miniEditor.focus()

  itemForElement: ({eventName, eventDescription}) ->
    keyBindings = @keyBindings
    $$ ->
      @li class: 'event', 'data-event-name': eventName, =>
        @div eventDescription, class: 'event-description'
        @div class: 'right', =>
          @div eventName, class: 'event-name'
          for binding in keyBindings[eventName] ? []
            @div binding, class: 'key-binding'
        @div class: 'clear-float'

  confirmed: ({eventName}) ->
    @cancel()
    @previouslyFocusedElement.trigger(eventName)

Clear mini editor base select list cancelled()

Clearing the mini editor when closing is something
all sub-classes were already doing so it makes sense
to pull it up to the base class as the default
cancelled() implementation that can still be overridden
if needed.