$(document).on "page:change", ->
  $(".data-table").each ->
    table = $(@)

    return if $.fn.dataTable.isDataTable(table)

    options =
      responsive: true
      order: [[0, "desc"]]

    ascColumn = table.find("th.sort-asc").index()
    descColumn = table.find("th.sort-desc").index()

    if (ascColumn >= 0)
      options["order"] = [[ ascColumn, "asc" ]]

    if (descColumn >= 0)
      options["order"] = [[ descColumn, "desc" ]]

    if table.hasClass("no-paging")
      options["paging"] = false

    table.dataTable(options)

$(document).on "page:change", ->
  $(".data-table").each ->
    table = $(@)

    return if $.fn.dataTable.isDataTable(table)

    options =
      responsive: true
      order: [[0, "desc"]]
      pageLength: 25

    ascColumn = table.find("th.sort-asc").index()
    descColumn = table.find("th.sort-desc").index()

    if (ascColumn >= 0)
      options["order"] = [[ ascColumn, "asc" ]]

    if (descColumn >= 0)
      options["order"] = [[ descColumn, "desc" ]]

    if table.hasClass("no-paging")
      options["paging"] = false

    table.dataTable(options)

Add default page legth to 25 for datatable for readability


describe "RequireJS", ->
  beforeEach ->
    @addMatchers requirejsTobeUndefined: ->
      typeof requirejs is "undefined"

  it "check that the RequireJS object is present in the global namespace", ->
    expect(RequireJS).toEqual jasmine.any(Object)
    expect(window.RequireJS).toEqual jasmine.any(Object)

  it "check that requirejs(), require(), and define() are not in the global namespace", ->
    expect({}).requirejsTobeUndefined()

    # expect(require).not.toBeDefined();
    # expect(define).not.toBeDefined();
    expect(window.requirejs).not.toBeDefined()
    expect(window.require).not.toBeDefined()
    expect(window.define).not.toBeDefined()

describe "RequireJS", ->
  beforeEach ->
    @addMatchers
      requirejsTobeUndefined: ->
        typeof requirejs is "undefined"

      requireTobeUndefined: ->
        typeof require is "undefined"

      defineTobeUndefined: ->
        typeof define is "undefined"

  it "check that the RequireJS object is present in the global namespace", ->
    expect(RequireJS).toEqual jasmine.any(Object)
    expect(window.RequireJS).toEqual jasmine.any(Object)

  it "check that requirejs(), require(), and define() are not in the global namespace", ->
    expect({}).requirejsTobeUndefined()
    expect({}).requireTobeUndefined()
    expect({}).defineTobeUndefined()
    expect(window.requirejs).not.toBeDefined()
    expect(window.require).not.toBeDefined()
    expect(window.define).not.toBeDefined()

Work on RequireJS Jasmine test.

Work on RequireJS Jasmine test.


do ->

	mapOptions =
		center: new (google.maps.LatLng)(43.8321591, 4.3428536)
		mapTypeId: google.maps.MapTypeId.ROADMAP
		streetViewControl: false
		scrollwheel: false
		navigationControl: false
		mapTypeControl: false
		scaleControl: false
		draggable: false
		zoomControlOptions: style: google.maps.ZoomControlStyle.SMALL
		zoom: 9

	map = new (google.maps.Map)(document.getElementById('map'), mapOptions)

	Caman.remoteProxy = "proxy";
	Caman.DEBUG = true
	Caman "#uploaded-marker", () ->
		@brightness(5).render()

do ->

	mapOptions =
		center: new (google.maps.LatLng)(43.8321591, 4.3428536)
		mapTypeId: google.maps.MapTypeId.ROADMAP
		streetViewControl: false
		scrollwheel: false
		navigationControl: false
		mapTypeControl: false
		scaleControl: false
		draggable: false
		zoomControlOptions: style: google.maps.ZoomControlStyle.SMALL
		zoom: 9

	map = new (google.maps.Map)(document.getElementById('map'), mapOptions)

	marker = new (google.maps.Marker)(
		position: map.getCenter()
		map: map
		draggable:true
		animation: google.maps.Animation.DROP
		icon:
			url: window.originalImage
	)

	Caman.remoteProxy = "proxy";
	Caman.DEBUG = true
	Caman "#uploaded-marker", () ->
		@brightness(5).render()

Add uploaded marker to map

Add uploaded marker to map


angular.module('fileManager').
factory('Selection', ()->
  return class Selection
    @_files: {}
    @number: 0

    @add: (file)->
      if not @hasFile(file)
        @_files[file._id] = file
        @number++

    @remove: (file)->
      if @hasFile(file)
        delete @_files[file._id]
        @number--

    @clear: ->
      @_files  = {}
      @number = 0

    @hasFile: (file)->
      if typeof file == 'object'
        id = file._id
      else
        id = file
      return @_files.hasOwnProperty(id)

    @select: (file, ctrl = false, contextMenu = false) ->
      if contextMenu and @hasFile(file)
        return true
      @clear() if not ctrl
      if not @hasFile(file)
        @add(file)
      else
        @remove(file)

    @isEmpty: ->
      return @number == 0

    @isSingle: ->
      return @number == 1

    @isMultiple: ->
      return @number > 1

    @forEach: (callback)->
      for id, file of @_files
        callback(file)

    @getSize: ->
      total = 0
      for id, file of @_files
        total += file.metadata.size ? 0
      return total

    @getFirst: ->
      for i, file of @_files
        return file

    @hasAtLeastOneFolder: ->
      for i, file of @_files
        if file.isFolder()
          return true
      return false
)

angular.module('fileManager').
factory('Selection', ($rootScope)->
  class Selection
    @_files: {}
    @number: 0

    @add: (file)->
      if not @hasFile(file)
        @_files[file._id] = file
        @number++

    @remove: (file)->
      if @hasFile(file)
        delete @_files[file._id]
        @number--

    @clear: ->
      @_files  = {}
      @number = 0

    @hasFile: (file)->
      if typeof file == 'object'
        id = file._id
      else
        id = file
      return @_files.hasOwnProperty(id)

    @select: (file, ctrl = false, contextMenu = false) ->
      if contextMenu and @hasFile(file)
        return true
      @clear() if not ctrl
      if not @hasFile(file)
        @add(file)
      else
        @remove(file)

    @isEmpty: ->
      return @number == 0

    @isSingle: ->
      return @number == 1

    @isMultiple: ->
      return @number > 1

    @forEach: (callback)->
      for id, file of @_files
        callback(file)

    @getSize: ->
      total = 0
      for id, file of @_files
        total += file.metadata.size ? 0
      return total

    @getFirst: ->
      for i, file of @_files
        return file

    @hasAtLeastOneFolder: ->
      for i, file of @_files
        if file.isFolder()
          return true
      return false

  $rootScope.$on('$stateChangeSuccess', ->
    Selection.clear()
  )
  return Selection
)

Clear selection every time you change of folder.


path = require 'path'
KeybindingPanel = require '../lib/keybinding-panel'

describe "KeybindingPanel", ->
  panel = null

  describe "loads and displays core key bindings", ->
    beforeEach ->
      expect(atom.keymap).toBeDefined()
      spyOn(atom.keymap, 'getKeyBindings').andReturn [
        source: "#{atom.getLoadSettings().resourcePath}#{path.sep}keymaps", keystroke: 'ctrl-a', command: 'core:select-all', selector: '.editor'
      ]
      panel = new KeybindingPanel

    it "shows exactly one row", ->
      expect(panel.keybindingRows.children().length).toBe 1

      row = panel.keybindingRows.find(':first')
      expect(row.find('.keystroke').text()).toBe 'ctrl-a'
      expect(row.find('.command').text()).toBe 'core:select-all'
      expect(row.find('.source').text()).toBe 'Core'
      expect(row.find('.selector').text()).toBe '.editor'

path = require 'path'
KeybindingPanel = require '../lib/keybinding-panel'

describe "KeybindingPanel", ->
  panel = null

  beforeEach ->
    expect(atom.keymap).toBeDefined()
    spyOn(atom.keymap, 'getKeyBindings').andReturn [
      source: "#{atom.getLoadSettings().resourcePath}#{path.sep}keymaps", keystroke: 'ctrl-a', command: 'core:select-all', selector: '.editor'
    ]
    panel = new KeybindingPanel

  it "loads and displays core key bindings", ->
    expect(panel.keybindingRows.children().length).toBe 1

    row = panel.keybindingRows.find(':first')
    expect(row.find('.keystroke').text()).toBe 'ctrl-a'
    expect(row.find('.command').text()).toBe 'core:select-all'
    expect(row.find('.source').text()).toBe 'Core'
    expect(row.find('.selector').text()).toBe '.editor'

  describe "when a keybinding is copied", ->
    describe "when the keybinding file ends in .cson", ->
      it "writes a CSON snippet to the clipboard", ->
        spyOn(atom.keymap, 'getUserKeymapPath').andReturn 'keymap.cson'
        panel.find('.copy-icon').click()
        expect(atom.pasteboard.read()[0]).toBe """
          '.editor':
            'ctrl-a': 'core:select-all'
        """

    describe "when the keybinding file ends in .json", ->
      it "writes a JSON snippet to the clipboard", ->
        spyOn(atom.keymap, 'getUserKeymapPath').andReturn 'keymap.json'
        panel.find('.copy-icon').click()
        expect(atom.pasteboard.read()[0]).toBe """
          ".editor": {
            "ctrl-a": "core:select-all"
          }
        """

Add spec for copying keybinding

Add spec for copying keybinding


jQuery(document).ready ->
  class photographyGame
    constructor: (@debug, @map) ->

    init: () ->
  return

jQuery(document).ready ->
  class photographyGame
    constructor: (@debug, @map) ->

    init: () ->

  class location
    constructor: (@position, @name, @icon) ->
      @marker

    addTo: (map) ->
      if @icon
        marker = new google.maps.Marker({
          position: @position,
          map: map,
          icon: @icon,
          title: @name
        })
      else
        marker = new google.maps.Marker({
          position: @position,
          map: map,
          title: @name
        })
      @marker = marker
      @setListener(@marker)

    setListener: (marker) ->
      self = this
      marker.addListener 'click', ->
        mark.moveTo(self)

  class player extends location
    constructor: (@position, @name, @icon) ->
      super(@position, @name, @icon)
      @playerMarker

    initTo: (map) ->
      @playerMarker = new google.maps.Marker({
        position: @position,
        map: map,
        icon: @icon,
        title: 'Mark'
      })

    moveTo: (location) ->
      console.log("current position", this.position, "new position", location.position, "distance travelled", distanceTravelled(this.position, location.position) + 'km')
      @position = location.position
      @playerMarker.setPosition(new google.maps.LatLng(location.position.lat, location.position.lng))

Add location and player classes

Add location and player classes


_ = require 'underscore-plus'
{View} = require 'atom'

# Menu item view for an installed package
module.exports =
class PackageMenuView extends View
  @content: ->
    @li =>
      @a outlet: 'link', class: 'icon', =>
        @span outlet: 'nameLabel'
        @span outlet: 'packageAuthorLabel', class: 'package-author'

  initialize: (@pack, @packageManager) ->
    @attr('name', @pack.name)
    @attr('type', 'package')
    @nameLabel.text(@packageManager.getPackageTitle(@pack))
    @packageAuthorLabel.text(@packageManager.getAuthorUserName(@pack))
    @checkForUpdates()
    @subscribe @packageManager, 'package-updated theme-updated', ({name}) =>
      @link.removeClass('icon-squirrel') if @pack.name is name

  checkForUpdates: ->
    return if atom.packages.isBundledPackage(@pack.name)

    @getAvailablePackage (availablePackage) =>
      if @packageManager.canUpgrade(@pack, availablePackage)
        @link.addClass('icon-squirrel')

  getAvailablePackage: (callback) ->
    @packageManager.getOutdated().then (packages) =>
      for pack in packages when pack.name is @pack.name
        callback(pack)

_ = require 'underscore-plus'
{View} = require 'atom'

# Menu item view for an installed package
module.exports =
class PackageMenuView extends View
  @content: ->
    @li =>
      @a outlet: 'link', class: 'icon', =>
        @span outlet: 'nameLabel'
        @span outlet: 'packageAuthorLabel', class: 'package-author'

  initialize: (@pack, @packageManager) ->
    @attr('name', @pack.name)
    @attr('type', 'package')
    @nameLabel.text(@packageManager.getPackageTitle(@pack))
    @packageAuthorLabel.text(@packageManager.getAuthorUserName(@pack))
    @checkForUpdates()
    @subscribe @packageManager, 'package-updated theme-updated', ({name}) =>
      @link.removeClass('icon-squirrel') if @pack.name is name

  checkForUpdates: ->
    return if atom.packages.isBundledPackage(@pack.name)

    @getAvailablePackage (availablePackage) =>
      if @packageManager.canUpgrade(@pack, availablePackage.latestVersion)
        @link.addClass('icon-squirrel')

  getAvailablePackage: (callback) ->
    @packageManager.getOutdated().then (packages) =>
      for pack in packages when pack.name is @pack.name
        callback(pack)

Check if package can be upgraded using the latest version


require './setup'

Song = null
Album = null
spy = null

describe 'has one change', ->
  beforeEach ->
    Song = Ento()
      .use(Ento.relations)
      .attr('id')
      .attr('title')

    Album = Ento()
      .use(Ento.relations)
      .attr('id')
      .hasOne('song', Song, as: 'album')

  describe 'propagate change event of children', ->
    beforeEach ->
      spy = sinon.spy()

    it 'one level, change:attr', ->
      parent = new Album()
      parent.song = new Song(title: 'Wrecking Ball')
      parent.on('change:song', spy)
      parent.song.title = 'Party in the USA'
      expect(spy).calledOnce

    it 'one level, change', ->
      parent = new Album()
      parent.song = new Song(title: 'Wrecking Ball')
      parent.on('change', spy)
      parent.song.title = 'Party in the USA'
      expect(spy).calledOnce
      expect(spy.firstCall.args).be.like ['title']

require './setup'

Song = null
Album = null
spy = null

describe 'has one change', ->
  beforeEach ->
    Song = Ento()
      .use(Ento.relations)
      .attr('id')
      .attr('title')

    Album = Ento()
      .use(Ento.relations)
      .attr('id')
      .hasOne('song', Song, as: 'album')

  describe 'propagate change event of children', ->
    beforeEach ->
      spy = sinon.spy()

    it 'one level, change:attr', ->
      parent = new Album()
      parent.song = new Song(title: 'Wrecking Ball')
      parent.on('change:song', spy)
      parent.song.title = 'Party in the USA'
      expect(spy).calledOnce

    it 'one level, change', ->
      parent = new Album()
      parent.song = new Song(title: 'Wrecking Ball')
      parent.on('change', spy)
      parent.song.title = 'Party in the USA'
      expect(spy).calledOnce
      expect(spy.firstCall.args).be.like [['song']]

Fix test related to relations.

Fix test related to relations.


module.exports = class Organization
  constructor: (org, @api) ->
    @orgName = if typeof org is "object" then org.name else org

  node: (path, cb) ->
    @api.get @apiPath(path), {}, cb

  apiPath: (path) ->
    path = path.path || path.name if typeof path is "object"
    "/#{encodeURIComponent(@orgName)}/#{path}"

module.exports = class Organization
  constructor: (org, @api) ->
    @orgName = if typeof org is "object" then org.name else org

  node: (path..., cb) ->
    @api.get @apiPath(path), {}, cb

  apiPath: (path) ->
    compiledPath = []
    for p in path
      p = p.path || p.name if typeof p is "object"
      compiledPath.push p

    "/#{encodeURIComponent(@orgName)}/#{compiledPath.join('/')}"

Change semantics of node() a little to allow for string path or multiple arguments


winston = require 'winston'
util = require 'util'

winston
	.remove winston.transports.Console
	.add winston.transports.File,
		level: 'silly'
		filename: 'output.log'
		json: no

exports.log = (level, params...) ->
	winston.log level, (params.map util.inspect)...

winston = require 'winston'
util = require 'util'

winston
	.remove winston.transports.Console
	.add winston.transports.File,
		level: 'silly'
		filename: 'output.log'
		json: no

exports.log = (level, params...) ->
	if params[0] instanceof Error
		winston.log level, params[0], params[1..]...

	else winston.log level, (params.map util.inspect)...

Tweak to Winston output handler

Tweak to Winston output handler


Base = require 'base'

class ListItem extends Base.View

  template: require '../../templates/list'

  elements:
    '.name':  'name'
    '.count': 'count'

  events:
    'click': 'click'

  constructor: ->
    Base.touchify(@events)
    super

    return unless @list?

    @listen [
      @list,
        'select': @select
        'change': @updateName
        'before:destroy': @remove
      @list.tasks,
        'change': @updateCount
    ]

  # Create the list element
  render: =>

    @el = $ @template @list
    @bind()

    el = @el[0]
    el.list = @list
    mouse.addDrop(el)

    # TODO: Setup droppable
    # @el.droppable
    #   hoverClass: 'ui-state-active'
    #   tolerance: 'pointer'
    #   drop: (event, ui) =>
    #     movedTask = Task.get(ui.draggable.attr('id').slice(5))
    #     List.current.moveTask(movedTask, @list)

    return this

  updateCount: =>
    @count.text @list.tasks.length

  updateName: =>
    @name.text @list.name

  click: =>
    @list.trigger 'select'

  select: =>
    @el.addClass 'current'

  remove: =>
    @unbind()
    @el.remove()

module.exports = ListItem

Base = require 'base'

class ListItem extends Base.View

  template: require '../../templates/list'

  elements:
    '.name':  'name'
    '.count': 'count'

  events:
    'mousedown': 'click'

  constructor: ->
    Base.touchify(@events)
    super

    return unless @list?

    @listen [
      @list,
        'select': @select
        'change': @updateName
        'before:destroy': @remove
      @list.tasks,
        'change': @updateCount
    ]

  # Create the list element
  render: =>

    @el = $ @template @list
    @bind()

    el = @el[0]
    el.list = @list
    mouse.addDrop(el)

    # TODO: Setup droppable
    # @el.droppable
    #   hoverClass: 'ui-state-active'
    #   tolerance: 'pointer'
    #   drop: (event, ui) =>
    #     movedTask = Task.get(ui.draggable.attr('id').slice(5))
    #     List.current.moveTask(movedTask, @list)

    return this

  updateCount: =>
    @count.text @list.tasks.length

  updateName: =>
    @name.text @list.name

  click: =>
    @list.trigger 'select'

  select: =>
    @el.addClass 'current'

  remove: =>
    @unbind()
    @el.remove()

module.exports = ListItem

Use mousedown instead of click

Use mousedown instead of click


React = require 'react'
BS = require 'react-bootstrap'
_ = require 'underscore'

{History, Link} = require 'react-router'
{TransitionActions, TransitionStore} = require '../../flux/transition'

BackButton = React.createClass
  displayName: 'BackButton'

  propTypes:
    fallbackLink: React.PropTypes.shape(
      to: React.PropTypes.string
      params: React.PropTypes.object
      text: React.PropTypes.string
    ).isRequired

  contextTypes:
    router: React.PropTypes.func

  render: ->
    # Gets route to last path that was not the same as the current one
    # See TransitionStore for more detail.
    historyInfo = TransitionStore.getPrevious(@context.router)
    {fallbackLink, className} = @props
    {text} = fallbackLink

    backText = if historyInfo.name then "Back to #{historyInfo.name}" else fallbackLink.text

    href =  historyInfo.path or @context.router.makeHref(
      @props.fallbackLink.to, @props.fallbackLink.params
    )

    <BS.Button href={href} className={className} {...@props}>
      {backText}
    </BS.Button>

module.exports = BackButton

React = require 'react'
BS = require 'react-bootstrap'
_ = require 'underscore'

{History, Link} = require 'react-router'
{TransitionActions, TransitionStore} = require '../../flux/transition'

BackButton = React.createClass
  displayName: 'BackButton'

  propTypes:
    bsStyle: React.PropTypes.string
    fallbackLink: React.PropTypes.shape(
      to: React.PropTypes.string
      params: React.PropTypes.object
      text: React.PropTypes.string
    ).isRequired

  getDefaultProps: ->
    bsStyle: 'default'

  contextTypes:
    router: React.PropTypes.func

  render: ->
    # Gets route to last path that was not the same as the current one
    # See TransitionStore for more detail.
    historyInfo = TransitionStore.getPrevious(@context.router)
    {fallbackLink, className} = @props
    {text} = fallbackLink

    backText = if historyInfo.name then "Back to #{historyInfo.name}" else fallbackLink.text

    href =  historyInfo.path or @context.router.makeHref(
      @props.fallbackLink.to, @props.fallbackLink.params
    )

    <Link className={"btn btn-#{@props.bsStyle}"} to={href}>
      {backText}
    </Link>

module.exports = BackButton

Use router Link to prevent full page reload


NestNode = require('./NestNode')

module.exports = class NestThermostatNode extends NestNode
  aspects:
    "temperature-sensor": {}
    "humidity-sensor": {}
    "temperature-set-point":
      commands:
        "set-target": (node, temp) -> node.adapter.setTemperature(node.id, temp)
      events:
        "target-changed": (prev, cur) -> prev.target != cur.target
        "mode-changed"  : (prev, cur) -> prev.mode != cur.mode

  processData: (data) ->
    @getAspect("temperature-sensor").setData
      value: data["current-temperature"]
    @getAspect("humidity-sensor").setData
      value: data["current-humidity"]
    @getAspect("temperature-set-point").setData
      target: data["target-temperature"]
      mode: data["target-type"]

NestNode = require('./NestNode')

module.exports = class NestThermostatNode extends NestNode
  aspects:
    "temperature-sensor":
      events:
        changed: (prev, cur) -> prev.value != cur.value
    "humidity-sensor":
      events:
        changed: (prev, cur) -> prev.value != cur.value
    "temperature-set-point":
      commands:
        "set-target": (node, temp) -> node.adapter.setTemperature(node.id, temp)
      events:
        "target-changed": (prev, cur) -> prev.target != cur.target
        "mode-changed"  : (prev, cur) -> prev.mode != cur.mode

  processData: (data) ->
    @getAspect("temperature-sensor").setData
      value: data["current-temperature"]
    @getAspect("humidity-sensor").setData
      value: data["current-humidity"]
    @getAspect("temperature-set-point").setData
      target: data["target-temperature"]
      mode: data["target-type"]

Support events on nest temp and humidity


fs = require 'fs'
path = require 'path'

module.exports = (grunt) ->
  grunt.registerTask 'generate-license', 'Generate the license, including the licenses of all dependencies', (mode) ->
    legalEagle = require 'legal-eagle'
    done = @async()

    options =
      path: process.cwd()
      overrides: require './license-overrides'

    legalEagle options, (err, dependencyLicenses) ->
      if err?
        console.error(err)
        exit 1

      licenseText = getLicenseText(dependencyLicenses)
      if mode is 'save'
        targetPath = path.join(grunt.config.get('atom.appDir'), 'LICENSE')
        fs.writeFileSync(targetPath, licenseText)
      else
        console.log licenseText
      done()

getLicenseText = (dependencyLicenses) ->
  {keys} = require 'underscore-plus'
  text = """
    Copyright 2014 GitHub, Inc.

    This application bundles the following third-party packages in accordance
    with the following licenses:\n\n
  """
  names = keys(dependencyLicenses).sort()
  for name in names
    {license, source, sourceText} = dependencyLicenses[name]

    text += "-------------------------------------------------------------------------\n\n"
    text += "Package: #{name}\n"
    text += "License: #{license}\n"
    text += "License Source: #{source}\n" if source?
    if sourceText?
      text += "Source Text:\n\n"
      text += sourceText
    text += '\n'
  text

fs = require 'fs'
path = require 'path'

module.exports = (grunt) ->
  grunt.registerTask 'generate-license', 'Generate the license, including the licenses of all dependencies', (mode) ->
    legalEagle = require 'legal-eagle'
    done = @async()

    options =
      path: process.cwd()
      overrides: require './license-overrides'

    legalEagle options, (err, dependencyLicenses) ->
      if err?
        console.error(err)
        exit 1

      licenseText = getLicenseText(dependencyLicenses)
      if mode is 'save'
        targetPath = path.join(grunt.config.get('atom.appDir'), 'LICENSE.md')
        fs.writeFileSync(targetPath, licenseText)
      else
        console.log licenseText
      done()

getLicenseText = (dependencyLicenses) ->
  {keys} = require 'underscore-plus'
  text = """
    Copyright 2014 GitHub, Inc.

    This application bundles the following third-party packages in accordance
    with the following licenses:\n\n
  """
  names = keys(dependencyLicenses).sort()
  for name in names
    {license, source, sourceText} = dependencyLicenses[name]

    text += "-------------------------------------------------------------------------\n\n"
    text += "Package: #{name}\n"
    text += "License: #{license}\n"
    text += "License Source: #{source}\n" if source?
    if sourceText?
      text += "Source Text:\n\n"
      text += sourceText
    text += '\n'
  text

Add .md extension to generated license

Add .md extension to generated license


tryRequire = (dep) ->
  try
    require dep
  catch
    undefined

@window ||= {}

Q = @window.Q
_ = @window._

Q ||= tryRequire 'q'
_ ||= tryRequire 'lodash/dist/lodash.underscore'
_ ||= tryRequire 'underscore'

utils = require('./yayson/utils')(_, Q)

Adapter = require('./yayson/adapter')
adapters = require('./yayson/adapters')
presenterFactory = require('./yayson/presenter')

lookupAdapter = (nameOrAdapter) ->
  adapters[nameOrAdapter] || Adapter

presenter = (options = {}) ->
  adapter = lookupAdapter options.adapter
  presenterFactory(utils, adapter)

module.exports = ({adapter} = {}) ->
  Store: require('./yayson/store')(utils)
  Presenter: presenter({adapter})
  Adapter: Adapter

@window ||= {}

Q = @window.Q
_ = @window._

Q ||= (try require? 'q')
_ ||= (try require? 'lodash/dist/lodash.underscore')
_ ||= (try require? 'underscore')

utils = require('./yayson/utils')(_, Q)

Adapter = require('./yayson/adapter')
adapters = require('./yayson/adapters')
presenterFactory = require('./yayson/presenter')

lookupAdapter = (nameOrAdapter) ->
  adapters[nameOrAdapter] || Adapter

presenter = (options = {}) ->
  adapter = lookupAdapter options.adapter
  presenterFactory(utils, adapter)

module.exports = ({adapter} = {}) ->
  Store: require('./yayson/store')(utils)
  Presenter: presenter({adapter})
  Adapter: Adapter

Change optional require format to make webpack happier


#= require trix/views/attachment_view
#= require trix/models/image_attachment

{defer, makeElement, measureElement} = Trix

class Trix.ImageAttachmentView extends Trix.AttachmentView
  getPreloadOperation: ->
    if @attachment.preloadOperation?.hasSucceeded()
      @attachment.preloadOperation
    else if @attachment.previewPreloadOperation?
      @attachment.previewPreloadOperation
    else
      @attachment.preloadOperation

  createContentNodes: ->
    image = makeElement("img", src: "", "data-trix-mutable": true)
    @refresh(image)

    if operation = @attachment.preloadOperation
      operation.then =>
        @refresh(image)
        @refresh()

    [image]

  getClassName: ->
    [super, "image"].join(" ")

  refresh: (image) ->
    image ?= @findElement()?.querySelector("img")
    @updateAttributesForImage(image) if image

  updateAttributesForImage: (image) ->
    attachmentURL = @attachment.getURL()
    operation = @getPreloadOperation()
    image.src = url = operation.url

    if url is attachmentURL
      image.removeAttribute("data-trix-serialized-attributes")
    else
      serializedAttributes = JSON.stringify(src: attachmentURL)
      image.setAttribute("data-trix-serialized-attributes", serializedAttributes)

    width = @attachmentPiece.getWidth() ? @attachment.getWidth()
    height = @attachmentPiece.getHeight() ? @attachment.getHeight()

    image.width = width if width?
    image.height = height if height?

#= require trix/views/attachment_view
#= require trix/models/image_attachment

{defer, makeElement, measureElement} = Trix

class Trix.ImageAttachmentView extends Trix.AttachmentView
  getPreloadOperation: ->
    if @attachment.preloadOperation?.hasSucceeded()
      @attachment.preloadOperation
    else if @attachment.previewPreloadOperation?
      @attachment.previewPreloadOperation
    else
      @attachment.preloadOperation

  createContentNodes: ->
    image = makeElement("img", src: "", "data-trix-mutable": true)
    caption = makeElement(tagName: "figcaption", textContent: @attachment.getFilename())
    @refresh(image)

    if operation = @attachment.preloadOperation
      operation.then =>
        @refresh(image)
        @refresh()

    if filesize = @attachment.getFormattedFilesize()
      span = makeElement(tagName: "span", className: "size", textContent: filesize)
      caption.appendChild(span)

    [image, caption]

  getClassName: ->
    [super, "image"].join(" ")

  refresh: (image) ->
    image ?= @findElement()?.querySelector("img")
    @updateAttributesForImage(image) if image

  updateAttributesForImage: (image) ->
    attachmentURL = @attachment.getURL()
    operation = @getPreloadOperation()
    image.src = url = operation.url

    if url is attachmentURL
      image.removeAttribute("data-trix-serialized-attributes")
    else
      serializedAttributes = JSON.stringify(src: attachmentURL)
      image.setAttribute("data-trix-serialized-attributes", serializedAttributes)

    width = @attachmentPiece.getWidth() ? @attachment.getWidth()
    height = @attachmentPiece.getHeight() ? @attachment.getHeight()

    image.width = width if width?
    image.height = height if height?

Add figcaptions to image attachments

Add figcaptions to image attachments


#global $, _
((NS) ->
  "use strict"

  # Filename: helpers/error_helper.js */
  NS = NS or {}
  isInBrowser = typeof module is 'undefined' and typeof window isnt 'undefined'
  # Exception class
  ###
   * Creates a new CustomException.
   * @class Exception class.
  ###
  class CustomException
    # @constructor
    constructor:(@name, @message,@options) ->
      @log()
    #Log the content of the exception.
    log: ->
      console.error("name", @name, "message", @message, "options", @options)
    # JSONify the content of the exception.
    toJSON:->
      return {"name": @name, "message": @message,  "options": @options}
  # Exception for a not implemented method.
  class NotImplementedException extends CustomException
    constructor:(message, options) ->
      super("NotImplementedException", message, options)
  # Exception class for an argument null exeption.
  class ArgumentNullException extends CustomException
    constructor:(message) ->
      super("ArgumentNull", message)
  # Exception for a invalid argument exeption
  class ArgumentInvalidException extends CustomException
    constructor:(message, options) ->
      super("ArgumentInvalidException", message, options)
  class DependencyException extends CustomException
    constructor:(message, options) ->
      super("DependencyException", message, options)
  mod = {
    CustomException: CustomException
    NotImplementedException: NotImplementedException
    ArgumentNullException: ArgumentNullException
    ArgumentInvalidException: ArgumentInvalidException
    DependencyException: DependencyException
  }
  if isInBrowser
    NS.Helpers = NS.Helpers or {}
    NS.Helpers.Exceptions = mod
  else
    module.exports = mod
)(if typeof module is 'undefined' and typeof window isnt 'undefined' then window.Fmk else module.exports)

#global $, _
  "use strict"
  # Filename: helpers/error_helper.js */
  # Exception class
  ###
   * Creates a new CustomException.
   * @class Exception class.
  ###
  class CustomException
    # @constructor
    constructor:(@name, @message,@options) ->
      @log()
    #Log the content of the exception.
    log: ->
      console.error("name", @name, "message", @message, "options", @options)
    # JSONify the content of the exception.
    toJSON:->
      return {"name": @name, "message": @message,  "options": @options}
  # Exception for a not implemented method.
  class NotImplementedException extends CustomException
    constructor:(message, options) ->
      super("NotImplementedException", message, options)
  # Exception class for an argument null exeption.
  class ArgumentNullException extends CustomException
    constructor:(message) ->
      super("ArgumentNull", message)
  # Exception for a invalid argument exeption
  class ArgumentInvalidException extends CustomException
    constructor:(message, options) ->
      super("ArgumentInvalidException", message, options)
  class DependencyException extends CustomException
    constructor:(message, options) ->
      super("DependencyException", message, options)
  mod = {
    CustomException: CustomException
    NotImplementedException: NotImplementedException
    ArgumentNullException: ArgumentNullException
    ArgumentInvalidException: ArgumentInvalidException
    DependencyException: DependencyException
  }
  module.exports = mod

Clean the custom exception module.

Clean the custom exception module.


###
A text region that can be clicked to edit its contents.
###

class window.EditableText extends Editable

  inherited:
    editClass: "TextBox"

  # True if the pressing Escape in edit mode cancels edit mode.
  # The default is true.
  cancelOnEscape: Control.property( null, true )

  editing: ( editing ) ->
    result = super editing
    # Switching to edit mode; put focus in the text box.
    @editControl().find( "input" ).andSelf().focus()  if editing
    result

  # True if the control should switch to editing mode when it's clicked.
  # Default is true.
  editOnClick: Control.property( null, true )

  initialize: ->
    @click =>
      @editing true if @editOnClick() and not @editing()

  # True if pressing the Enter key in edit mode saves changes and switches
  # back to read mode. The default is true.
  saveOnEnter: Control.property( null, true )

  _createEditControl: ->
    result = super()
    # Wire up events bound to input elements.
    @editControl().find( "input" ).andSelf().on
      blur: =>
        # Implicitly save when control loses focus.
        @save()  if @editing()
      keydown: ( event ) =>
        if @editing()
          switch event.which
            when 13 # Enter
              if @saveOnEnter()
                @save()
                event.preventDefault()
            when 27 # Escape
              @cancel()  if @cancelOnEscape()

    result

###
A text region that can be clicked to edit its contents.
###

class window.EditableText extends Editable

  inherited:
    editClass: "TextBox"

  # True if the pressing Escape in edit mode cancels edit mode.
  # The default is true.
  cancelOnEscape: Control.property( null, true )

  editing: ( editing ) ->
    result = super editing
    # Switching to edit mode; put focus in the text box.
    @editControl().find( "input" ).addBack().focus()  if editing
    result

  # True if the control should switch to editing mode when it's clicked.
  # Default is true.
  editOnClick: Control.property( null, true )

  initialize: ->
    @click =>
      @editing true if @editOnClick() and not @editing()

  # True if pressing the Enter key in edit mode saves changes and switches
  # back to read mode. The default is true.
  saveOnEnter: Control.property( null, true )

  _createEditControl: ->
    result = super()
    # Wire up events bound to input elements.
    @editControl().find( "input" ).addBack().on
      blur: =>
        # Implicitly save when control loses focus.
        @save()  if @editing()
      keydown: ( event ) =>
        if @editing()
          switch event.which
            when 13 # Enter
              if @saveOnEnter()
                @save()
                event.preventDefault()
            when 27 # Escape
              @cancel()  if @cancelOnEscape()

    result

Change $.andSelf() to $.addBack(), which is now preferred.


describe "RequireJS", ->
    it "check that the RequireJS object is present in the global namespace", ->
        expect(RequireJS).toEqual jasmine.any(Object)
        expect(window.RequireJS).toEqual jasmine.any(Object)

    it "check that requirejs(), require(), and define() are not in the global namespace", ->
        expect(requirejs).not.toBeDefined()
        expect(require).not.toBeDefined()
        expect(define).not.toBeDefined()
        expect(window.requirejs).not.toBeDefined()
        expect(window.require).not.toBeDefined()
        expect(window.define).not.toBeDefined()

describe "RequireJS", ->
  beforeEach ->
    @addMatchers requirejsTobeUndefined: ->
      typeof requirejs is "undefined"

  it "check that the RequireJS object is present in the global namespace", ->
    expect(RequireJS).toEqual jasmine.any(Object)
    expect(window.RequireJS).toEqual jasmine.any(Object)

  it "check that requirejs(), require(), and define() are not in the global namespace", ->
    expect({}).requirejsTobeUndefined()

    # expect(require).not.toBeDefined();
    # expect(define).not.toBeDefined();
    expect(window.requirejs).not.toBeDefined()
    expect(window.require).not.toBeDefined()
    expect(window.define).not.toBeDefined()

Work on RequireJS Jasmine test.

Work on RequireJS Jasmine test.


define (require) ->
  _ = require('underscore')
  Backbone = require('backbone')
  router = require('cs!router')
  BaseView = require('cs!helpers/backbone/views/base')
  #MailPopoverView = require('cs!./popovers/mail/mail')
  template = require('hbs!./title-template')
  require('less!./title')

  return class MediaTitleView extends BaseView
    template: template
    templateHelpers: () ->
      title = @model.get('title')

      # Set information used for social media links
      share =
        url: Backbone.history.fragment
        source: 'Connexions'
        summary: @model.get('abstract') or 'An OpenStax College book.'
        title: title or 'Untitled'
        image: @model.get('image') or "#{Backbone.history.location.host}/images/logo.png"

      # Encode all of the shared values for a URI
      _.each share, (value, key, list) ->
        list[key] = encodeURI(value)

      return {share: share, encodedTitle: encodeURI(title)}

    initialize: () ->
      super()
      @listenTo(@model, 'change:title', @render)
      @listenTo(router, 'navigate', @render)

    #onRender: () ->
    #  $share = @$el.find('.share')
    #  @attachPopover new MailPopoverView({owner: $share.find('.mail'), model: @model})

define (require) ->
  _ = require('underscore')
  Backbone = require('backbone')
  settings = require('cs!settings')
  router = require('cs!router')
  BaseView = require('cs!helpers/backbone/views/base')
  #MailPopoverView = require('cs!./popovers/mail/mail')
  template = require('hbs!./title-template')
  require('less!./title')

  return class MediaTitleView extends BaseView
    template: template
    templateHelpers: () ->
      title = @model.get('title')

      # Set information used for social media links
      share =
        url: location.origin + settings.root + Backbone.history.fragment
        source: 'Connexions'
        summary: @model.get('abstract') or 'An OpenStax College book.'
        title: title or 'Untitled'
        image: @model.get('image') or "#{Backbone.history.location.origin}/images/logo.png"

      # Encode all of the shared values for a URI
      _.each share, (value, key, list) ->
        list[key] = encodeURI(value)

      return {share: share, encodedTitle: encodeURI(title)}

    initialize: () ->
      super()
      @listenTo(@model, 'change:title', @render)
      @listenTo(router, 'navigate', @render)

    #onRender: () ->
    #  $share = @$el.find('.share')
    #  @attachPopover new MailPopoverView({owner: $share.find('.mail'), model: @model})

Include location.origin in URL for share links


ETahi.HeartbeatService = Em.Object.extend
  interval: 10 * 1000
  intervalId: null
  resource: null
  url: null

  init: ->
    resource = @get('resource')
    throw new Error("need to specify resource") unless resource
    @set('url', "#{resource.path()}/heartbeat")

  start: ->
    @heartbeat() # immediate heartbeat
    heartbeatWrapper = => @heartbeat()
    @set('intervalId', setInterval(heartbeatWrapper, @get('interval')))

  stop: ->
    iid = @get('intervalId')
    if iid
      clearInterval(iid)
      @set('iid', null)

  heartbeat: ->
    $.ajax
      url: @get('url')
      type: "PUT"
      headers:
        'Tahi-Heartbeat': true

ETahi.HeartbeatService = Em.Object.extend
  interval: 90 * 1000
  intervalId: null
  resource: null
  url: null

  init: ->
    resource = @get('resource')
    throw new Error("need to specify resource") unless resource
    @set('url', "#{resource.path()}/heartbeat")

  start: ->
    @heartbeat() # immediate heartbeat
    heartbeatWrapper = => @heartbeat()
    @set('intervalId', setInterval(heartbeatWrapper, @get('interval')))

  stop: ->
    iid = @get('intervalId')
    if iid
      clearInterval(iid)
      @set('iid', null)

  heartbeat: ->
    $.ajax
      url: @get('url')
      type: "PUT"
      headers:
        'Tahi-Heartbeat': true

Set heartbeat pulse to 90 seconds

Set heartbeat pulse to 90 seconds


class @Calendar
  options =
    month: "short"
    day: "numeric"
    year: "numeric"

  constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
    cal = new CalHeatMap()
    cal.init
      itemName: ["contribution"]
      data: timestamps
      start: new Date(starting_year, starting_month)
      domainLabelFormat: "%b"
      id: "cal-heatmap"
      domain: "month"
      subDomain: "day"
      range: 12
      tooltip: true
      label:
        position: "top"
      legend: [
        0
        10
        20
        30
      ]
      legendCellPadding: 3
      cellSize: $('.user-calendar').width() / 73
      onClick: (date, count) ->
        formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
        $.ajax
          url: calendar_activities_path
          data:
            date: formated_date
          cache: false
          dataType: "html"
          success: (data) ->
            $(".user-calendar-activities").html data

class @Calendar
  constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
    cal = new CalHeatMap()
    cal.init
      itemName: ["contribution"]
      data: timestamps
      start: new Date(starting_year, starting_month)
      domainLabelFormat: "%b"
      id: "cal-heatmap"
      domain: "month"
      subDomain: "day"
      range: 12
      tooltip: true
      label:
        position: "top"
      legend: [
        0
        10
        20
        30
      ]
      legendCellPadding: 3
      cellSize: $('.user-calendar').width() / 73
      onClick: (date, count) ->
        formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
        $.ajax
          url: calendar_activities_path
          data:
            date: formated_date
          cache: false
          dataType: "html"
          success: (data) ->
            $(".user-calendar-activities").html data

Remove unused "options" object from Calendar JS


class Skr.Components.CustomerFinder extends Lanes.React.Component

    propTypes:
        model:      Lanes.PropTypes.Model.isRequired
        commands:   React.PropTypes.object
        autoFocus:  React.PropTypes.bool
        name:       React.PropTypes.string
        selectField:   React.PropTypes.bool

    getDefaultProps: ->
        autoFocus: false, label: 'Customer Code', name: 'customer'

    dataObjects:
        query: ->
            new Lanes.Models.Query({
                syncOptions: @props.syncOptions
                src: Skr.Models.Customer, fields: [
                    {id:'id', visible: false}
                    { id: 'code', fixedWidth: 130 }, 'name', 'notes',
                    { id: 'open_balance', fixedWidth: 100, textAlign: 'right', format: (v) ->
                        if v then _.bigDecimal(v).toFixed(2) else '0.00'
                    }
                ]
            })

    render: ->
        props = _.clone(@props)

        if props.selectField
            <LC.SelectField sm=2 labelField="code" {...props} />
        else
            <LC.RecordFinder ref="finder" sm=3 autoFocus
                commands={@props.commands}
                query={@query}
                {...props} />

class Skr.Components.CustomerFinder extends Lanes.React.Component

    propTypes:
        model:      Lanes.PropTypes.Model.isRequired
        commands:   React.PropTypes.object
        autoFocus:  React.PropTypes.bool
        name:       React.PropTypes.string
        selectField:   React.PropTypes.bool

    getDefaultProps: ->
        autoFocus: false, label: 'Customer Code', name: 'customer'

    dataObjects:
        query: ->
            new Lanes.Models.Query({
                syncOptions: @props.syncOptions
                src: Skr.Models.Customer, fields: [
                    {id:'id', visible: false}
                    { id: 'code', fixedWidth: 130 }, 'name', 'notes',
                    { id: 'open_balance', fixedWidth: 100, textAlign: 'right', format: (v) ->
                        if v then _.bigDecimal(v).toFixed(2) else '0.00'
                    }
                ]
            })

    render: ->
        props = _.clone(@props)
        if @model.hasAttribute('customer_code')
            props.defaultLabel = @model.customer_code

        if props.selectField
            <LC.SelectField sm=2 labelField="code" {...props} />
        else
            <LC.RecordFinder ref="finder" sm=3 autoFocus
                commands={@props.commands}
                query={@query}
                {...props} />

Set a defaultLabel if it exists

Set a defaultLabel if it exists


class window.BoardView extends Backbone.View

    el: $('.board__tiles')

    initialize: ->
      @listenTo @collection, 'reset', @render
      @collection.view = @
      @collection.shuffle()

    render: =>
      els = []
      @$el.html('')
      @collection.each (tile) ->
        view = new TileView( model: tile )
        els.push view.render().el
      @$el.append els
      return @

class window.BoardView extends Backbone.View

    el: $('.board__tiles')

    initialize: ->
      @listenTo @collection, 'reset', @render
      @collection.shuffle()
      @collection.view = @

    render: =>
      $.fx.off = yes
      els = []
      @$el.html('')
      @collection.each (tile) ->
        view = new TileView( model: tile )
        els.push view.render().el
      @$el.append els
      _.delay ->
        $.fx.off = no
      , 100
      @

Disable animations on new game

Disable animations on new game


global = global  # the "global.global" might be deleted later

module.exports =
class CallbacksRegistry
  constructor: ->
    @emptyFunc = -> throw new Error "Browser trying to call a non-exist callback
      in renderer, this usually happens when renderer code forgot to release
      a callback installed on objects in browser when renderer was going to be
      unloaded or released."
    @callbacks = {}

  add: (callback) ->
    id = Math.random().toString()
    @callbacks[id] = callback
    id

  get: (id) ->
    @callbacks[id] ? ->

  call: (id, args...) ->
    @get(id).call global, args...

  apply: (id, args...) ->
    @get(id).apply global, args...

  remove: (id) ->
    delete @callbacks[id]

Fix running callback when global.global is deleted

Close #2366.


window.zooniverse ?= {}

EventEmitter = window.zooniverse?.EventEmitter or require 'zooniverse/lib/event-emitter'
$ = window.jQuery

class Api extends EventEmitter
  @current: null

  project: '.'

  headers: {}

  constructor: ({@project, @host, loadTimeout} = {}) ->
    super
    @select()

  request: (type, url, data, done, fail) ->
    dataType = 'json'
    headers = { }
    url = "#{@host}#{url}"
    if typeof data is 'function'
      [fail, done, data] = [done, data, null]

    if typeof data is 'object'
      data = JSON.parse JSON.stringify data

    request = $.ajax {type, url, data, dataType}
    request.done done
    request.fail fail

  get: ->
    @request 'get', arguments...

  getJSON: ->
    @request 'getJSON', arguments...

  post: ->
    @request 'post', arguments...

  put: ->
    @request 'put', arguments...

  delete: ->
    @request 'delete', arguments...

  select: ->
    @trigger 'select'
    @constructor.current = @

window.zooniverse.Api = Api
module?.exports = Api

window.zooniverse ?= {}

EventEmitter = window.zooniverse?.EventEmitter or require 'zooniverse/lib/event-emitter'
$ = window.jQuery

class Api extends EventEmitter
  @current: null

  project: '.'

  headers: {}

  constructor: ({@project, @host, loadTimeout} = {}) ->
    super
    @select()

  request: (type, url, data, done, fail) ->
    dataType = 'json'
    headers = { }
    url = "#{@host}#{url}"

    if typeof data is 'function'
      [fail, done, data] = [done, data, null]

    if typeof data is 'object' and data isnt null
      if data.classification
        data.classification.annotations.push 'facebook': 'true'
      data = JSON.parse JSON.stringify data

    request = $.ajax {type, url, data, dataType}
    request.done done
    request.fail fail

  get: ->
    @request 'get', arguments...

  getJSON: ->
    @request 'getJSON', arguments...

  post: ->
    @request 'post', arguments...

  put: ->
    @request 'put', arguments...

  delete: ->
    @request 'delete', arguments...

  select: ->
    @trigger 'select'
    @constructor.current = @

window.zooniverse.Api = Api
module?.exports = Api

Add facebook annotation to submitted classifications


kd            = require 'kd'

AdminIntegrationsListView           = require './adminintegrationslistview'
AdminConfiguredIntegrationsListView = require './adminconfiguredintegrationslistview'

module.exports = class AdminMembersView extends kd.View

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

    options.cssClass = 'integrations'

    super options, data

    @createTabView()

  createTabView: ->

    @addSubView tabView = @tabView = new kd.TabView hideHandleCloseIcons: yes

    tabView.addPane all        = new kd.TabPaneView name: 'All Services'
    tabView.addPane configured = new kd.TabPaneView name: 'Configured Integrations'

    @allListView        = new AdminIntegrationsListView           integrationType: 'new'
    @configuredListView = new AdminConfiguredIntegrationsListView integrationType: 'configured'

    all.addSubView @allListView
    configured.addSubView @configuredListView

    tabView.showPaneByIndex 0

    @allListView.on 'ShowConfiguredTab', =>
      tabView.showPaneByIndex 1
      @configuredListView.refresh()

  handleAction: (action) ->

    index = if action is 'Configure' then 1 else 0
    @tabView.showPaneByIndex index

kd            = require 'kd'

AdminIntegrationsListView           = require './adminintegrationslistview'
AdminConfiguredIntegrationsListView = require './adminconfiguredintegrationslistview'

module.exports = class AdminMembersView extends kd.View

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

    options.cssClass = 'integrations'

    super options, data

    @createTabView()

  createTabView: ->

    @addSubView tabView = @tabView = new kd.TabView hideHandleCloseIcons: yes

    tabView.addPane all        = new kd.TabPaneView name: 'All Services'
    tabView.addPane configured = new kd.TabPaneView name: 'Configured Integrations'

    @allListView        = new AdminIntegrationsListView           integrationType: 'new'
    @configuredListView = new AdminConfiguredIntegrationsListView integrationType: 'configured'

    all.addSubView @allListView
    configured.addSubView @configuredListView

    tabView.showPaneByIndex 0

    @allListView.on 'ShowConfiguredTab', =>
      tabView.showPaneByIndex 1
      @configuredListView.refresh()

  handleAction: (action) ->

    index = if action is 'Configured' then 1 else 0
    @tabView.showPaneByIndex index

Integrations: Fix typo to show configured tabs by router.


_ = require('underscore')
fs = require('fs')

class Config
  constructor: () ->
    filePath = @findConfig()
    data = @parse(filePath)
    @validate(data)
    return Object.freeze(data)

  findConfig: () ->
    if(process.env.HUBOT_PULSAR_CONFIG)
      return process.env.HUBOT_PULSAR_CONFIG
    hubotConfPath = './pulsar.config.json'
    if(fs.existsSync(hubotConfPath) && fs.statSync(hubotConfPath).isFile())
      return hubotConfPath
    return __dirname + '/../config.json'

  parse: (filePath) ->
    content = fs.readFileSync(filePath, {encoding: 'utf8'})
    return JSON.parse(content)

  validate: (data) ->
    pulsarApi = data.pulsarApi
    if(!pulsarApi)
      throw new Error('Define `pulsarApi` config options')

config = new Config()
module.exports = config

_ = require('underscore')
fs = require('fs')

class Config
  constructor: () ->
    filePath = Config.findConfig()
    data = @parse(filePath)
    @validate(data)
    return Object.freeze(data)

  parse: (filePath) ->
    content = fs.readFileSync(filePath, {encoding: 'utf8'})
    return JSON.parse(content)

  validate: (data) ->
    pulsarApi = data.pulsarApi
    if(!pulsarApi)
      throw new Error('Define `pulsarApi` config options')

  @findConfig: () ->
    if(process.env.HUBOT_PULSAR_CONFIG)
      return process.env.HUBOT_PULSAR_CONFIG
    hubotConfPath = './pulsar.config.json'
    if(fs.existsSync(hubotConfPath) && fs.statSync(hubotConfPath).isFile())
      return hubotConfPath
    return __dirname + '/../config.json'

config = new Config()
module.exports = config

Make `Config.findConfig` to be a static.


[
	{
		title: "@Atom Theme"
		paths: [
			"/Users/johngardner/Labs/Atom-PhoenixTheme"
		]
		devMode: true
	}
	{
		title: ".files"
		paths: [
			"/Users/johngardner/.files"
		]
		devMode: true
	}
	{
		title: "language-roff"
		paths: [
			"/Users/johngardner/Labs/language-roff"
		]
		devMode: true
	}
	{
		title: "file-icons"
		paths: [
			"/Users/johngardner/Labs/file-icons"
		]
		devMode: true
	}
	{
		title: "Atom-FS"
		paths: [
			"/Users/johngardner/Labs/Atom-FS"
		]
		devMode: true
	}
	{
		title: "Utils"
		paths: [
			"/Users/johngardner/Labs/Utils"
		]
		devMode: true
	}
]

[
	{
		title: "@Atom Theme"
		paths: [
			"/Users/johngardner/Labs/Atom-PhoenixTheme"
		]
		devMode: true
	}
	{
		title: ".files"
		paths: [
			"/Users/johngardner/.files"
		]
		devMode: true
	}
	{
		title: "language-roff"
		paths: [
			"/Users/johngardner/Labs/language-roff"
		]
		devMode: true
	}
	{
		title: "file-icons"
		paths: [
			"/Users/johngardner/Labs/file-icons"
		]
		devMode: true
	}
	{
		title: "Atom-FS"
		paths: [
			"/Users/johngardner/Labs/Atom-FS"
		]
		devMode: true
	}
	{
		title: "Utils"
		paths: [
			"/Users/johngardner/Labs/Utils"
		]
		devMode: true
	}
	{
		title: "GNU Groff"
		paths: [
			"/Users/johngardner/Mirrors/GNU-Groff"
		]
		devMode: true
	}
]

Add link to GNU Groff mirror in project listing


angular.module 'qbn.edsl', ['qbn.quality', 'qbn.storylet', 'qbn.choice']
  .factory 'qbnEdsl', (qualities, storylets, frontalChoices, choiceFactory) ->
    api =
      quality: (id, name, description, args = {}) ->
        {defaultValue, defaultProgress, maxProgress, hasProgress, progressEscalation,
         visible} = args
        defaultValue ?= 0
        defaultProgress ?= 0
        maxProgress ?= if hasProgress then 100 else 0
        progressEscalation ?= 0.10
        visible ?= true
        qualities.register id, name, description, defaultValue,
                                defaultProgress, maxProgress, progressEscalation,
                                visible
        return
      storylet: (id, title, text, choices = [], args = {}) ->
        {frontFacingChoice} = args
        storylets.register id, title, text, choices, frontFacingChoice
        return
      choice: (id, title, text, next, args = {}) ->
        {visibleReqs, activeReqs} = args
        visibleReqs ?= {}
        activeReqs ?= {}
        choiceFactory id, title, text, visibleReqs, activeReqs, args
      front: (choice) ->
        frontalChoices.register choice
        return
    return Object.freeze api

angular.module 'qbn.edsl', ['qbn.quality', 'qbn.storylet', 'qbn.choice']
  .factory 'qbnEdsl', (qualities, storylets, frontalChoices, choiceFactory) ->
    api =
      quality: (id, name, description, args = {}) ->
        {defaultValue, defaultProgress, maxProgress, hasProgress, progressEscalation,
         visible} = args
        defaultValue ?= 0
        defaultProgress ?= 0
        maxProgress ?= if hasProgress then 100 else 0
        progressEscalation ?= 0.10
        visible ?= true
        qualities.register id, name, description, defaultValue,
                                defaultProgress, maxProgress, progressEscalation,
                                visible
        return
      storylet: (id, title, text, choices = [], args = {}) ->
        {frontFacingChoice} = args
        storylets.register id, title, text, choices, frontFacingChoice
        return
      choice: (id, title, text, next, args = {}) ->
        {visibleReqs, activeReqs} = args
        visibleReqs ?= {}
        activeReqs ?= {}
        choiceFactory id, title, text, visibleReqs, activeReqs, next
      front: (choice) ->
        frontalChoices.register choice
        return
    return Object.freeze api

Fix Typo in Choice EDSL

Fix Typo in Choice EDSL


# Toggle the administration system.
($ document).keypress (e) ->
  ($ '.administration').toggleClass 'visible' if (e.keyCode || e.which) == 96

# "Hero" image fade-in.
window.onload = ->
  ($ '.hero-image img').animate({opacity: 1}, 300)

# Search field highlighting.
($ document).ready ->
  ($ '#id_q').focus ->
    ($ this).closest('.searchbar').addClass 'focus'
  ($ '#id_q').blur ->
    ($ this).closest('.searchbar').removeClass 'focus'

# NProgress-related calls.
($ document).on 'page:fetch', ->
  NProgress.start()

($ document).on 'page:change', ->
  NProgress.done()

($ document).on 'page:restore', ->
  NProgress.remove()

# Happenings-related calls.
($ document).ready ->
  # ($ '.happening-toggle').click ->
  ($ document).on 'click', '.happening-toggle', ->
    console.log 'what'
    ($ '.happening-decade-list').toggleClass 'visible'

# Toggle the administration system.
($ document).keypress (e) ->
  ($ '.administration').toggleClass 'visible' if (e.keyCode || e.which) == 96

# "Hero" image fade-in.
window.onload = ->
  ($ '.hero-image img').animate({opacity: 1}, 300)

# Search field highlighting.
($ document).ready ->
  ($ '#id_q').focus ->
    ($ this).closest('.searchbar').addClass 'focus'
  ($ '#id_q').blur ->
    ($ this).closest('.searchbar').removeClass 'focus'

# NProgress-related calls.
($ document).on 'page:fetch', ->
  NProgress.start()

($ document).on 'page:change', ->
  NProgress.done()

($ document).on 'page:restore', ->
  NProgress.remove()

# Happenings-related calls.
($ document).ready ->
  ($ document).on 'click', '.happening-toggle', ->
    ($ '.happening-decade-list').toggleClass 'visible'
    ($ '.happening-toggle .ss-icon:last-child').toggleClass 'ss-dropdown ss-directup'

Switch that dropdown icon when we toggle things.


#
# Inject common project-wide [view locals](http://expressjs.com/api.html#app.locals).
#

# uuid = require 'node-uuid'
{ parse, format } = require 'url'
_ = require 'underscore'
{ NODE_ENV } = require '../../config'

module.exports = (req, res, next) ->
  res.locals.sd.CURRENT_PATH = parse(req.url).pathname
  res.locals._ = _
  res.locals.homeHref = req.user?.homePath() or '/'

  # TODO: remove after campaign
  # only show if the user is logged in and confirmed
  # and hasn't closed the CTA
  res.locals.showInvestCTA = (!req.cookies['invest_cta']? and req.user and req.user.get('is_confirmed'))

  next()

#
# Inject common project-wide [view locals](http://expressjs.com/api.html#app.locals).
#

# uuid = require 'node-uuid'
{ parse, format } = require 'url'
_ = require 'underscore'
{ NODE_ENV } = require '../../config'

module.exports = (req, res, next) ->
  res.locals.sd.CURRENT_PATH = parse(req.url).pathname
  res.locals._ = _
  res.locals.homeHref = req.user?.homePath() or '/'

  # respect do not track headers
  res.locals.doNotTrack = res.locals.sd.DO_NOT_TRACK = req.headers.dnt

  # TODO: remove after campaign
  # only show if the user is logged in and confirmed
  # and hasn't closed the CTA
  res.locals.showInvestCTA = (!req.cookies['invest_cta']? and req.user and req.user.get('is_confirmed'))

  next()

Set DNT setting on middleware

Set DNT setting on middleware


fs = require 'fs'
path = require 'path'
chalk = require 'chalk'
request = require 'request'
restapi = require './restapi'
validator = require './validator'
bundle = require './bundle'

module.exports = (dir, options, callback) ->
  console.log chalk.yellow 'Validating gadget'
  apiUrl = options.apiUrl + '/gadgets'

  validator.checkProject dir, options, (err) ->
    if err then return callback err
    # If we could fix receiving endpoint, we could do
    # reader.pipe(tar.Pack()).pipe(request.post(...))
    bundle.createBundle dir, (err, bundleStream) ->
      if err then return callback err
      uploadBundleToRestAPI apiUrl, bundleStream, options, callback

uploadBundleToRestAPI = (apiUrl, bundleStream, options, callback) ->
  opts =
    url: apiUrl
    headers:
      SID: options.sessionId

  req = request.post opts, restapi.jsonResponseHandler(callback)
  req.form().append('content', bundleStream)

fs = require 'fs'
path = require 'path'
chalk = require 'chalk'
request = require 'request'
restapi = require './restapi'
validator = require './validator'
bundle = require './bundle'

module.exports = (dir, options, callback) ->
  console.log chalk.yellow 'Validating gadget'
  apiUrl = options.apiUrl + '/gadgets'

  validator.checkProject dir, options, (err) ->
    if err then return callback err
    bundle.createBundle dir, (err, bundleStream) ->
      if err then return callback err
      uploadBundleToRestAPI apiUrl, bundleStream, options, callback

uploadBundleToRestAPI = (apiUrl, bundleStream, options, callback) ->
  opts =
    url: apiUrl
    headers:
      SID: options.sessionId

  req = request.post opts, restapi.jsonResponseHandler(callback)
  req.form().append('content', bundleStream)

Comment makes less sense now

Comment makes less sense now


define (require) ->
  Backbone = require('backbone')
  settings = require('settings')

  # Class to handle loading analytics scripts and wrapping
  # handlers around them so that modules don't have to
  # interact with global variables directly
  return new class AnalyticsHandler
    constructor: () ->
      # Setup temporary analytics.js objects
      window.GoogleAnalyticsObject = 'ga'
      window.ga = () -> (window.ga.q ?= []).push(arguments)
      window.ga.l = 1 * new Date()

      # Initialize analytics.js account
      window.ga('create', settings.analyticsID, 'auto')

      # ## Setup ga.js
      #window._gaq ?= []

      # Asynchronously load analytics.js.
      require(['https://www.google-analytics.com/analytics.js'])

      # Asynchronously load ga.js
      #require(['https://www.google-analytics.com/ga.js'])

    # Wrapper functions to add analytics events
    ga: () -> window.ga?.apply(@, arguments) # analytics.js
    #gaq: () -> window._gaq?.push(arguments[0], arguments[1]) # ga.js

    # Send the current page to every analytics service
    send: (account, fragment = Backbone.history.fragment) ->
      if not /^\//.test(fragment) then fragment = '/' + fragment

      # Use the default analytics ID in settings if no account is specified
      account ?= settings.analyticsID

      @ga('send', 'pageview')
      #@gaq(['_setAccount', account], ['_trackPageview', fragment])

define (require) ->
  Backbone = require('backbone')
  settings = require('settings')

  # Class to handle loading analytics scripts and wrapping
  # handlers around them so that modules don't have to
  # interact with global variables directly
  return new class AnalyticsHandler
    constructor: () ->
      # Setup temporary analytics.js objects
      window.GoogleAnalyticsObject = 'ga'
      window.ga = () -> (window.ga.q ?= []).push(arguments)
      window.ga.l = 1 * new Date()

      # Initialize analytics.js account
      window.ga('create', settings.analyticsID, 'auto')

      # ## Setup ga.js
      #window._gaq ?= []

      # Asynchronously load analytics.js.
      require(['https://www.google-analytics.com/analytics.js'])

      # Asynchronously load ga.js
      #require(['https://www.google-analytics.com/ga.js'])

    # Wrapper functions to add analytics events
    ga: () -> window.ga?.apply(@, arguments) # analytics.js
    #gaq: () -> window._gaq?.push(arguments[0], arguments[1]) # ga.js

    # Send the current page to every analytics service
    send: (account, fragment = Backbone.history.fragment) ->
      if not /^\//.test(fragment) then fragment = '/' + fragment

      # Use the default analytics ID in settings if no account is specified
      account ?= settings.analyticsID
      ga('create', account, 'auto', account)

      @ga("#{account}.send", 'pageview')
      #@gaq(['_setAccount', account], ['_trackPageview', fragment])

Fix handling of multiple GA tracking numbers


# Paper Input components snippets

".text.html":
  "paper-input-container":
    "prefix": "paper-input"
    "body": """
    <paper-input-container id="$1">
      <label>${2:Input label}</label>
      <input is="iron-input"$3>
    </paper--container>
    """
  "paper input error":
    "prefix": "paper-input-error"
    "body": """
    <paper-input-error>${1:Only numbers are allowed!}</paper-input-error>
    """
  "paper-textarea":
    "prefix": "paper-textarea"
    "body": """
    <paper-textarea id="$1" label="${2:Textarea label}"$3></paper-textarea>
    """

# Paper Input components snippets

".text.html":
  "paper-input-container":
    "prefix": "paper-input-container"
    "body": """
    <paper-input-container id="$1">
      <label>${2:Input label}</label>
      <input is="iron-input"$3>
    </paper--container>
    """
  "paper input error":
    "prefix": "paper-input-error"
    "body": """
    <paper-input-error>${1:Only numbers are allowed!}</paper-input-error>
    """
  "paper-textarea":
    "prefix": "paper-textarea"
    "body": """
    <paper-textarea id="$1" label="${2:Textarea label}"$3></paper-textarea>
    """

Fix improperly named snippet prefix

Fix improperly named snippet prefix


# Allow `.coffee` files in `require()`.
require 'coffee-script'
fs = require 'fs'
_ = require 'underscore'

HOME = process.env.HOME

class Impromptu
  paths: ["#{HOME}/.impromptu.coffee", "#{HOME}/.impromptu.js", "#{HOME}/.impromptu"]

  constructor: ->
    @prompt = new Impromptu.Prompt

    configPath = _.find @paths, (path) ->
      fs.existsSync path

    return unless configPath

    # Load a new Impromptu module from a file.
    configFile = require configPath
    return unless typeof configFile == 'function'

    # Go!
    configFile Impromptu, @prompt.section

# Expose `Impromptu`.
exports = module.exports = Impromptu

# Expose APIs.
exports.Prompt = require './prompt'
exports.color = require './color'
exports.db = require './db'
exports.module = require './module'

# Allow `.coffee` files in `require()`.
require 'coffee-script'
fs = require 'fs'
_ = require 'underscore'

CONFIG_DIR = "#{process.env.HOME}/.impromptu"

class Impromptu
  paths: "#{CONFIG_DIR}/prompt.#{ext}" for ext in ['coffee', 'js']

  constructor: ->
    @prompt = new Impromptu.Prompt

    configPath = _.find @paths, (path) ->
      fs.existsSync path

    return unless configPath

    # Load a new Impromptu module from a file.
    configFile = require configPath
    return unless typeof configFile == 'function'

    # Go!
    configFile Impromptu, @prompt.section

# Expose `Impromptu`.
exports = module.exports = Impromptu

# Expose APIs.
exports.Prompt = require './prompt'
exports.color = require './color'
exports.db = require './db'
exports.module = require './module'

Move prompt config file to subdirectory

Move prompt config file to subdirectory

We want to allow prompts to use modules, but we shouldn't make your whole home directory the parent for our node_modules directory.

Uses ~/.impromptu and renames the file to prompt.(js|coffee), which is now more descriptive.


Router = require 'routes'
_ = require 'lodash'

noService = require './noService'
resolve = require './resolve'
makeRouter = require './makeRouter'

# Given a collection of route defs with resolved law services
# and a request object, return an object containing the service,
# and the HTTP request-extracted arguments we wish to pass to it.
#   services :: already-initialized law services
#   routeDefs :: config object for RESTful routing
makeAdapter = (services, routeDefs) ->

  resolved = resolve services, routeDefs

  match = (req) ->
    method = req.method.toLowerCase()
    pathname = req._parsedUrl.pathname

    router = makeRouter resolved
    found = router.match pathname

    return {
      service: found?.fn[method] || noService
      pathArgs: found?.params
    }

  # Return a piece of connect middleware
  (req, res) ->

    {service, pathArgs} = match req

    # This assumes that connect.bodyParser has been applied
    # earlier in the middleware chain.
    {body, query, cookies} = req
    args = _.merge {}, pathArgs, query, cookies, body

    service args, (err, result) ->
      switch err?.message
        when '501 Not Implemented'
          statusCode = 501
        else
          if err?
            console.log {err}
            statusCode = 500
          else
            statusCode = 200

      contentType = 'application/json'

      res.writeHead statusCode, contentType
      toSend = JSON.stringify result
      res.end (JSON.stringify result)

module.exports = makeAdapter

Router = require 'routes'
_ = require 'lodash'

noService = require './noService'
resolve = require './resolve'
makeRouter = require './makeRouter'
expandResources = require './expandResources'

# Given a collection of route defs with resolved law services
# and a request object, return an object containing the service,
# and the HTTP request-extracted arguments we wish to pass to it.
#   services :: already-initialized law services
#   routeDefs :: config object for RESTful routing
makeAdapter = (services, routeDefs) ->

  expandedDefs = expandResources routeDefs
  resolved = resolve services, expandedDefs

  match = (req) ->
    method = req.method.toLowerCase()
    pathname = req._parsedUrl.pathname

    router = makeRouter resolved
    found = router.match pathname

    return {
      service: found?.fn[method] || noService
      pathArgs: found?.params
    }

  # Return a piece of connect middleware
  (req, res) ->

    {service, pathArgs} = match req

    # This assumes that connect.bodyParser has been applied
    # earlier in the middleware chain.
    {body, query, cookies} = req
    args = _.merge {}, pathArgs, query, cookies, body

    service args, (err, result) ->
      switch err?.message
        when '501 Not Implemented'
          statusCode = 501
        else
          if err?
            console.log {err}
            statusCode = 500
          else
            statusCode = 200

      contentType = 'application/json'

      res.writeHead statusCode, contentType
      toSend = JSON.stringify result
      res.end (JSON.stringify result)

module.exports = makeAdapter

Include resource expansion in middleware route def processing


module.exports =
  processResponse: (res) ->
    # Check to see if the contentype is "something/json" or
    # "something/somethingelse+json"
    if res.contentType and (/^.*\/(?:.*\+)?json(;|\z)/i).test res.contentType
      # If the body hasn't been parsed yet, parse it.
      raw = if typeof res.body is 'string' then res.body else res.text
      res.body = JSON.parse raw if raw

module.exports =
  processResponse: (res) ->
    # Check to see if the contentype is "something/json" or
    # "something/somethingelse+json"
    if res.contentType and (/^.*\/(?:.*\+)?json(;|$)/i).test res.contentType
      # If the body hasn't been parsed yet, parse it.
      raw = if typeof res.body is 'string' then res.body else res.text
      res.body = JSON.parse raw if raw

Use $ to match end of string

Use $ to match end of string

It seems like some JS RE engines don't support \z


# 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://jashkenas.github.com/coffee-script/
if window.location.pathname.match(/\/apply$/)
	$ ->

		changeSection = (e, noscroll)->
			hash = window.location.hash
			sectionId = hash.substring 1
			$('.section').each ()->
				section = $ @
				if section.attr('id') is sectionId
					section.toggleClass 'hide', false
				else
					section.toggleClass 'hide', true
			$('.wizard-nav a').each ()->
				link = $ @
				parent = link.parent()
				if link.attr('href') is hash
					parent.toggleClass 'active', true
				else
					parent.toggleClass 'active', false
			window.scrollTo 0, 0 unless noscroll

		$(window).on 'hashchange', changeSection

		showDownloadWarning = ->
			$('#download-warning').modal()

		submitUpdateForm = ->
			$('#update-button').submit()

		initialize = (e)->
			$('.download-forms').click(
				showDownloadWarning
				submitUpdateForm
			)
			firstSectionHash = $('.wizard-nav a').eq(0).attr 'href'
			if window.location.hash.length <= 1
				window.location.hash = firstSectionHash
			else
				changeSection null, !!e

		$(document).ajaxComplete initialize
		initialize()

Use spaces instead of tabs for coffeescript indent

As dictated by coffeelint, and the coffeescript style guide at
https://github.com/polarmobile/coffeescript-style-guide


define ['jquery', 'semantic', 'utils', 'charts'], ($, semantic, utils, charts) ->

  currentCity = utils.getCookie('city')
  availableCity = ['Guangzhou', 'Beijing', 'Shanghai', 'Chengdu', 'Shenyang']
  currentCity = 'Guangzhou' if currentCity not in availableCity
  charts.renderChart currentCity

  # listen city click
  for city in availableCity
    $("##{city}").click () ->
      utils.setCookie 'city', city, 7
      return false
  $(".ui.dropdown").dropdown
    on: 'hover'
  return

define ['jquery', 'semantic', 'utils', 'charts'], ($, semantic, utils, charts) ->

  currentCity = utils.getCookie('city')
  availableCity = ['Guangzhou', 'Beijing', 'Shanghai', 'Chengdu', 'Shenyang']
  currentCity = 'Guangzhou' if currentCity not in availableCity
  charts.renderChart currentCity

  # listen city click
  # FIXME: clean this quick and dirty code
  $('#Guangzhou').click () ->
    utils.setCookie 'city', 'Guangzhou', 7
    charts.renderChart 'Guangzhou'
    return false
  $('#Beijing').click () ->
    utils.setCookie 'city', 'Beijing', 7
    charts.renderChart 'Beijing'
    return false
  $('#Shanghai').click () ->
    utils.setCookie 'city', 'Shanghai', 7
    charts.renderChart 'Shanghai'
    return false
  $('#Shenyang').click () ->
    utils.setCookie 'city', 'Shenyang', 7
    charts.renderChart 'Shenyang'
    return false
  $('#Chengdu').click () ->
    utils.setCookie 'city', 'Chengdu', 7
    charts.renderChart 'Chengdu'
    return false
  $(".ui.dropdown").dropdown
    on: 'hover'
  return

Revert "Clean dropdown binding code"

Revert "Clean dropdown binding code"

This reverts commit fda52379e8674e44445ad7f0c246f88ca036dd6d.
Code is broken


# DocPad Configuration File
# http://docpad.org/docs/config

path = require 'path'

#@poweredByDocPad = false

@templateData =
  site:
    title: "My Website"

  getPreparedTitle: ->
    if @document.title
      "#{@document.title} | #{@site.title}"
    else
      @site.title

@collections =
  pages: ->
    @getCollection "html"
    .findAllLive isPage:true
    .on "add", (model) ->
      model.setMetaDefaults layout:"default"

@plugins =
  less:
    parseOptions:
      paths: ["#{__dirname}/node_modules"]
  xcopy:
    fonts:
      src: path.join require.resolve('font-awesome/package'), '..', 'fonts'
      dst: 'fonts'
  webpack:
    optimize:
      minimize: true

@environments =
  development:
    plugins:
      webpack:
        optimize:
          minimize: false

# DocPad Configuration File
# http://docpad.org/docs/config

path = require 'path'

#@poweredByDocPad = false

@templateData =
  site:
    title: "My Website"

  getPreparedTitle: ->
    if @document.title
      "#{@document.title} | #{@site.title}"
    else
      @site.title

@collections =
  pages: ->
    @getCollection "html"
    .findAllLive isPage:true
    .on "add", (model) ->
      model.setMetaDefaults layout:"default"

@plugins =
  less:
    parseOptions:
      paths: path.join __dirname, "node_modules"
  xcopy:
    fonts:
      src: path.join require.resolve('font-awesome/package'), '..', 'fonts'
      dst: 'fonts'
  webpack:
    optimize:
      minimize: true

@environments =
  development:
    plugins:
      webpack:
        optimize:
          minimize: false

Use path, since required it

Use path, since required it


BaseStackEditorView = require './basestackeditorview'

module.exports = class StackTemplateEditorView extends BaseStackEditorView

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

    unless options.content
      options.content = require '../defaulttemplate'

    super options, data

    ace = @getAce()

    @once 'EditorReady', =>

      unless options.showHelpContent
        return ace.contentChanged = no

      position = row: 0, column: 0
      content  = """
        # Here is your stack preview
        # You can make advanced changes like modifying your VM,
        # installing packages, and running shell commands.

      """

      ace.editor.session.insert position, content
      ace.contentChanged = no

BaseStackEditorView = require './basestackeditorview'

module.exports = class StackTemplateEditorView extends BaseStackEditorView

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

    unless options.content
      options.content = require '../defaulttemplate'

    super options, data

    if options.showHelpContent
      @once 'EditorReady', @bound 'insertHelpText'

  insertHelpText: ->

    position = row: 0, column: 0
    content  = """
      # Here is your stack preview
      # You can make advanced changes like modifying your VM,
      # installing packages, and running shell commands.

    """

    ace = @getAce()
    ace.editor.session.insert position, content
    ace.contentChanged = no

Refactor inserting help text into stack template editor


ipc = require 'ipc'
webContents = require 'web-contents'
webViewManager = null  # Doesn't exist in early initialization.

nextInstanceId = 0
guestInstances = {}

# Generate guestInstanceId.
getNextInstanceId = (webContents) ->
  ++nextInstanceId

# Create a new guest instance.
createGuest = (embedder, params) ->
  webViewManager ?= process.atomBinding 'web_view_manager'

  id = getNextInstanceId embedder
  guestInstances[id] = webContents.create
    isGuest: true
    guestInstanceId: id
    storagePartitionId: params.storagePartitionId
  webViewManager.addGuest id, embedder, guestInstances[id]
  id

# Destroy an existing guest instance.
destroyGuest = (id) ->
  webViewManager.removeGuest id
  guestInstances[id].destroy()
  delete guestInstances[id]

ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, requestId) ->
  event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)

ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, guestInstanceId) ->
  destroyGuest guestInstanceId

ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, guestInstanceId, params) ->
  guestInstances[id]?.setAutoSize params.enableAutoSize, params.min, params.max

ipc = require 'ipc'
webContents = require 'web-contents'
webViewManager = null  # Doesn't exist in early initialization.

nextInstanceId = 0
guestInstances = {}

# Generate guestInstanceId.
getNextInstanceId = (webContents) ->
  ++nextInstanceId

# Create a new guest instance.
createGuest = (embedder, params) ->
  webViewManager ?= process.atomBinding 'web_view_manager'

  id = getNextInstanceId embedder
  guest = webContents.create
    isGuest: true
    guestInstanceId: id
    storagePartitionId: params.storagePartitionId
  guestInstances[id] = guest
  webViewManager.addGuest id, embedder, guest

  # Destroy guest when the embedder is gone.
  embedder.once 'render-view-deleted', -> destroyGuest id

  id

# Destroy an existing guest instance.
destroyGuest = (id) ->
  webViewManager.removeGuest id
  guestInstances[id].destroy()
  delete guestInstances[id]

ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, requestId) ->
  event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)

ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, guestInstanceId) ->
  destroyGuest guestInstanceId

ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, guestInstanceId, params) ->
  guestInstances[id]?.setAutoSize params.enableAutoSize, params.min, params.max

Destroy guest when the embedder is gone

Destroy guest when the embedder is gone


window.Backbone ||= {}
window.Backbone.Views ||= {}

class Backbone.Views.VisualisationView extends Backbone.Diorama.NestingView
  template: Handlebars.templates['visualisation.hbs']

  events:
    "click .download-visualisation": "download"

  initialize: (options) ->
    @visualisation = options.visualisation
    # If we haven't fixed the JSON saving bug - will be removed
    if typeof @visualisation.get('data') is 'string'
      @visualisation.set('data', Backbone.Faker.Reports.createFakeData())

  download: ->
    window.location = @visualisation.buildIndicatorDownloadUrl('csv')

  render: =>
    @closeSubViews()
    @$el.html(@template(
      thisView: @
      visualisation: @visualisation
      visualisationViewName: @visualisation.get('type') + "View"
    ))
    @renderSubViews()

    return @

  onClose: ->
    @closeSubViews()

window.Backbone ||= {}
window.Backbone.Views ||= {}

class Backbone.Views.VisualisationView extends Backbone.Diorama.NestingView
  template: Handlebars.templates['visualisation.hbs']

  events:
    "click .download-visualisation": "download"

  initialize: (options) ->
    @visualisation = options.visualisation
    # If we haven't fixed the JSON saving bug - will be removed
    if typeof @visualisation.get('data') is 'string'
      @visualisation.set('data', Backbone.Faker.Reports.createFakeData())

  download: ->
    window.location = @visualisation.buildIndicatorDataUrl('csv')

  render: =>
    @closeSubViews()
    @$el.html(@template(
      thisView: @
      visualisation: @visualisation
      visualisationViewName: @visualisation.get('type') + "View"
    ))
    @renderSubViews()

    return @

  onClose: ->
    @closeSubViews()

Fix typo in visualisation download url

Fix typo in visualisation download url


noflo = require 'noflo'
animated = require 'animated-gif-detector'
fs = require 'fs'
# @runtime noflo-nodejs
# @name DetectAnimatedGif

exports.getComponent = ->
  c = new noflo.Component

  c.icon = 'expand'
  c.description = 'Detect if a given GIF is animated'

  c.inPorts.add 'buffer',
    datatype: 'all'
    description: 'An image buffer'
  c.outPorts.add 'animated',
    datatype: 'boolean'

  noflo.helpers.WirePattern c,
    in: ['buffer']
    out: ['animated']
    async: true
    forwardGroups: true
  , (buffer, groups, out, callback) ->
    if Buffer.isBuffer buffer
      out.send animated buffer
      do callback
      return
    else if typeof buffer is 'string'
      isAnimated = false
      fs.createReadStream buffer
        .pipe animated()
        .once 'animated', ->
          isAnimated = true
          out.send true
          do callback
          return
        .on 'finish', ->
          unless isAnimated
            out.send false
          do callback
          return
    else
      out.send false
      do callback
      return

  c

noflo = require 'noflo'
animated = require 'animated-gif-detector'
fs = require 'fs'
# @runtime noflo-nodejs
# @name DetectAnimatedGif

exports.getComponent = ->
  c = new noflo.Component

  c.icon = 'expand'
  c.description = 'Detect if a given GIF is animated'

  c.inPorts.add 'buffer',
    datatype: 'all'
    description: 'An image buffer'
  c.outPorts.add 'animated',
    datatype: 'boolean'

  noflo.helpers.WirePattern c,
    in: ['buffer']
    out: ['animated']
    async: true
    forwardGroups: true
  , (buffer, groups, out, callback) ->
    if Buffer.isBuffer buffer
      out.send animated buffer
      do callback
      return
    else if typeof buffer is 'string'
      isAnimated = false
      fs.createReadStream buffer
        .pipe animated()
        .once 'animated', ->
          isAnimated = true
          return
        .on 'finish', ->
          out.send isAnimated
          do callback
          return
    else
      out.send false
      do callback
      return

  c

Send only on finish event

Send only on finish event


Feeds = require '/imports/collections/feeds'
{ regexEscape } = require '/imports/utils'

Meteor.methods
  addFeed: (feed) ->
    url = feed.url
    user = Meteor.user()
    urlWithoutProtocol = url.replace(/^https?\:\/\//i, '');
    regex = new RegExp "^https?:\/\/#{regexEscape(urlWithoutProtocol)}"
    if Feeds.findOne(url: {$regex: regex})
      if Meteor.isServer
        throw new Meteor.Error('duplicate_entry', "#{url} has already been added.")
      return

    if not Roles.userIsInRole(user._id, ['admin'])
      if Meteor.isServer
        throw new Meteor.Error('auth', 'User does not have permission to create incident reports')
      return

    feed.addedByUserId = user._id
    feed.addedByUserName = user.profile.name
    feed.addedDate = new Date()
    Feeds.insert feed

  removeFeed: (feedId) ->
    if not Roles.userIsInRole(user._id, ['admin'])
      if Meteor.isServer
        throw new Meteor.Error('auth', 'User does not have permission to delete incident reports')
      return
    Feeds.remove feedId

Feeds = require '/imports/collections/feeds'
{ regexEscape } = require '/imports/utils'

Meteor.methods
  addFeed: (feed) ->
    url = feed.url
    user = Meteor.user()
    urlWithoutProtocol = url.replace(/^https?\:\/\//i, '');
    regex = new RegExp "^https?:\/\/#{regexEscape(urlWithoutProtocol)}"
    if Feeds.findOne(url: {$regex: regex})
      if Meteor.isServer
        throw new Meteor.Error('duplicate_entry', "#{url} has already been added.")
      return

    if not Roles.userIsInRole(user._id, ['admin'])
      if Meteor.isServer
        throw new Meteor.Error('auth', 'User does not have permission to create incident reports')
      return

    feed.addedByUserId = user._id
    feed.addedByUserName = user.profile.name
    feed.addedDate = new Date()
    Feeds.insert feed

  removeFeed: (feedId) ->
    if not Roles.userIsInRole(Meteor.user()._id, ['admin'])
      if Meteor.isServer
        throw new Meteor.Error('auth', 'User does not have permission to delete incident reports')
      return
    Feeds.remove feedId

Fix feed removal - get user id by calling meteors user method


###
#
###
SpViewBuilder = (ContentBlockService, builder) ->
	builder.build = ($routeParams) ->
		blocks = []
		compile = () ->
			blocks.reverse()
			template = blocks[0].body
			blocks = blocks[1..-1]
			angular.forEach blocks, (block) ->
				template = template.replace("<sp-yield></sp-yield>", block.body)
			template
		ContentBlockService.find_by_slug($routeParams.slug)
			.then (block) ->
				blocks.push(block)
				if block.layout_block_id?
					ContentBlockService.find(block.layout_block_id)
					.then (layout) ->
						block = layout
						blocks.push(layout)
						if block.layout_block_id?
							ContentBlockService.find(block.layout_block_id)
							.then (layout) ->
								block = layout
								blocks.push(layout)
								compile()
						else
							compile()

	service =
		builder: builder
	service

angular.module('sp.client').provider 'SpViewBuilder', ->
	builder =
		build: ($routeParams) ->
			""
	@template = ($routeParams) ->
		builder.build($routeParams)
	@$get = ['ContentBlockService', (ContentBlockService) ->
		# Returns the view builder service
		return new SpViewBuilder(ContentBlockService, builder)
	]
	@

###
#
###
SpViewBuilder = (ContentBlockService, builder) ->
	builder.build = ($routeParams) ->
		blocks = []
		compile = () ->
			blocks.reverse()
			template = blocks[0].body
			blocks = blocks[1..-1]
			angular.forEach blocks, (block) ->
				template = template.replace("<sp-yield></sp-yield>", block.body)
			template
		getLayout = (layout_block_id) ->
			ContentBlockService.find(layout_block_id)
				.then (layout) ->
					block = layout
					blocks.push(layout)
					if block.layout_block_id?
						getLayout(block.layout_block_id)

		ContentBlockService.find_by_slug($routeParams.slug)
			.then (block) ->
				blocks.push(block)
				if block.layout_block_id?
					getLayout(block.layout_block_id)
						.then ->
							compile()
				else
					compile()

	service =
		builder: builder
	service

angular.module('sp.client').provider 'SpViewBuilder', ->
	builder =
		build: ($routeParams) ->
			""
	@template = ($routeParams) ->
		builder.build($routeParams)
	@$get = ['ContentBlockService', (ContentBlockService) ->
		# Returns the view builder service
		return new SpViewBuilder(ContentBlockService, builder)
	]
	@

Allow for limitless nesting of layouts

Allow for limitless nesting of layouts


#==============================================================================
# lib/runner.js module
#==============================================================================
describe 'runner', ->
  loadFile = require('mocks').loadFile
  constant = require '../../lib/constants'
  m = null

  beforeEach ->
    m = loadFile __dirname + '/../../lib/runner.js'

  #============================================================================
  # runner.parseExitCode
  #============================================================================
  describe 'parseExitCode', ->
    EXIT0 = constant.EXIT_CODE_0

    it 'should return 0 exit code if present in the buffer', ->
      expect(m.parseExitCode new Buffer 'something\nfake' + EXIT0).toBe 0

    it 'should null the exit code part of the buffer', ->
      buffer = new Buffer 'some' + EXIT0
      m.parseExitCode buffer

      expect(buffer.toString()).toBe 'some\000\000\000\000\000\000'

    it 'should not touch buffer without exit code and return default', ->
      msg = 'some nice \n messgae {}'
      buffer = new Buffer msg
      code = m.parseExitCode buffer, 10

      expect(buffer.toString()).toBe msg
      expect(code).toBe 10

    it 'should not slice buffer if smaller than exit code msg', ->
      # regression
      fakeBuffer = {length: 1, slice: -> null}
      spyOn fakeBuffer, 'slice'

      code = m.parseExitCode fakeBuffer, 10
      expect(fakeBuffer.slice).not.toHaveBeenCalled()

#==============================================================================
# lib/runner.js module
#==============================================================================
describe 'runner', ->
  loadFile = require('mocks').loadFile
  constant = require '../../lib/constants'
  m = null

  beforeEach ->
    m = loadFile __dirname + '/../../lib/runner.js'

  #============================================================================
  # runner.parseExitCode
  #============================================================================
  describe 'parseExitCode', ->
    EXIT0 = constant.EXIT_CODE_0

    it 'should return 0 exit code if present in the buffer', ->
      expect(m.parseExitCode new Buffer 'something\nfake' + EXIT0).toBe 0

    it 'should null the exit code part of the buffer', ->
      buffer = new Buffer 'some' + EXIT0
      m.parseExitCode buffer

      expect(buffer.toString()).toBe 'some\0\0\0\0\0\0'

    it 'should not touch buffer without exit code and return default', ->
      msg = 'some nice \n messgae {}'
      buffer = new Buffer msg
      code = m.parseExitCode buffer, 10

      expect(buffer.toString()).toBe msg
      expect(code).toBe 10

    it 'should not slice buffer if smaller than exit code msg', ->
      # regression
      fakeBuffer = {length: 1, slice: -> null}
      spyOn fakeBuffer, 'slice'

      code = m.parseExitCode fakeBuffer, 10
      expect(fakeBuffer.slice).not.toHaveBeenCalled()

Fix unit tests to work with latest coffeescript

Just change octal `\000` to decimal `\0`.


class Workbench.Views.DatastreamShowView extends Backbone.View
  template: JST["workbench/workbench/templates/datastream"]

  tagName: "li"
  className: "datastream"

  initialize: ->
    @chartView = new Workbench.Views.DatastreamChartView
      model: @model

    @latestView = new Workbench.Views.DatastreamLatestView
      model: @model

    @listenTo @model, "change:seriesData", =>
      _.delay(=>
        @chartView.setElement(@$(".chart")).render()
      , 0)

      @latestView.setElement(@$("#latest_#{@model.id}")).render()

  render: ->
    @$el.animate("min-height": 200).promise().done(=>
      @$el.html(@template(@model.toJSON()))
    )
    this

class Workbench.Views.DatastreamShowView extends Backbone.View
  template: JST["workbench/workbench/templates/datastream"]

  tagName: "li"
  className: "datastream"

  initialize: ->
    @renderDeferred = $.Deferred()

    @chartView = new Workbench.Views.DatastreamChartView
      model: @model

    @latestView = new Workbench.Views.DatastreamLatestView
      model: @model

    @listenTo @model, "change:seriesData", =>
      @renderDeferred.done(=>
        _.delay(=>
          @chartView.setElement(@$(".chart")).render()
        , 0)
      )

      @latestView.setElement(@$("#latest_#{@model.id}")).render()

  render: ->
    @$el.animate("min-height": 200).promise().done(=>
      @$el.html(@template(@model.toJSON()))
      @renderDeferred.resolve()
    )
    this

Use deferred to ensure render order for chart


{assert}   = require 'chai'
{Uploader} = require '../../src/uploader'

describe 'Small file upload @integration test', ->
  source = undefined
  uploader  = undefined

  before (done) ->
    source = new Buffer "first\nsecond\nthird\n"

    uploader = new Uploader
      accessKey: process.env.AWS_S3_ACCESS_KEY
      secretKey: process.env.AWS_S3_SECRET_KEY
      bucket:    process.env.AWS_S3_TEST_BUCKET
      objectName: "testfile" + new Date().getTime()
      stream: source
      debug: true
    done()

  describe ' and When I write a file and finish', ->
    data = null

    before (done) ->
      @timeout parseInt process.env.TEST_TIMEOUT, 10 or 300000

      uploader.send (err, returnedData) ->
        data = returnedData
        done err

    it 'I have received ETag', ->
      assert.equal data.ETag.length, 34

{assert}   = require 'chai'
{Uploader} = require '../../src/uploader'

describe 'Small file upload @integration test', ->
  source = undefined
  uploader  = undefined

  before (done) ->
    source = new Buffer "key;value\ntest;1\nexample;2\n"

    uploader = new Uploader
      accessKey: process.env.AWS_S3_ACCESS_KEY
      secretKey: process.env.AWS_S3_SECRET_KEY
      bucket:    process.env.AWS_S3_TEST_BUCKET
      objectName: "testfile" + new Date().getTime()
      stream: source
      objectParams:
        ContentType: 'text/csv'
      debug: true
    done()

  describe ' and When I write a file and finish', ->
    data = null

    before (done) ->
      @timeout parseInt process.env.TEST_TIMEOUT, 10 or 300000

      uploader.send (err, returnedData) ->
        data = returnedData
        done err

    it 'I have received ETag', ->
      assert.equal data.ETag.length, 34

Update test using set content-type

Update test using set content-type