window.languageAutocomplete = ->
  return false if !$("[data-provide=typeahead]").length

  projectLanguages = $("[data-provide=typeahead]").data "source"

  $("[data-provide=typeahead]").typeahead
    name: $(this).attr "name"
    local: projectLanguages

jQuery ->
  $("a[rel=popover]").popover()
  $(".tooltip").tooltip()
  $("[rel=tooltip]").tooltip()

  $('#presents a:first').tab('show')

  $("#presents a").click (e) ->
    e.preventDefault()
    $(this).tab "show"

    languageAutocomplete()

$(document).on 'ready page:load', ->
  Emojify.replace '.js-emoji'

window.languageAutocomplete = ->
  return false if !$("[data-provide=typeahead]").length

  projectLanguages = $("[data-provide=typeahead]").data "source"

  $("[data-provide=typeahead]").typeahead
    name: $(this).attr "name"
    local: projectLanguages

jQuery.timeago.settings.allowFuture = true;

jQuery ->
  $("a[rel=popover]").popover()
  $(".tooltip").tooltip()
  $("[rel=tooltip]").tooltip()

  $('#presents a:first').tab('show')

  $("#presents a").click (e) ->
    e.preventDefault()
    $(this).tab "show"

    languageAutocomplete()

$(document).on 'ready page:load', ->
  Emojify.replace '.js-emoji'

Allow future dates in timeago

Allow future dates in timeago

Although not something that can happen in normal application usage
(without something going a bit wrong) this is a bit of an issue if you
have seeded the database with future PRs. This change of setting
resolves this issue.


'use strict'
Hapi = require 'hapi'
Boom = require 'boom'
BadRequest = Boom.badRequest
join = require('path').join

class Server

  constructor: ->
    @server = new Hapi.Server()
    @server.connection(port: 4555)
    @_names()

  _names: ->
    @server.route
      method: 'GET'
      path: '/names'
      handler: (req, reply)=>
        return reply(BadRequest('Server Has not been started!')) unless @snippetNames
        reply(names: @snippetNames)

  ###
  The required path is relative to this module...
  ###
  _configure: (context, path)->
    @requiredFile = context.require(path)
    console.log 'file', path
    console.log 'file', @requiredFile
    @snippetNames = Object.keys(@requiredFile)
    @_setupRoutes()

  _setupRoutes: ->
    @server.route
      method: ['PUT', 'POST', 'GET']
      path: '/snippet/{name}'
      handler: (req, reply)=>
        snippet = @requiredFile[req.params.name]
        return reply(BadRequest('Snippet Not Found!')) unless snippet
        snippet(req, reply)

  start: (context, path, cb)->
    throw Error('No Path Given!') unless path
    @_configure(context, path)
    @server.start (err)->
      cb(err) if cb

module.exports = new Server()

'use strict'
Hapi = require 'hapi'
Boom = require 'boom'
BadRequest = Boom.badRequest
join = require('path').join

class Server

  constructor: ->
    @server = new Hapi.Server()
    @server.connection(process.env.PORT or 4545)
    @_names()

  _names: ->
    @server.route
      method: 'GET'
      path: '/names'
      handler: (req, reply)=>
        return reply(BadRequest('Server Has not been started!')) unless @snippetNames
        reply(names: @snippetNames)

  ###
  The required path is relative to this module...
  ###
  _configure: (context, path)->
    @requiredFile = context.require(path)
    console.log 'file', path
    console.log 'file', @requiredFile
    @snippetNames = Object.keys(@requiredFile)
    @_setupRoutes()

  _setupRoutes: ->
    @server.route
      method: ['PUT', 'POST', 'GET']
      path: '/snippet/{name}'
      handler: (req, reply)=>
        snippet = @requiredFile[req.params.name]
        return reply(BadRequest('Snippet Not Found!')) unless snippet
        snippet(req, reply)

  start: (context, path, cb)->
    throw Error('No Path Given!') unless path
    @_configure(context, path)
    @server.start (err)->
      cb(err) if cb

module.exports = new Server()

Use the deis specified port if it exists.


#= require ./validators

class Batman.ExclusionValidator extends Batman.Validator
  @triggers 'exlusionIn'

  constructor: (options) ->
    @acceptableValues = options.exlusionIn
    super

  validateEach: (errors, record, key, callback) ->
    value = record.get(key)

    for acceptableValue in @acceptableValues
      if acceptableValue == value
        errors.add key, @format(key, 'included_in_list')
        return callback()

    callback()

Batman.Validators.push Batman.ExclusionValidator

#= require ./validators

class Batman.ExclusionValidator extends Batman.Validator
  @triggers 'exlusionIn'

  constructor: (options) ->
    @unacceptableValues = options.exlusionIn
    super

  validateEach: (errors, record, key, callback) ->
    value = record.get(key)

    for unacceptableValue in @unacceptableValues
      if unacceptableValue == value
        errors.add key, @format(key, 'included_in_list')
        return callback()

    callback()

Batman.Validators.push Batman.ExclusionValidator

Rename variables for readability and to avoid confusion


'.platform-linux atom-text-editor.ide-haskell-repl, .platform-win32 atom-text-editor.ide-haskell-repl':
  'shift-enter': 'ide-haskell-repl:exec-command'
  'shift-up': 'ide-haskell-repl:history-back'
  'shift-down': 'ide-haskell-repl:history-forward'
  'ctrl-shift-r': 'ide-haskell-repl:ghci-reload'

'.platform-darwin atom-text-editor.ide-haskell-repl':
  'cmd-enter': 'ide-haskell-repl:exec-command'
  'shift-up': 'ide-haskell-repl:history-back'
  'shift-down': 'ide-haskell-repl:history-forward'
  'ctrl-shift-r': 'ide-haskell-repl:ghci-reload'

'.platform-linux atom-text-editor.ide-haskell-repl':
  'shift-enter': 'ide-haskell-repl:exec-command'
  'shift-up': 'ide-haskell-repl:history-back'
  'shift-down': 'ide-haskell-repl:history-forward'
  'ctrl-shift-r': 'ide-haskell-repl:ghci-reload'

'.platform-win32 atom-text-editor.ide-haskell-repl':
  'shift-enter': 'ide-haskell-repl:exec-command'
  'shift-up': 'ide-haskell-repl:history-back'
  'shift-down': 'ide-haskell-repl:history-forward'
  'ctrl-shift-r': 'ide-haskell-repl:ghci-reload'

'.platform-darwin atom-text-editor.ide-haskell-repl':
  'cmd-enter': 'ide-haskell-repl:exec-command'
  'shift-up': 'ide-haskell-repl:history-back'
  'shift-down': 'ide-haskell-repl:history-forward'
  'ctrl-shift-r': 'ide-haskell-repl:ghci-reload'

Work around Atom not displaying keybindings


do ->
  global.Libs or= {}

  global.Libs.JsZip = require("jszip")

  global.Libs.CoffeeScript = require("coffee-script")

  # global.Libs.Canarium = require("canarium")

  global.Libs.GitHubFactory = {
    GitHub: require("github-api")
    apiBase: "http://#{window.location.host}/api"
    create: (args...) ->
      instance = new @GitHub(args...)
      instance.__apiBase = @apiBase if @apiBase?
      return instance
  }

Remove GitHubFactory (replaced with GitHubFetcher)


path = require 'path'

module.exports = (grunt) ->
  {rm} = require('./task-helpers')(grunt)

  grunt.registerTask 'partial-clean', 'Delete some of the build files', ->
    rm grunt.config.get('atom.buildDir')
    rm '/tmp/atom-coffee-cache'
    rm '/tmp/atom-cached-atom-shells'
    rm 'node'

  grunt.registerTask 'clean', 'Delete all the build files', ->
    rm 'node_modules'
    rm 'atom-shell'
    rm path.join(process.env.HOME, '.atom', '.node-gyp')
    grunt.task.run('partial-clean')

path = require 'path'

module.exports = (grunt) ->
  {rm} = require('./task-helpers')(grunt)

  grunt.registerTask 'partial-clean', 'Delete some of the build files', ->
    rm grunt.config.get('atom.buildDir')
    rm '/tmp/atom-coffee-cache'
    rm '/tmp/atom-cached-atom-shells'
    rm 'node'
    rm 'atom-shell'

  grunt.registerTask 'clean', 'Delete all the build files', ->
    rm 'node_modules'
    rm path.join(process.env.HOME, '.atom', '.node-gyp')
    grunt.task.run('partial-clean')

Remove atom-shell during partial-clean task instead of clean task


mod = angular.module 'mothership', [
  'ui.router'
  'ui.bootstrap'
]

mod.config ($stateProvider, $urlRouterProvider) ->

  $urlRouterProvider.otherwise('/playing')

  $stateProvider.state
    name: 'layout'
    abstract: true
    views:
      'layout':
        template: '<m-header></m-header><main ui-view></main>'

  $stateProvider.state
    name: 'playing'
    url: '/playing'
    parent: 'layout'
    template: '<m-playing></m-playing>'

  $stateProvider.state
    name: 'playlist'
    url: '/playlist'
    parent: 'layout'
    template: '<m-playlist></m-playlist>'

  $stateProvider.state
    name: 'browse',
    url: '/browse?page&sort&direction'
    parent: 'layout'
    template: '<m-browse></m-browse>'

  # This needs to be the last state, because of the wildcard url match.
  $stateProvider.state
    name: 'browse.uri'
    url: '/{uri:.*}?page&sort&direction'
    parent: 'layout'
    template: '<m-browse></m-browse>'

mod.run ($rootScope, $state) ->
  $rootScope.$state = $state

mod = angular.module 'mothership', [
  'ui.router'
  'ui.bootstrap'
]

mod.config (
  $stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider
) ->

  $urlRouterProvider.otherwise('/playing')

  valToString = (val) -> if val? then val.toString() else val
  $urlMatcherFactoryProvider.type 'nonURIEncoded',
    encode: valToString
    decode: valToString
    is: -> true

  $stateProvider.state
    name: 'layout'
    abstract: true
    views:
      'layout':
        template: '<m-header></m-header><main ui-view></main>'

  $stateProvider.state
    name: 'playing'
    url: '/playing'
    parent: 'layout'
    template: '<m-playing></m-playing>'

  $stateProvider.state
    name: 'playlist'
    url: '/playlist'
    parent: 'layout'
    template: '<m-playlist></m-playlist>'

  $stateProvider.state
    name: 'browse',
    url: '/browse?page&sort&direction'
    parent: 'layout'
    template: '<m-browse></m-browse>'

  # This needs to be the last state, because of the wildcard url match.
  $stateProvider.state
    name: 'browse.uri'
    url: '/{uri:nonURIEncoded}?page&sort&direction'
    parent: 'layout'
    template: '<m-browse></m-browse>'

mod.run ($rootScope, $state) ->
  $rootScope.$state = $state

:bug: Fix prevent ui router from encoding path names in the URL


React = require 'react'
objectAssign = require 'object-assign'

module.exports = (icons) ->
  React.createClass
    propTypes:
      icon: React.PropTypes.string.isRequired
      size: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number
      ])
      style: React.PropTypes.object

    getDefaultProps: ->
      return {
        size: 24
        style: {}
      }

    render: ->
      styles = {
        fill: "currentcolor"
        verticalAlign: "middle"
         # Use CSS instead of the width attr to support non-pixel units
        width: @props.size
      }

      return (
        <svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" fit
          style={objectAssign(
            styles,
            @props.style
          )}>
            {icons[@props.icon]}
        </svg>
      )

React = require 'react'
objectAssign = require 'object-assign'

module.exports = (icons) ->
  React.createClass
    propTypes:
      icon: React.PropTypes.string.isRequired
      size: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number
      ])
      style: React.PropTypes.object

    getDefaultProps: ->
      return {
        size: 24
        style: {}
      }

    render: ->
      styles = {
        fill: "currentcolor"
        verticalAlign: "middle"
        # Use CSS instead of the width attr to support non-pixel units
        width: @props.size
        # Prevents scaling issue in IE
        height: @props.size
      }

      return (
        <svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" fit
          style={objectAssign(
            styles,
            @props.style
          )}>
            {icons[@props.icon]}
        </svg>
      )

Add `height` to prevent scaling issue in IE


React = require 'react'
CropInitializer = require './initializer'
GenericTask = require '../generic'

module.exports = React.createClass
  displayName: 'CropTask'

  statics:
    getSVGProps: ({workflow, classification, annotation}) ->
      tasks = require '../index'
      [previousCropAnnotation] = classification.annotations.filter (anAnnotation) =>
        taskDescription = workflow.tasks[anAnnotation.task]
        TaskComponent = tasks[taskDescription.type]
        TaskComponent is this and anAnnotation.value? and anAnnotation isnt annotation
      if previousCropAnnotation?
        {x, y, width, height} = previousCropAnnotation.value
        viewBox: "#{x} #{y} #{width} #{height}"

    InsideSubject: CropInitializer

    getDefaultTask: ->
      type: 'crop'
      instruction: 'Drag to select the relevant area.'
      help: ''

    getTaskText: (task) ->
      task.instruction

    getDefaultAnnotation: ->
      value: null

    isAnnotationComplete: (task, annotation) ->
      annotation.value? or not task.required

  getDefaultProps: ->
    task: null
    annotation: null
    onChange: Function.prototype

  render: ->
    <GenericTask question={@props.task.instruction} help={@props.task.help}>
      <p>
        <button type="button" onClick={@handleClear}>Clear current crop</button>
      </p>
    </GenericTask>

  handleClear: ->
    @props.annotation.value = null
    @props.onChange()

React = require 'react'
CropInitializer = require './initializer'
GenericTask = require '../generic'

module.exports = React.createClass
  displayName: 'CropTask'

  statics:
    getSVGProps: ({workflow, classification, annotation}) ->
      tasks = require '../index'
      [previousCropAnnotation] = classification.annotations.filter (anAnnotation) =>
        taskDescription = workflow.tasks[anAnnotation.task]
        TaskComponent = tasks[taskDescription.type]
        TaskComponent is this and anAnnotation.value? and anAnnotation isnt annotation
      if previousCropAnnotation?
        {x, y, width, height} = previousCropAnnotation.value
        viewBox: "#{x} #{y} #{width} #{height}"

    InsideSubject: CropInitializer

    getDefaultTask: ->
      type: 'crop'
      instruction: 'Drag to select the relevant area.'
      help: ''

    getTaskText: (task) ->
      task.instruction

    getDefaultAnnotation: ->
      value: null

    isAnnotationComplete: (task, annotation) ->
      annotation.value? or not task.required

  getDefaultProps: ->
    task: null
    annotation: null
    onChange: Function.prototype

  render: ->
    <GenericTask question={@props.task.instruction} help={@props.task.help}>
      <p>
        <button type="button" disabled={not @props.annotation.value?} onClick={@handleClear}>Clear current crop</button>
      </p>
    </GenericTask>

  handleClear: ->
    @props.annotation.value = null
    @props.onChange()

Disable Clear button when there's no crop


dependencies = [
    'ngRoute',
    'ui.bootstrap',
    'myApp.filters',
    'myApp.services',
    'myApp.controllers',
    'myApp.directives',
    'myApp.common',
    'myApp.routeConfig'
]

app = angular.module('myApp', dependencies)

angular.module('myApp.routeConfig', ['ngRoute']).config ($locationProvider) ->
    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    })

@commonModule = angular.module('myApp.common', [])
@controllersModule = angular.module('myApp.controllers', [])
@servicesModule = angular.module('myApp.services', [])
@modelsModule = angular.module('myApp.models', [])
@directivesModule = angular.module('myApp.directives', [])
@filtersModule = angular.module('myApp.filters', [])

Change indentation to follow coffeelint

Change indentation to follow coffeelint


_ = require 'underscore'
NamespaceStore = require '../../src/flux/stores/namespace-store'

describe "NamespaceStore", ->
  beforeEach ->
    @constructor = NamespaceStore.constructor

  it "should initialize current() using data saved in config", ->
    state =
      "id": "123",
      "email_address":"bengotow@gmail.com",
      "object":"namespace"
      "organization_unit": "label"

    spyOn(atom.config, 'get').andCallFake -> state
    instance = new @constructor
    expect(instance.current().id).toEqual(state['id'])
    expect(instance.current().emailAddress).toEqual(state['email_address'])

  it "should initialize current() to null if data is not present", ->
    spyOn(atom.config, 'get').andCallFake -> null
    instance = new @constructor
    expect(instance.current()).toEqual(null)

  it "should initialize current() to null if data is invalid", ->
    spyOn(atom.config, 'get').andCallFake -> "this isn't an object"
    instance = new @constructor
    expect(instance.current()).toEqual(null)

_ = require 'underscore'
NamespaceStore = require '../../src/flux/stores/namespace-store'

describe "NamespaceStore", ->
  beforeEach ->
    @instance = null
    @constructor = NamespaceStore.constructor

  afterEach ->
    @instance.stopListeningToAll()

  it "should initialize current() using data saved in config", ->
    state =
      "id": "123",
      "email_address":"bengotow@gmail.com",
      "object":"namespace"
      "organization_unit": "label"

    spyOn(atom.config, 'get').andCallFake -> state
    @instance = new @constructor
    expect(@instance.current().id).toEqual(state['id'])
    expect(@instance.current().emailAddress).toEqual(state['email_address'])

  it "should initialize current() to null if data is not present", ->
    spyOn(atom.config, 'get').andCallFake -> null
    @instance = new @constructor
    expect(@instance.current()).toEqual(null)

  it "should initialize current() to null if data is invalid", ->
    spyOn(atom.config, 'get').andCallFake -> "this isn't an object"
    @instance = new @constructor
    expect(@instance.current()).toEqual(null)

Fix memory leak in NamespaceStoreSpec

fix(spec): Fix memory leak in NamespaceStoreSpec


class Lanes.Components.RadioField extends Lanes.React.Component

    mixins: [
        Lanes.Components.Form.FieldMixin
    ]

    renderEdit: ->
        <BS.Col {...@props}>
            <BS.Input
                type="radio"
                checked={@props.checked? || @props.value == @model[@props.name]}
                onChange={@handleChange}
                {...@props} />
        </BS.Col>

class FakeInputEvent
    constructor: (value) ->
        @target = {value}
    isDefaultPrevented: -> false

class Lanes.Components.RadioField extends Lanes.React.Component

    mixins: [
        Lanes.Components.Form.FieldMixin
    ]

    handleRadioChange: (ev) ->
        if ev.target.checked
            @fieldMixinSetValue( new FakeInputEvent(@props.value) )

    renderEdit: (props, handlers) ->
        <BS.FormControl
            {...props}
            {...handlers}
            type="radio"
            checked={@props.checked? || @props.value == @model[@props.name]}
            onChange={@handleRadioChange}
        />

Fix radio input to work with new BS forms


Include RNH and RUN file extensions

Include RNH and RUN file extensions

RUN appears to be one of the file extensions used by the original RUNOFF
program. RNH appears to signify a help file (supposedly "RUNOFF HELP"?).

Sources:

* http://web.mit.edu/Saltzer/www/publications/starring/starring.run
* http://odl.sysworks.biz/disk$vaxdocdec953/decw$book/dy4yaaa7.decw$book
* https://github.com/endlesssoftware/mmk/blob/master/mmk_help.rnh
* https://github.com/LuaDist/unzip/blob/master/vms/unzip_def.rnh


showFrame = document.getElementById("frame")
last_created_text = null

window.remote = Factlink.createFrameProxyObject window.parent,
  ['hide', 'show', 'highlightNewFactlink', 'stopHighlightingFactlink',
    'createdNewFactlink', 'trigger', 'setFeatureToggles'
  ]

local =
    showFactlink: (id, successFn) ->
      url = "/client/facts/#{id}"
      showUrl url, successFn

    prepareNewFactlink: (text, siteUrl, siteTitle, guided, successFn) ->
      url = "/facts/new" +
              "?fact=" + encodeURIComponent(text) +
              "&url=" + encodeURIComponent(siteUrl) +
              "&title=" + encodeURIComponent(siteTitle) +
              "&guided=" + encodeURIComponent(guided)
      showUrl url, successFn
      last_created_text = text

Factlink.listenToWindowMessages null, local

window.highlightLastCreatedFactlink = (id, text) ->
  if last_created_text == text
    remote.highlightNewFactlink(text, id)

showUrl = (url, successFn) ->
  window.onModalReady = ->
    window.onModalReady = -> # nothing
    successFn()

  backbone = showFrame.contentWindow.Backbone
  history = backbone?.history
  if history && backbone.History.started
    # Force (re)loading the url, even if already showing that url
    # If history.fragment is equal to the current url, it doesn't reload,
    # so we reset it to null
    history.fragment = null

    history.navigate url, trigger: true
  else
    showFrame.onload = -> window.onModalReady()
    showFrame.src = url

showFrame.src = '/client/blank'

showFrame = document.getElementById("frame")
last_created_text = null

window.remote = Factlink.createFrameProxyObject window.parent,
  ['hide', 'onModalReady', 'highlightNewFactlink', 'stopHighlightingFactlink',
    'createdNewFactlink', 'trigger', 'setFeatureToggles'
  ]

local =
    showFactlink: (id) ->
      url = "/client/facts/#{id}"
      showUrl url

    prepareNewFactlink: (text, siteUrl, siteTitle, guided) ->
      url = "/facts/new" +
              "?fact=" + encodeURIComponent(text) +
              "&url=" + encodeURIComponent(siteUrl) +
              "&title=" + encodeURIComponent(siteTitle) +
              "&guided=" + encodeURIComponent(guided)
      showUrl url
      last_created_text = text

Factlink.listenToWindowMessages null, local

window.highlightLastCreatedFactlink = (id, text) ->
  if last_created_text == text
    remote.highlightNewFactlink(text, id)

showUrl = (url) ->
  backbone = showFrame.contentWindow.Backbone
  history = backbone?.history
  if history && backbone.History.started
    # Force (re)loading the url, even if already showing that url
    # If history.fragment is equal to the current url, it doesn't reload,
    # so we reset it to null
    history.fragment = null

    history.navigate url, trigger: true
  else
    showFrame.onload = -> window.remote.onModalReady()
    showFrame.src = url

showFrame.src = '/client/blank'

Replace callbacks with an API

Replace callbacks with an API


App.IndexRoute = App.AuthenticatedRoute.extend
  setupController: (controller, model)->
    states   = []
    stateIds = []
    activeState = null

    model.forEach (item)->
      stateId = item.get("id")
      if !activeState? && item.get("joined") == true
        activeState = item
      states.push(stateId)
      states[stateId] = {}

    for stateId in stateIds
      console.log "k:", stateId, states[stateId]

    controller.set("stateIds", stateIds)
    controller.set("states", states)
    controller.set("activeState", activeState)
    @_super(controller, model)

  model: ->
    @store.find("room_user_state")

App.IndexRoute = App.AuthenticatedRoute.extend
  setupController: (controller, model)->
    stateData   = []
    stateIds = []
    activeState = null

    # Loop thru all room states
    #   find the first joined room to load
    #   start pollers for all joined rooms
    model.forEach (item)=>
      stateId = item.get("id")
      stateIds.push(stateId)
      console.log stateId

      # This is to make sure the first active room is loaded
      if item.get("joined") == true
        activeState = item if !activeState?
        poller = new App.Poller()
        poller.store  = @store
        poller.roomId = item.get("room").get("id")
        poller.start(item.get("room").get("id"))
        stateData[stateId] = {"poller": poller}
      else
        stateData[stateId] = {}

    for stateId in stateIds
      console.log "stateId: #{stateId}"

    controller.set("stateIds", stateIds)
    controller.set("stateData", stateData)
    controller.set("activeState", activeState)
    @_super(controller, model)

  model: ->
    @store.find("room_user_state")

  deactivate: ->
    states = controller.get("states")
    console.log states

App.Poller = Em.Object.extend
  start: ()->
    @started = true
    @messages = []
    @beforeMessageId = null
    @timer = setInterval @onPoll.bind(@), 3000

  stop: ->
    clearInterval(@timer)
    @started = false

  onPoll: ->
    console.log("polling now #{@roomId}")
    if @afterMessageId
      console.log "after #{@afterMessageId}"
      url = "/api/messages/#{@roomId}?after=#{@afterMessageId}"
    else
      url = "/api/messages/#{@roomId}"

    $.getJSON url, (response)=>
      Em.$.each response.messages, (index, message)=>
        if (! @store.recordIsLoaded(App.Message, message.id))
          console.log message
          @afterMessageId = message.id

Add Poller class to poll rooms

Add Poller class to poll rooms


class FinderPane extends Pane

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

    super options, data

    vmController = KD.getSingleton 'vmController'
    vmController.fetchDefaultVmName (vmName) =>
      @finder = new NFinderController
        nodeIdPath       : 'path'
        nodeParentIdPath : 'parentPath'
        contextMenu      : yes
        useStorage       : no

      @addSubView @finder.getView()
      @finder.updateVMRoot vmName, "/home/#{KD.nick()}"

      @finder.on 'FileNeedsToBeOpened', (file) =>
        file.fetchContents (err, contents) ->
          appManager = KD.getSingleton 'appManager'
          appManager.tell 'IDE', 'openFile', file, contents

class FinderPane extends Pane

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

    super options, data

    KD.getSingleton('appManager').open 'Finder', (finderApp) =>
      @createFinderController finderApp
      @bindListeners()

  createFinderController: (finderApp) ->
    @finderController = finderApp.create()
    @addSubView @finderController.getView()
    @finderController.reset()

    # this is legacy, should be deleted when we open source koding finder
    @finderController.getView().subViews.first.destroy()

  bindListeners: ->
    @finderController.on 'FileNeedsToBeOpened', (file) =>
      file.fetchContents (err, contents) ->
        appManager = KD.getSingleton 'appManager'
        appManager.tell 'IDE', 'openFile', file, contents

Refactor finder pane to work with multiple vms.


class KDBlockingModalView extends KDModalView
  constructor:->
    super
    $(window).off "keydown.modal"

  putOverlay:()->
    @$overlay = $ "
",
      class : "kdoverlay"
    @$overlay.hide()
    @$overlay.appendTo "body"
    @$overlay.fadeIn 200

  setDomElement:(cssClass)->
    @domElement = $ "

"

  click:(e)->

class KDBlockingModalView extends KDModalView
  constructor:->
    super
    $(window).off "keydown.modal"

  putOverlay:()->
    @$overlay = $ "
",
      class : "kdoverlay"
    @$overlay.hide()
    @$overlay.appendTo "body"
    @$overlay.fadeIn 200

  setDomElement:(cssClass)->
    @domElement = $ """

      """

  click:(e)->

Fix kdblockingmodal, take care hidden objects


React = require 'react'
CollectionsManager = require './manager'
alert = require '../lib/alert'

# Shows an icon to logged-in users that pops up a collections manager
module?.exports = React.createClass
  displayName: 'CollectionsManagerIcon'

  propTypes:
    subject: React.PropTypes.object
    user: React.PropTypes.object

  toggleCollectionsManagerPopup: ->
    alert (resolve) =>
      <div className="content-container">
        <CollectionsManager user={@props.user} project={@props.project} subject={@props.subject} onSuccess={resolve} />
      </div>

  render: ->
    <button
      className="collections-manager-icon"
      title="Collect"
      onClick={@toggleCollectionsManagerPopup}>
      <i className="fa fa-list" />
    </button>

React = require 'react'
CollectionsManager = require './manager'
Dialog = require 'modal-form/dialog'

# Shows an icon to logged-in users that pops up a collections manager
module?.exports = React.createClass
  displayName: 'CollectionsManagerIcon'

  propTypes:
    subject: React.PropTypes.object
    user: React.PropTypes.object

  getInitialState: ->
    open: false

  render: ->
    <button
      className="collections-manager-icon"
      title="Collect"
      onClick={@setState.bind this, {open: true}, null}>
      <i className="fa fa-list" />

      {if @state.open
        <Dialog tag="div">
          <CollectionsManager user={@props.user} project={@props.project} subject={@props.subject} onSuccess={@setState.bind this, {open: false}, null} />
        </Dialog>}
    </button>

Use modal-form dialog for collections manager icon


{ Disposable } = require 'atom'
path = require 'path'
fs = require 'fs'
glob = require 'glob'

module.exports =
class Cleaner extends Disposable
  constructor: (latex) ->
    @latex = latex

  clean: ->
    if !@latex.manager.findMain()
      return false
    rootDir = path.dirname(@latex.mainFile)
    removeGlobs = atom.config.get('atom-latex.file_ext_to_clean')\
      .replace(/\s/,'').split(',')
    for removeGlob in removeGlobs
      glob(removeGlob, cwd: rootDir, (err, files) ->
        if err
          return
        for file in files
          fullPath = path.resolve(rootDir, file)
          fs.unlink(fullPath)
      )
    return true

{ Disposable } = require 'atom'
path = require 'path'
fs = require 'fs'
glob = require 'glob'

module.exports =
class Cleaner extends Disposable
  constructor: (latex) ->
    @latex = latex

  clean: ->
    if !@latex.manager.findMain()
      return false
    rootDir = path.dirname(@latex.mainFile)
    FileExts = atom.config.get('atom-latex.file_ext_to_clean')\
      .replace(/\*\./g,'').replace(/\,\s/g,'|')
    glob("**/*.*(#{FileExts})", cwd: rootDir, (err, files) ->
      if err
        console.log err
        return
      for file in files
        fullPath = path.resolve(rootDir, file)
        fs.unlink(fullPath,(e) ->
          console.log e if e?)
    )
    return true

Clean files in project sub directories as well


class AceApplicationTabView extends ApplicationTabView

  removePane_: KDTabView::removePane

  removePane: (pane, shouldDetach) ->
    {aceView} = pane.getOptions()

    return  @removePane_ pane, shouldDetach  unless aceView

    {ace} = aceView
    file  = ace.getData()

    return @removePane_ pane, shouldDetach  unless ace.isContentChanged()

    modal = new KDModalView
      width         : 620
      cssClass      : "modal-with-text"
      title         : "Do you want to save your changes?"
      content       : "
Your changes will be lost if you don't save them.
"
      overlay       : yes
      buttons       :
        "SaveClose" :
          cssClass  : "modal-clean-green"
          title     : "Save and Close"
          callback  : =>
            if file.path.indexOf("localfile:") is 0
              file.once "fs.saveAs.finished", => @removePane_ pane
              @willClose = yes
              ace.requestSaveAs()
              modal.destroy()
            else
              ace.requestSave()
              @closePaneAndModal pane, modal
        "DontSave"  :
          cssClass  : "modal-clean-red"
          title     : "Don't Save"
          callback  : =>
            @closePaneAndModal pane, modal
        "Cancel"    :
          cssClass  : "modal-cancel"
          title     : "Cancel"
          callback  : =>
            modal.destroy()

  closePaneAndModal: (pane, modal) ->
    @removePane_ pane
    modal.destroy()

class AceApplicationTabView extends ApplicationTabView

  removePane_: KDTabView::removePane

  removePane: (pane, shouldDetach, quiet = no) ->
    {aceView} = pane.getOptions()

    return  @removePane_ pane, shouldDetach  if quiet or not aceView

    {ace} = aceView
    file  = ace.getData()

    return @removePane_ pane, shouldDetach  unless ace.isContentChanged()

    modal = new KDModalView
      width         : 620
      cssClass      : "modal-with-text"
      title         : "Do you want to save your changes?"
      content       : "
Your changes will be lost if you don't save them.
"
      overlay       : yes
      buttons       :
        "SaveClose" :
          cssClass  : "modal-clean-green"
          title     : "Save and Close"
          callback  : =>
            if file.path.indexOf("localfile:") is 0
              file.once "fs.saveAs.finished", => @removePane_ pane
              @willClose = yes
              ace.requestSaveAs()
              modal.destroy()
            else
              ace.requestSave()
              @closePaneAndModal pane, modal
        "DontSave"  :
          cssClass  : "modal-clean-red"
          title     : "Don't Save"
          callback  : =>
            @closePaneAndModal pane, modal
        "Cancel"    :
          cssClass  : "modal-cancel"
          title     : "Cancel"
          callback  : =>
            modal.destroy()

  closePaneAndModal: (pane, modal) ->
    @removePane_ pane
    modal.destroy()

Ace: Add `quiet` parameter to `removePane` method


#    BeamWars - A multiplayer in-browser remake of the Mac game of the same name
#    Copyright (C) 2013  Aaron Hill
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see http://www.gnu.org/licenses/.

define([], ->

  class Player

    constructor: (@name, pos) ->
      @positions = []
      @positions.push(pos)
      @current_line = []

    lastPos: ->
      @positions[@positions.length - 1]

    currentLine: ->
      @current_line.slice() # Copy array

    currentLinePos: ->
      @current_line[@current_line.length - 1]

    addToLine: (pos) ->
      @current_line.push(pos)

  Player
)

#    BeamWars - A multiplayer in-browser remake of the Mac game of the same name
#    Copyright (C) 2013  Aaron Hill
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see http://www.gnu.org/licenses/.

define(['fabric'], ->

  class Player

    constructor: (@name, pos) ->
      @positions = []
      @positions.push(pos)
      @current_line = new fabric.Polyline([], {
        stroke: 'black',
        stokeWidth: 3,
        fille: 'white'
      })

    lastPos: ->
      @positions[@positions.length - 1]

    currentLine: ->
      @current_line.points.slice() # Copy array

    currentLinePos: ->
      @current_line.points[@current_line.points.length - 1]

    addToLine: (pos) ->
      @current_line.points.push(pos)

  Player
)

Use fabric.js in Player class

Use fabric.js in Player class


{CompositeDisposable} = require 'atom'

module.exports =
class MinimapBookmarksBinding
  constructor: (@minimap) ->
    @subscriptions = new CompositeDisposable
    @editor = @minimap.getTextEditor()

    @subscriptions.add @editor.displayBuffer.onDidCreateMarker (marker) =>
      if marker.matchesProperties(class: 'bookmark')
        @minimap.decorateMarker(marker, type: 'line', class: 'bookmark')

  destroy: ->
    @subscriptions.dispose()

{CompositeDisposable} = require 'atom'

module.exports =
class MinimapBookmarksBinding
  constructor: (@minimap) ->
    @subscriptions = new CompositeDisposable
    @editor = @minimap.getTextEditor()
    @decorationsByMarkerId = {}
    @decorationSubscriptionsByMarkerId = {}

    @subscriptions.add @editor.displayBuffer.onDidCreateMarker (marker) =>
      if marker.matchesProperties(class: 'bookmark')
        @handleMarker(marker)

    @editor.displayBuffer.findMarkers(class: 'bookmark').forEach (marker) =>
      @handleMarker(marker)

  handleMarker: (marker) ->
    {id} = marker
    decoration = @minimap.decorateMarker(marker, type: 'line', class: 'bookmark')
    @decorationsByMarkerId[id] = decoration
    @decorationSubscriptionsByMarkerId[id] = decoration.onDidDestroy =>
      @decorationSubscriptionsByMarkerId[id].dispose()

      delete @decorationsByMarkerId[id]
      delete @decorationSubscriptionsByMarkerId[id]

  destroy: ->
    for id,decoration of @decorationsByMarkerId
      @decorationSubscriptionsByMarkerId[id].dispose()
      decoration.destroy()

      delete @decorationsByMarkerId[id]
      delete @decorationSubscriptionsByMarkerId[id]

    @subscriptions.dispose()

Implement retrieving existing markers and destroying decorations along binding


request = require 'request'
should = require 'should'

startApp = require './start_app'
base = require './base'
options = require './options'

describe 'Basic Things', ->
  before (done) ->
    startApp done

  it 'should return version information', (done)->
    request (base '/'), options, (e,r,b)->
      r.statusCode.should.be.equal 200
      b.should.have.property 'version', require('../package').version
      done()

  it 'should send a JSON response on 404', (done)->
    request (base '/' + 'not-an-existent-route1234'), options, (e,r,b)->
      r.statusCode.should.be.equal 404
      r.headers['content-type'].should.be.equal 'application/json'
      b.error.should.be.equal '/not-an-existent-rout1234 was not found'
      done()

request = require 'request'
should = require 'should'

startApp = require './start_app'
base = require './base'
options = require './options'

describe 'Basic Things', ->
  before (done) ->
    startApp done

  it 'should return version information', (done)->
    request (base '/'), options, (e,r,b)->
      r.statusCode.should.be.equal 200
      b.should.have.property 'version', require('../package').version
      done()

  it 'should send a JSON response on 404', (done)->
    request (base '/' + 'not-an-existent-route1234'), options, (e,r,b)->
      r.statusCode.should.be.equal 404
      r.headers['content-type'].should.startWith 'application/json'
      b.error.should.be.equal '/not-an-existent-route1234 was not found'
      done()

Test should account for possible charset


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

StandardIndicatorator = require('../indicatorators/standard_indicatorator')

GETTERS =
  gdoc: require('../getters/gdoc')
  cartodb: require('../getters/cartodb')

FORMATTERS =
  gdoc = require('../formatters/gdoc')

module.exports = class Indicator
  constructor: (attributes) ->
    _.extend(@, attributes)

  query: ->
    @getData().then( (data) =>
      formattedData = @formatData(data)
      StandardIndicatorator.applyRanges(formattedData, @range)
    )

  getData: ->
    Getter = GETTERS[@source]
    if Getter?
      getter = new Getter(@)
      getter.fetch()
    else
      throw new Error("No known getter for source '#{@source}'")

  formatData: (data) ->
    formatter = FORMATTERS[@source]
    if formatter?
      formatter(data)
    else
      throw new Error("No known formatter for source '#{@source}'")

  @find: (id) ->
    deferred = Q.defer()

    Q.nsend(
      fs, 'readFile', './definitions/indicators.json'
    ).then( (definitionsJSON) ->

      definitions = JSON.parse(definitionsJSON)
      indicator = new Indicator(
        _.findWhere(definitions, id: id)
      )

      deferred.resolve(indicator)
    ).fail(
      deferred.reject
    )

    return deferred.promise

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

StandardIndicatorator = require('../indicatorators/standard_indicatorator')

GETTERS =
  gdoc: require('../getters/gdoc')
  cartodb: require('../getters/cartodb')

FORMATTERS =
  gdoc: require('../formatters/gdoc')
  cartodb: require('../formatters/cartodb')

module.exports = class Indicator
  constructor: (attributes) ->
    _.extend(@, attributes)

  query: ->
    @getData().then( (data) =>
      formattedData = @formatData(data)
      StandardIndicatorator.applyRanges(formattedData, @range)
    )

  getData: ->
    Getter = GETTERS[@source]
    if Getter?
      getter = new Getter(@)
      getter.fetch()
    else
      throw new Error("No known getter for source '#{@source}'")

  formatData: (data) ->
    formatter = FORMATTERS[@source]
    if formatter?
      formatter(data)
    else
      throw new Error("No known formatter for source '#{@source}'")

  @find: (id) ->
    deferred = Q.defer()

    Q.nsend(
      fs, 'readFile', './definitions/indicators.json'
    ).then( (definitionsJSON) ->

      definitions = JSON.parse(definitionsJSON)
      indicator = new Indicator(
        _.findWhere(definitions, id: id)
      )

      deferred.resolve(indicator)
    ).fail(
      deferred.reject
    )

    return deferred.promise

Make CartoDB formatter available for Indicator formatting


class KeypathObserver
  constructor: (@view, @model, @keypath, @callback) ->
    @interfaces = (k for k, v of @view.adapters)
    @objectPath = []
    @tokens = Rivets.KeypathParser.parse @keypath, @interfaces, @view.config.rootInterface
    @root = @tokens.shift()
    @key = @tokens.pop()
    @target = @realize()

  update: =>
    unless (next = @realize()) is @target
      @callback @target = next

  realize: =>
    current = @view.adapters[@root.interface].read @view.models, @root.path

    for token, index in @tokens
      next = @view.adapters[token.interface].read current, token.path

      if @objectPath[index]?
        if next isnt @objectPath[index]
          @view.adapters[token.interface].unsubscribe current, token.path, @update
          @view.adapters[token.interface].subscribe next, token.path, @update
      else
        @view.adapters[token.interface].subscribe current, token.path, @update

      current = next

    current

class KeypathObserver
  constructor: (@view, @model, @keypath, @callback) ->
    @interfaces = (k for k, v of @view.adapters)
    @objectPath = []
    @tokens = Rivets.KeypathParser.parse @keypath, @interfaces, @view.config.rootInterface
    @root = @tokens.shift()
    @key = @tokens.pop()
    @target = @realize()

  update: =>
    unless (next = @realize()) is @target
      @callback @target = next

  realize: =>
    current = @view.adapters[@root.interface].read @view.models, @root.path

    for token, index in @tokens
      if @objectPath[index]?
        if current isnt prev = @objectPath[index]
          @view.adapters[token.interface].unsubscribe prev, token.path, @update
          @view.adapters[token.interface].subscribe current, token.path, @update
          @objectPath[index] = current
      else
        @view.adapters[token.interface].subscribe current, token.path, @update
        @objectPath[index] = current

      current = @view.adapters[token.interface].read current, token.path

    current

Make sure that we properly unsubscribe from any outdated portions of a keypath.


Yossarian.Track = DS.Model.extend
  name: DS.attr 'string'

  recordings: DS.hasMany 'recording'

Add mising relation in Track

Add mising relation in Track


$       = require 'jquery'
globals = require 'globals'

module.exports = shortenUrl = (longUrl, callback) ->

  { apiKey } = globals.config.google

  apiUrl = "https://www.googleapis.com/urlshortener/v1/url?key=#{apiKey}"

  request = $.ajax
    url         : apiUrl
    type        : 'POST'
    contentType : 'application/json'
    data        : JSON.stringify { longUrl }
    dataType    : 'json'
    timeout     : 4000

  request.done (data) ->
    callback data?.id or longUrl, data

  request.error ({ status, statusText, responseText }) ->
    console.error 'URL shortener error', status, statusText, responseText
    callback longUrl

$       = require 'jquery'
globals = require 'globals'

module.exports = shortenUrl = (longUrl, callback) ->

  { apiKey } = globals.config.google

  apiUrl = "https://www.googleapis.com/urlshortener/v1/url?key=#{apiKey}"

  request = $.ajax
    url         : apiUrl
    type        : 'POST'
    contentType : 'application/json'
    data        : JSON.stringify { longUrl }
    dataType    : 'json'
    timeout     : 4000

  request.done (data) ->
    callback data?.id or longUrl, data

  request.fail ({ status, statusText, responseText }) ->
    console.error 'URL shortener error', status, statusText, responseText
    callback longUrl

Fix jQuery promise failure handler API reference

Signed-off-by: Sonmez Kartal <d2d15c3d37396a5f2a09f8b42cf5f27d43a3fbde@koding.com>


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

module.exports = React.createClass
  displayName: 'Icon'
  propTypes:
    type: React.PropTypes.string.isRequired
    spin: React.PropTypes.bool
    className: React.PropTypes.string
    tooltip: React.PropTypes.oneOf([
      React.PropTypes.string, React.PropTypes.element
    ])
    tooltipProps: React.PropTypes.object
    onNavbar: React.PropTypes.bool

  componentWillMount: ->
    uniqueId = _.uniqueId('icon-tooltip-')
    @setState({uniqueId: uniqueId})

  getDefaultProps: ->
    tooltipProps:
      placement: 'bottom',
      trigger: 'click'

  render: ->
    classNames = classnames('tutor-icon', 'fa', "fa-#{@props.type}", @props.className, {
      'fa-spin': @props.spin
      'clickable': @props.tooltip and @props.tooltipProps.trigger is 'click'
    })

    icon = <i {...@props} className={classNames} />

    if @props.tooltip
      classNames =
      tooltip = <BS.Tooltip id={@state.uniqueId}
        className={classnames({'on-navbar': @props.onNavbar})}
        >{@props.tooltip}</BS.Tooltip>
      <BS.OverlayTrigger {...@props.tooltipProps} overlay={tooltip}>{icon}</BS.OverlayTrigger>
    else
      icon

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

module.exports = React.createClass
  displayName: 'Icon'
  propTypes:
    type: React.PropTypes.string.isRequired
    spin: React.PropTypes.bool
    className: React.PropTypes.string
    tooltip: React.PropTypes.oneOfType([
      React.PropTypes.string, React.PropTypes.element
    ])
    tooltipProps: React.PropTypes.object
    onNavbar: React.PropTypes.bool

  componentWillMount: ->
    uniqueId = _.uniqueId('icon-tooltip-')
    @setState({uniqueId: uniqueId})

  getDefaultProps: ->
    tooltipProps:
      placement: 'bottom',
      trigger: 'click'

  render: ->
    classNames = classnames('tutor-icon', 'fa', "fa-#{@props.type}", @props.className, {
      'fa-spin': @props.spin
      'clickable': @props.tooltip and @props.tooltipProps.trigger is 'click'
    })

    icon = <i {...@props} className={classNames} />

    if @props.tooltip
      classNames =
      tooltip = <BS.Tooltip id={@state.uniqueId}
        className={classnames({'on-navbar': @props.onNavbar})}
        >{@props.tooltip}</BS.Tooltip>
      <BS.OverlayTrigger {...@props.tooltipProps} overlay={tooltip}>{icon}</BS.OverlayTrigger>
    else
      icon

Fix propType to be correct "oneOfType"

Fix propType to be correct "oneOfType"


@lobbyQueue = new Meteor.Collection "lobbyQueue"

Meteor.startup ->
  lobbyQueue.remove({})

@cancelFindServer = (lobbyId)->
  console.log "canceling server search: "+lobbyId
  lobbyQueue.remove
    lobby: lobbyId

@startFindServer = (lobbyId)->
  console.log "finding server for "+lobbyId
  lobbyQueue.insert
    lobby: lobbyId
    started: new Date().getTime()
  lobbies.update {_id: lobbyId}, {$set: {status: 1}}

Set status to 1 when queuing

Set status to 1 when queuing


ProjectManager = require '../lib/project-manager'
{WorkspaceView} = require 'atom'
fs = require 'fs'

describe "ProjectManager", ->
  activationPromise: null

  describe "Toggle Project Manager", ->
    beforeEach ->
      atom.workspaceView = new WorkspaceView
      activationPromise = atom.packages.activatePackage('project-manager')

    it "Shows the Project Viewer", ->
      expect(atom.workspaceView.find('.project-manager')).not.toExist()
      atom.workspaceView.trigger 'project-manager:toggle'
      expect(atom.workspaceView.find('.project-manager')).toExist()

  describe "Initiating Project Manager", ->
    beforeEach ->
      activationPromise = atom.packages.activatePackage('project-manager')

    it "Makes sure projects.cson exists", ->
      options =
        encoding: 'utf-8'
      fs.readFile ProjectManager.file(), options, (err, data) ->
        expect(err).toBe null

    it "getCurrentPath existential operator issue is fixed", ->
      projects = test: paths: [atom.project.getPath()]
      result = ProjectManager.getCurrentProject projects
      expect(result).not.toBe false
      projects = test: {}
      result = ProjectManager.getCurrentProject projects
      expect(result).toBe false

Add test for getCurrentPath bug

Add test for getCurrentPath bug


msgpack = require 'msgpack'
r = require('redis').createClient detect_buffers: true

r.keys '*', (err, all_keys) ->
  throw err if err
  keys = []
  for key in all_keys
    parts = key.split ':'
    continue if (parts.length == 1) || (parts[0] == 'lock')
    keys.push key
  count = keys.length
  for key in keys
    do (key) ->
      r.get key, (err, val) ->
        throw err if err
        object = JSON.parse val
        buf = msgpack.pack object
        r.set key, buf, (err) ->
          throw err if err
          unless --count
            console.log "Packed #{keys.length} keys"
            r.end()

msgpack = require 'msgpack'
r = require('redis').createClient 6379, 'localhost', detect_buffers: true

r.keys '*', (err, all_keys) ->
  throw err if err
  keys = []
  for key in all_keys
    parts = key.split ':'
    continue if (parts.length == 1) || (parts[0] == 'lock')
    keys.push key
  count = keys.length
  for key in keys
    do (key) ->
      r.get key, (err, val) ->
        throw err if err
        object = JSON.parse val
        buf = msgpack.pack object
        r.set key, buf, (err) ->
          throw err if err
          unless --count
            console.log "Packed #{keys.length} keys"
            r.end()

Fix bug in new script

Fix bug in new script


Config = require '../config'
CustomerXmlImport = require '../lib/customerxmlimport'

# Increase timeout
jasmine.getEnv().defaultTimeoutInterval = 10000

describe 'process', ->
  beforeEach ->
    @import = new CustomerXmlImport Config

  it 'one customer', (done) ->
    rawXml = '
<Customer>
  <CustomerNr>1234</CustomerNr>
  <Street>Foo 1</Street>
  <Group>B2B</Group>
  <Employees>
    <Employee>
      <employeeNr>2</employeeNr>
      <email>some.one+27@example.com</email>
      <gender>Mrs.</gender>
      <firstname>Some</firstname>
      <lastname>One</lastname>
    </Employee>
  </Employees>
</Customer>'
    @import.run rawXml, (msg) =>
      expect(msg.status).toBe false
      expect(msg.message).toBe 'Update of customer isnt implemented yet!'
      done()

_ = require('underscore')._
Config = require '../config'
CustomerXmlImport = require '../lib/customerxmlimport'

# Increase timeout
jasmine.getEnv().defaultTimeoutInterval = 10000

describe 'process', ->
  beforeEach ->
    @import = new CustomerXmlImport Config

  it 'one existing customer', (done) ->
    rawXml = '
<Customer>
  <CustomerNr>1234</CustomerNr>
  <Street>Foo 1</Street>
  <Group>B2B</Group>
  <Employees>
    <Employee>
      <employeeNr>2</employeeNr>
      <email>some.one+27@example.com</email>
      <gender>Mrs.</gender>
      <firstname>Some</firstname>
      <lastname>One</lastname>
    </Employee>
  </Employees>
</Customer>'
    @import.run rawXml, (msg) =>
      expect(msg.status).toBe false
      expect(msg.message).toBe 'Update of customer isnt implemented yet!'
      done()

  it 'one new customer', (done) ->
    unique = new Date().getTime()
    rawXml = "
<Customer>
  <CustomerNr>5678</CustomerNr>
  <Street>Foo 1</Street>
  <Group>B2C</Group>
  <Employees>
    <Employee>
      <employeeNr>1</employeeNr>
      <email>some.one.else+#{unique}@example.com</email>
      <gender>Mrs.</gender>
      <firstname>Some</firstname>
      <lastname>One</lastname>
    </Employee>
  </Employees>
</Customer>"
    @import.run rawXml, (result) =>
      console.log result unless result.status
      expect(result.status).toBe true
      expect(_.size(result.message)).toBe 2
      expect(result.message['Customer has no paymentInfo.']).toBe 1
      expect(result.message['Customer has no group.']).toBe 1
      done()

Add integration test for new customer.

Add integration test for new customer.


counterpart = require 'counterpart'
React = require 'react'
{Markdown} = (require 'markdownz').default

counterpart.registerTranslations 'en',
  glossary:
    content: '''
      ## Glossary
      A collection of definitions for terms used across the Zooniverse. The terms are split into three different groups; [General Terms](#general-terms); [People](#people) and [Project-Specific Terms](#project-specific-terms).

      ###GENERAL TERMS

      ###PEOPLE

      ###PROJECT-SPECIFIC TERMS

    '''

module.exports = React.createClass
  displayName: 'Glossary'

  render: ->

      <Markdown>{counterpart "glossary.content"}</Markdown>

counterpart = require 'counterpart'
React = require 'react'
{Markdown} = (require 'markdownz').default

counterpart.registerTranslations 'en',
  policiesPage:
    content: '''
      ## Glossary
      A collection of definitions for terms used across the Zooniverse. The terms are split into three different groups:

      ## General Terms

      ## People

      ## Project-Specific Terms

    '''

module.exports = React.createClass
  displayName: 'Glossary'

  render: ->
    <div className="secondary-page centered-grid">
      <Markdown>{counterpart "policiesPage.content"}</Markdown>
    </div>

Revert to non TOC markdown

Revert to non TOC markdown


React = require 'react'
BS = require 'react-bootstrap'
Router = require 'react-router'

{CCDashboardStore, CCDashboardActions} = require '../../flux/cc-dashboard'
LoadableItem = require '../loadable-item'
CCDashboard = require './dashboard'

BookLinks = require './book-links'

classnames = require 'classnames'

DashboardShell = React.createClass
  contextTypes:
    router: React.PropTypes.func

  render: ->
    {courseId} = @context.router.getCurrentParams()

      <BookLinks courseId={courseId} />

        Class Performance
        <Router.Link className='btn btn-default pull-right' to='viewScores' params={{courseId}}>
          View Detailed Scores
        </Router.Link>

      <LoadableItem
        store={CCDashboardStore}
        actions={CCDashboardActions}
        id={courseId}
        renderItem={-> <CCDashboard key={courseId} id={courseId} />}
      />

module.exports = DashboardShell

React = require 'react'
BS = require 'react-bootstrap'
Router = require 'react-router'

{CCDashboardStore, CCDashboardActions} = require '../../flux/cc-dashboard'
LoadableItem = require '../loadable-item'
CCDashboard = require './dashboard'

BookLinks = require './book-links'

classnames = require 'classnames'

DashboardShell = React.createClass
  contextTypes:
    router: React.PropTypes.func

  render: ->
    {courseId} = @context.router.getCurrentParams()

      <BookLinks courseId={courseId} />

        Class Dashboard
        <Router.Link className='btn btn-default pull-right' to='viewScores' params={{courseId}}>
          View Detailed Scores
        </Router.Link>

      <LoadableItem
        store={CCDashboardStore}
        actions={CCDashboardActions}
        id={courseId}
        renderItem={-> <CCDashboard key={courseId} id={courseId} />}
      />

module.exports = DashboardShell

Update title to be "Class Dashboard"

Update title to be "Class Dashboard"


#= require vendor/modernizr
#= require jquery
#= require jquery_ujs
#= require foundation/foundation
#= require foundation
#= require rails.validations
#= require rails.validations.simple_form
#= require rails.validations.simple_form.fix
#= require turbolinks
#= require nprogress
#= require nprogress-turbolinks
#= require jquery.autosize
#= require globals/_functions
#= require tools/mapbox
#= require tools/nprogress

$(document).on 'ready page:load page:restore', ->
  $(document).foundation
  $('.autosize').autosize()

#= require vendor/modernizr
#= require jquery
#= require jquery_ujs
#= require foundation/foundation
#= require foundation
#= require turbolinks
#= require nprogress
#= require nprogress-turbolinks
#= require rails.validations
#= require rails.validations.simple_form
#= require rails.validations.simple_form.fix
#= require jquery.autosize
#= require globals/_functions
#= require tools/mapbox
#= require tools/nprogress

$(document).on 'ready page:load page:restore', ->
  $(document).foundation
  $('.autosize').autosize()

Move turbolinks up to make client_side_validations working after ajax request


class IDE.FinderContextMenuController extends NFinderContextMenuController

  getFolderMenu: (fileView) ->

    fileData = fileView.getData()

    items =
      Expand                      :
        action                    : "expand"
        separator                 : yes
      Collapse                    :
        action                    : "collapse"
        separator                 : yes
      'Make this the top folder'  :
        action                    : 'makeTopFolder'
      'Workspace from here'       :
        action                    : 'createWorkspace'
      'Terminal from here'        :
        action                    : 'createTerminal'
        separator                 : yes
      Delete                      :
        action                    : 'delete'
        separator                 : yes
      Rename                      :
        action                    : 'rename'
      Duplicate                   :
        action                    : 'duplicate'
      Compress                    :
        children                  :
          'as .zip'               :
            action                : 'zip'
          'as .tar.gz'            :
            action                : 'tarball'
      'Set permissions'           :
        separator                 : yes
        children                  :
          customView              : new NSetPermissionsView {}, fileData
      'New file'                  :
        action                    : 'createFile'
      'New folder'                :
        action                    : 'createFolder'
      Refresh                     :
        action                    : 'refresh'

    if fileView.expanded
      delete items.Expand
    else
      delete items.Collapse

    return items

class IDE.FinderContextMenuController extends NFinderContextMenuController

  getFolderMenu: (fileView) ->

    fileData = fileView.getData()

    items =
      Expand                      :
        action                    : "expand"
        separator                 : yes
      Collapse                    :
        action                    : "collapse"
        separator                 : yes
      'Change top folder'         :
        separator                 : yes
        children                  : @getTopFolderItems fileView
      'Make this the top folder'  :
        action                    : 'makeTopFolder'
      'Workspace from here'       :
        action                    : 'createWorkspace'
      'Terminal from here'        :
        action                    : 'createTerminal'
        separator                 : yes
      Delete                      :
        action                    : 'delete'
        separator                 : yes
      Rename                      :
        action                    : 'rename'
      Duplicate                   :
        action                    : 'duplicate'
      Compress                    :
        children                  :
          'as .zip'               :
            action                : 'zip'
          'as .tar.gz'            :
            action                : 'tarball'
      'Set permissions'           :
        separator                 : yes
        children                  :
          customView              : new NSetPermissionsView {}, fileData
      'New file'                  :
        action                    : 'createFile'
      'New folder'                :
        action                    : 'createFolder'
      Refresh                     :
        action                    : 'refresh'

    if fileView.expanded
      delete items.Expand
    else
      delete items.Collapse

    return items

Add `Change Top Folder` context menu action


$ ->
  $(".topbar-wrapper").dropdown()
$ ->
  $(".alert-message").alert()
$ ->
  $(".modal").modal
    show: false
    backdrop: "static"

Make modals not hide when clicking on greyed out background


_ = require 'underscore'
guid = require 'guid'

module.exports =
class WsChannel
  _.extend @prototype, require('event-emitter')

  constructor: (@name) ->
    @clientId = guid.create().toString()
    @socket = new WebSocket('ws://localhost:8080')
    @socket.onopen = =>
      @rawSend 'subscribe', @name, @clientId
      @trigger 'channel:opened'

    @socket.onmessage = (message) =>
      [operation, data] = JSON.parse(message.data)
      @trigger(data...)

  send: (data...) ->
    @rawSend('broadcast', data)

  rawSend: (args...) ->
    @socket.send(JSON.stringify(args))

_ = require 'underscore'
guid = require 'guid'
keytar = require 'keytar'

module.exports =
class WsChannel
  _.extend @prototype, require('event-emitter')

  constructor: (@name) ->
    @clientId = guid.create().toString()
    token = keytar.getPassword('github.com', 'github')
    @socket = new WebSocket("ws://localhost:8080?token=#{token}")
    @socket.onopen = =>
      @rawSend 'subscribe', @name, @clientId
      @trigger 'channel:opened'

    @socket.onmessage = (message) =>
      [operation, data] = JSON.parse(message.data)
      @trigger(data...)

  send: (data...) ->
    @rawSend('broadcast', data)

  rawSend: (args...) ->
    @socket.send(JSON.stringify(args))

Send OAuth token as web socket query param


'use strict'

app.directive 'volumeEditLinksForm', [
  'pageService',
  (page) ->
    restrict: 'E',
    templateUrl: 'volume/editLinks.html',
    link: ($scope) ->
      volume = $scope.volume
      form = $scope.volumeEditLinksForm

      form.data = _.map volume.links, (ref) ->
        head: ref.head
        url: ref.url

      blank = () ->
        form.data.push
          head: ''
          url: ''
      blank()

      form.change = () -> blank() unless form.data[form.data.length-1].url == ''

      form.remove = (ref) ->
        ref.removed = true
        ref.head = ''
        ref.url = ''
        form.$setDirty()

      form.save = () ->
        page.messages.clear(form)
        data = _.filter form.data, (ref) -> !ref.removed
        volume.save({links: data}).then(() ->
            form.validator.server {}
            form.data = data.filter (ref) -> ref.head != '' || ref.url != ''
            blank()

            page.messages.add
              type: 'green'
              body: page.constants.message('volume.edit.success')
              owner: form

            form.$setPristine()
          , (res) ->
            form.validator.server res
          )

      return
]

'use strict'

app.directive 'volumeEditLinksForm', [
  'pageService',
  (page) ->
    restrict: 'E',
    templateUrl: 'volume/editLinks.html',
    link: ($scope) ->
      volume = $scope.volume
      form = $scope.volumeEditLinksForm

      form.data = _.map volume.links, (ref) ->
        head: ref.head
        url: ref.url

      blank = () ->
        form.data.push
          head: ''
          url: ''
      blank()

      form.change = () -> blank() unless form.data[form.data.length-1].url == ''

      form.remove = (ref) ->
        ref.removed = true
        ref.head = ''
        ref.url = ''
        form.$setDirty()

      form.save = () ->
        page.messages.clear(form)
        data = _.filter form.data, (ref) -> !ref.removed
        form.$setSubmitted()
        volume.save({links: data}).then(() ->
            form.validator.server {}
            form.data = data.filter (ref) -> ref.head != '' || ref.url != ''
            blank()

            page.messages.add
              type: 'green'
              body: page.constants.message('volume.edit.success')
              owner: form

            form.$setPristine()
            form.$setUnsubmitted()
          , (res) ->
            form.validator.server res
          )

      return
]

Add a submitted/unsubmitted thing to editing links.


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

LearningGuide  = require '../../flux/learning-guide'
PracticeButton = require './practice-button'
WeakerSections = require './weaker-sections'

WeakerPanel = React.createClass
  propTypes:
    courseId:            React.PropTypes.string.isRequired
    sections:            React.PropTypes.array.isRequired
    weakerTitle:         React.PropTypes.string.isRequired
    weakerExplanation:   React.PropTypes.element.isRequired
    weakerEmptyMessage:  React.PropTypes.string.isRequired
    onPractice:          React.PropTypes.func
    sectionCount:        React.PropTypes.number
    sampleSizeThreshold: React.PropTypes.number.isRequired

  render: ->
    # Do not render if we have no sections
    return null if @props.sections.length is 0

        {@props.weakerTitle}
        {@props.weakerExplanation}
        {if LearningGuide.Helpers.canDisplayWeakest(@props) # hide practice button when the panel is empty
          <PracticeButton title='Practice All'
            sections=LearningGuide.Helpers.weakestSections(@props.sections)
            courseId={@props.courseId} /> }

      <WeakerSections {...@props} />

module.exports = WeakerPanel

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

LearningGuide  = require '../../flux/learning-guide'
PracticeButton = require './practice-button'
WeakerSections = require './weaker-sections'

WeakerPanel = React.createClass
  propTypes:
    courseId:            React.PropTypes.string.isRequired
    sections:            React.PropTypes.array.isRequired
    weakerTitle:         React.PropTypes.string.isRequired
    weakerExplanation:   React.PropTypes.element.isRequired
    weakerEmptyMessage:  React.PropTypes.string.isRequired
    onPractice:          React.PropTypes.func
    sectionCount:        React.PropTypes.number
    sampleSizeThreshold: React.PropTypes.number.isRequired

  render: ->
    # Do not render if we have no sections
    return null if @props.sections.length is 0

        {@props.weakerTitle}
        {@props.weakerExplanation}
        {if @props.onPractice and LearningGuide.Helpers.canDisplayWeakest(@props)
          <PracticeButton title='Practice All'
            sections=LearningGuide.Helpers.weakestSections(@props.sections)
            courseId={@props.courseId} /> }

      <WeakerSections {...@props} />

module.exports = WeakerPanel

Hide practice button if practice handler isn't provided

Even though the PracticeButton doesn't use the onPractice callback, it's
a good way to determine if practicing sections is allowed.  The prop is
only given for the Student component, not Teacher or TeacherStudent.


try
  keytar = require 'keytar'
catch error
  # Gracefully handle keytar failing to load due to missing library on Linux
  if process.platform is 'linux'
    keytar =
      findPassword: ->
      replacePassword: ->
  else
    throw error

tokenName = 'Atom.io API Token'

module.exports =
  # Get the Atom.io API token from the keychain.
  #
  # callback - A function to call with an error as the first argument and a
  #            string token as the second argument.
  getToken: (callback) ->
    if token = process.env.ATOM_ACCESS_TOKEN
      callback(null, token)
      return

    if token = keytar.findPassword(tokenName)
      callback(null, token)
      return

    callback """
      No Atom.io API token in keychain
      Run `apm login` or set the `ATOM_ACCESS_TOKEN` environment variable.
    """

  # Save the given token to the keychain.
  #
  # token - A string token to save.
  saveToken: (token) ->
    keytar.replacePassword(tokenName, 'atom.io', token)

try
  keytar = require 'keytar'
catch error
  # Gracefully handle keytar failing to load due to missing library on Linux
  if process.platform is 'linux'
    keytar =
      findPassword: ->
      replacePassword: ->
  else
    throw error

tokenName = 'Atom.io API Token'

module.exports =
  # Get the Atom.io API token from the keychain.
  #
  # callback - A function to call with an error as the first argument and a
  #            string token as the second argument.
  getToken: (callback) ->
    if token = keytar.findPassword(tokenName)
      callback(null, token)
      return

    if token = process.env.ATOM_ACCESS_TOKEN
      callback(null, token)
      return

    callback """
      No Atom.io API token in keychain
      Run `apm login` or set the `ATOM_ACCESS_TOKEN` environment variable.
    """

  # Save the given token to the keychain.
  #
  # token - A string token to save.
  saveToken: (token) ->
    keytar.replacePassword(tokenName, 'atom.io', token)

Check the keychain for the token before falling back to ATOM_ACCESS_TOKEN.

Otherwise auth failures get confusing: we’d keep updating the token
stored in the keychain when the real problem was that ATOM_ACCESS_TOKEN
was out of date. See #505.


"use strict"

module.exports =
  title: 'Hytteadmin'
  version: '2.0.0-alpha'
  desc: 'Administrasjon av hytter i Nasjonal Turbase'
  author: 'Hans Kristian Flaatten, Den Norske Turistforening'
  copyright: '© Den Norske Turistforening'

"use strict"

module.exports =
  title: 'Sherpa'
  version: '2.0.0-alpha'
  desc: 'Administrasjon av hytter i Nasjonal Turbase'
  author: 'Hans Kristian Flaatten, Den Norske Turistforening'
  copyright: '© Den Norske Turistforening'

Change site tile to Sherpa

Change site tile to Sherpa


{cloneFragment} = Trix

Trix.registerElement "trix-toolbar",
  defaultCSS: """
    %t {
      white-space: collapse;
    }

    %t .dialog {
      display: none;
    }

    %t .dialog.active {
      display: block;
    }

    %t .dialog input.validate:invalid {
      background-color: #ffdddd;
    }

    %t[native] {
      display: none;
    }
  """

  attachedCallback: ->
    if @innerHTML is ""
      @appendChild(cloneFragment(Trix.config.toolbar.content))

{cloneFragment} = Trix

Trix.registerElement "trix-toolbar",
  defaultCSS: """
    %t {
      white-space: collapse;
    }

    %t .dialog {
      display: none;
    }

    %t .dialog.active {
      display: block;
    }

    %t .dialog input.validate:invalid {
      background-color: #ffdddd;
    }

    %t[native] {
      display: none;
    }
  """

  createdCallback: ->
    if @innerHTML is ""
      @appendChild(cloneFragment(Trix.config.toolbar.content))

Add default content when created to avoid extra DOM manipulation when attached


'menu': [
  {
    'label': 'View'
    'submenu': [
      {
        'label': 'Toggle Git Panel'
        'command': 'github:toggle-git-panel'
      }
    ]
  }
  {
    'label': 'Packages'
    'submenu': [
      {
        'label': 'GitHub',
        'submenu': [
          {
            'label': 'Toggle'
            'command': 'github:toggle-git-panel'
          }
        ]
      }
    ]
  }
]
'context-menu':
  '.github-FilePatchListView-item': [
    {
      'label': 'Open File'
      'command': 'github:open-file'
    }
  ]
  '.github-UnstagedChanges': [
    {
      'label': 'Discard Changes'
      'command': 'github:discard-changes'
    }
  ]
  '.github-FilePatchView': [
    {
      'label': 'Open File'
      'command': 'github:open-file'
    }
  ]

'menu': [
  {
    'label': 'View'
    'submenu': [
      {
        'label': 'Toggle Git Panel'
        'command': 'github:toggle-git-panel'
      }
    ]
  }
  {
    'label': 'Packages'
    'submenu': [
      {
        'label': 'GitHub',
        'submenu': [
          {
            'label': 'Toggle'
            'command': 'github:toggle-git-panel'
          }
        ]
      }
    ]
  }
]
'context-menu':
  '.github-FilePatchListView-item': [
    {
      'label': 'Open File'
      'command': 'github:open-file'
    }
  ]
  '.github-UnstagedChanges': [
    {
      'label': 'Discard Changes'
      'command': 'github:discard-changes'
    }
    {
      'label': 'Stage'
      'command': 'core:confirm'
    }
  ]
  '.github-StagedChanges': [
    {
      'label': 'Unstage'
      'command': 'core:confirm'
    }
  ]
  '.github-MergeConflictPaths': [
    {
      'label': 'Stage'
      'command': 'core:confirm'
    }
  ]
  '.github-FilePatchView': [
    {
      'label': 'Open File'
      'command': 'github:open-file'
    }
  ]

Add context menu items for staging and unstaging in changed files list


_       = require 'lodash'
kd      = require 'kd'
remote  = require('app/remote').getInstance()
globals = require 'globals'

defaults = require './tracking/defaults'

module.exports = class Tracker

  _.assign this, require('./tracking/trackingtypes')

  @track = (action, properties = {}) ->

    return  unless globals.config.logToExternal

    @assignDefaultProperties action, properties
    remote.api.Tracker.track action, properties, kd.noop

  @assignDefaultProperties: (action, properties) ->

    _.defaults properties, defaults.properties[action]

_       = require 'lodash'
kd      = require 'kd'
remote  = require('app/remote').getInstance()
globals = require 'globals'

defaults = require './tracking/defaults'

module.exports = class Tracker

  _.assign this, require('./tracking/trackingtypes')

  @track = (action, properties = {}) ->

    return  unless globals.config.sendEventsToSegment

    @assignDefaultProperties action, properties
    remote.api.Tracker.track action, properties, kd.noop

  @assignDefaultProperties: (action, properties) ->

    _.defaults properties, defaults.properties[action]

Fix condition clause of Tracker.track function


{CompositeDisposable} = require 'atom'

module.exports =
  config:
    executablePath:
      type: 'string'
      title: 'PHP Executable Path'
      default: 'php' # Let OS's $PATH handle the rest

  activate: ->
    @regex = '(Parse|Fatal) ' +
            '(?<error>error):(\\s*(?<type>parse|syntax) error,?)?\\s*' +
            '(?<message>(unexpected \'(?<near>[^\']+)\')?.*) ' +
            'in .*? on line (?<line>\\d+)'
    @subscriptions = new CompositeDisposable
    @subscriptions.add atom.config.observe 'linter-php.executablePath',
      (executablePath) =>
        @executablePath = executablePath

  deactivate: ->
    @subscriptions.dispose()

  provideLinter: ->
    helpers = require('atom-linter')
    provider =
      grammarScopes: ['text.html.php', 'source.php']
      scope: 'file'
      lintOnFly: false
      lint: (textEditor) =>
        filePath = textEditor.getPath()
        command = @executablePath
        parameters = []
        parameters.push('--syntax-check')
        parameters.push('--no-php-ini')
        parameters.push('--define', 'display_errors=On')
        parameters.push('--define', 'log_errors=Off')
        parameters.push('--file', filePath)
        return helpers.exec(command, parameters).then (output) =>
          messages = helpers.parse(output, @regex, {filePath: filePath})
          return messages

{CompositeDisposable} = require 'atom'

module.exports =
  config:
    executablePath:
      type: 'string'
      title: 'PHP Executable Path'
      default: 'php' # Let OS's $PATH handle the rest

  activate: ->
    @regex = '(Parse|Fatal) ' +
            '(?<error>error):(\\s*(?<type>parse|syntax) error,?)?\\s*' +
            '(?<message>(unexpected \'(?<near>[^\']+)\')?.*) ' +
            'in .*? on line (?<line>\\d+)'
    @subscriptions = new CompositeDisposable
    @subscriptions.add atom.config.observe 'linter-php.executablePath',
      (executablePath) =>
        @executablePath = executablePath

  deactivate: ->
    @subscriptions.dispose()

  provideLinter: ->
    helpers = require('atom-linter')
    provider =
      grammarScopes: ['text.html.php', 'source.php']
      scope: 'file'
      lintOnFly: true
      lint: (textEditor) =>
        filePath = textEditor.getPath()
        command = @executablePath
        parameters = []
        parameters.push('--syntax-check')
        parameters.push('--no-php-ini')
        parameters.push('--define', 'display_errors=On')
        parameters.push('--define', 'log_errors=Off')
        text = textEditor.getText()
        return helpers.exec(command, parameters, {stdin: text}).then (output) =>
          messages = helpers.parse(output, @regex, {filePath: filePath})
          return messages

Enable linting on the fly

Enable linting on the fly

Note that this represents a slight loss of functionality. With the
update to the new API the file was explicitly specified, which according
to the documentation enables checking for "fatal errors (like undefined
functions)".

Since we are linting on the fly we can't specify a file and thus lose
this functionality.


# Graph-stuff-code
# Generalised way to send an ajax request to load a chart when a
# link is clicked with data-load="graph"

$('body.coders.show, body.repositories.show').ready ->
    $('a[data-load="graph"]').on 'shown.bs.tab', (e) ->
        if !$("#chart").hasClass('google-visualization-atl container')
            $.ajax
                url: $(this).data('graphurl') + '.js'
                type: 'GET'

# Graph-stuff-code
# Generalised way to send an ajax request to load a chart when a
# link is clicked with data-load="graph"

$('body.coders.show, body.repositories.show').ready ->
    $('a[data-load="graph"]').on 'shown.bs.tab', (e) ->
        # Only initialise the chart the first time we click the tab
        # Google_visualr adds those classes when it is initialised so it's safe to
        # filter on those classes
        if !$("#chart").hasClass('google-visualization-atl container')
            $.ajax
                url: $(this).data('graphurl') + '.js'
                type: 'GET'

Add documentation for the if

Add documentation for the if


$ ->
  # $('#rows').on "change", ->
  #   $rows = $(this).val()
  #   console.log $rows

  # $('#columns').on "change", ->
  #   $columns = $(this).val()
  #   console.log $columns

  $('#submit_details').click (e) ->
    e.preventDefault()
    $rows = parseInt($('#rows').val(), 10)
    $columns = parseInt($('#columns').val(), 10)
    layout = ''
    for $rows in [$rows-1..0] by -1
      row = '
'
      layout += row
      layout += Array($columns + 1).join(seatTemplate())
      layout += '
'

    $('#layout').html(layout)

  $('#layout').on 'click', '.seat', (e) ->

    if parseInt($(this).children().val() == 1)
      $(this).children().val(0)
    else
      console.log 'test'
      $(this).children().val(1)

    unless $(this).hasClass('alley')
      $(this).addClass('alley')
    else
      $(this).removeClass('alley')

  seatTemplate = () ->
    '
<input type="hidden" value=1 class="seat_type" />
'

$ ->
  # $('#rows').on "change", ->
  #   $rows = $(this).val()
  #   console.log $rows

  # $('#columns').on "change", ->
  #   $columns = $(this).val()
  #   console.log $columns

  $('#submit_details').click (e) ->
    e.preventDefault()
    $rows = parseInt($('#rows').val(), 10)
    $columns = parseInt($('#columns').val(), 10)
    layout = ''
    for $rows in [$rows-1..0] by -1
      row = '
'
      layout += row
      layout += Array($columns + 1).join(seatTemplate())
      layout += '
'

    $('#layout').html(layout)

  $('#layout').on 'click', '.seat', (e) ->

    # if parseInt($(this).children().val() == 1)
    #   $(this).children().val(0)
    # else
    #   console.log 'test'
    #   $(this).children().val(1)

    unless $(this).hasClass('alley')
      $(this).addClass('alley')
      $(this).children().val(0)
    else
      $(this).removeClass('alley')
      $(this).children().val(1)

  seatTemplate = () ->
    '
<input type="hidden" value=1 class="seat_type" />
'

Create alleys in hall creation

Create alleys in hall creation


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

  initialize: ->
    @zoom = 13

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

  onShow: ->
    if @el.id is ""
      console.warn "No Map Element"
    else
      @location = [@model.get("latitude"), @model.get("longitude")]
      @map = L.map(@el.id, {
        continuousWorld: true
        center: Workbench.provider.center
        minZoom: Workbench.provider.zoomRange.min
        maxZoom: Workbench.provider.zoomRange.max
        crs: Workbench.provider.CRS
      })

      L.tileLayer(Workbench.provider.url, {
          attribution: Workbench.provider.attribution
      }).addTo(@map)

      @map.setView(@location, @zoom)

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

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

  initialize: ->
    @zoom = 13

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

  onShow: ->
    if @el.id is ""
      console.warn "No Map Element"
    else
      @location = [@model.get("latitude"), @model.get("longitude")]
      pMap = polarMap(@el.id, { permalink: false })
      @map = pMap.map
      @map.setView(@location, @zoom)

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

Use PolarMap on sensor page

Use PolarMap on sensor page


class window.SearchCollection extends Backbone.Collection
  constructor: (args...)->
    super(args...)
    @searchFor ''

  emptyState: -> []

  searchFor: (query) ->
    query = $.trim(query)
    return if query == @query
    @query = query
    @_search()

  throttle = (method) -> _.throttle method, 300
  _search: throttle ->
    @jqxhr?.abort()
    if @query == ''
      @reset @emptyState()
      @trigger 'sync'
    else
      @reset []
      @jqxhr = @fetch()

  encodedQuery: -> encodeURIComponent @query

  addNewItem: (compare_field) ->
    return unless @shouldShowNewItem(compare_field)

    @add @getNewItem()
    @trigger 'sync'

  shouldShowNewItem: (compare_field) ->
    @query != '' and not (@query.toLowerCase() in @newItemFields(compare_field))

  newItemFields: (compare_field) -> _.map @pluck(compare_field), (field)-> field.toLowerCase()

  getNewItem: -> console.error "'getNewItem' was not implemented"

class window.SearchCollection extends Backbone.Collection
  constructor: (args...)->
    super(args...)
    @searchFor ''

  emptyState: -> []

  searchFor: (query) ->
    query = $.trim(query)
    return if query == @query
    @query = query
    @_search()

  throttle = (method) -> _.throttle method, 300
  _search: throttle ->
    @jqxhr?.abort()
    if @query == ''
      @reset @emptyState()
      @trigger 'sync'
    else
      @reset []
      @jqxhr = @fetch(reset: true) # because the CollectionUtils do a full reset on add/remove

  encodedQuery: -> encodeURIComponent @query

  addNewItem: (compare_field) ->
    return unless @shouldShowNewItem(compare_field)

    @add @getNewItem()
    @trigger 'sync'

  shouldShowNewItem: (compare_field) ->
    @query != '' and not (@query.toLowerCase() in @newItemFields(compare_field))

  newItemFields: (compare_field) -> _.map @pluck(compare_field), (field)-> field.toLowerCase()

  getNewItem: -> console.error "'getNewItem' was not implemented"

Use reset for better performance

Use reset for better performance


{Document} = require 'telepath'

# Public: Manages the deserializers used for serialized state
module.exports =
class DeserializerManager
  constructor: ->
    @deserializers = {}
    @deferredDeserializers = {}

  # Public: Add a deserializer.
  add: (klasses...) ->
    @deserializers[klass.name] = klass for klass in klasses

  # Public: Add a deferred deserializer.
  addDeferred: (name, fn) ->
    @deferredDeserializers[name] = fn

  # Public: Remove a deserializer.
  remove: (klasses...) ->
    delete @deserializers[klass.name] for klass in klasses

  # Public: Deserialize the state and params.
  deserialize: (state, params) ->
    return unless state?

    if deserializer = @getDeserializer(state)
      stateVersion = state.get?('version') ? state.version
      return if deserializer.version? and deserializer.version isnt stateVersion
      if (state instanceof Document) and not deserializer.acceptsDocuments
        state = state.toObject()
      deserializer.deserialize(state, params)
    else
      console.warn "No deserializer found for", state

  # Public: Get the deserializer for the state.
  get: (state) ->
    return unless state?

    name = state.get?('deserializer') ? state.deserializer
    if @deferredDeserializers[name]
      @deferredDeserializers[name]()
      delete @deferredDeserializers[name]

    @deserializers[name]

{Document} = require 'telepath'

# Public: Manages the deserializers used for serialized state
module.exports =
class DeserializerManager
  constructor: ->
    @deserializers = {}
    @deferredDeserializers = {}

  # Public: Add a deserializer.
  add: (klasses...) ->
    @deserializers[klass.name] = klass for klass in klasses

  # Public: Add a deferred deserializer.
  addDeferred: (name, fn) ->
    @deferredDeserializers[name] = fn

  # Public: Remove a deserializer.
  remove: (klasses...) ->
    delete @deserializers[klass.name] for klass in klasses

  # Public: Deserialize the state and params.
  deserialize: (state, params) ->
    return unless state?

    if deserializer = @get(state)
      stateVersion = state.get?('version') ? state.version
      return if deserializer.version? and deserializer.version isnt stateVersion
      if (state instanceof Document) and not deserializer.acceptsDocuments
        state = state.toObject()
      deserializer.deserialize(state, params)
    else
      console.warn "No deserializer found for", state

  # Public: Get the deserializer for the state.
  get: (state) ->
    return unless state?

    name = state.get?('deserializer') ? state.deserializer
    if @deferredDeserializers[name]
      @deferredDeserializers[name]()
      delete @deferredDeserializers[name]

    @deserializers[name]

Call get instead of getDeserializer

Call get instead of getDeserializer


# 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/

$ ->
	$('select[data-reveal-section]').change(->
		section = $("##{$(@).val() + $(@).attr('data-reveal-section')}")

		if section
			$('.hide-unless-selected').hide()
			section.find(':input').removeAttr('disabled')
			section.show()
	).trigger('change')

Add javascript to show section if an option with a matching value is selected


# Newer view to manage Question form.
class ELMO.Views.QuestionFormView extends ELMO.Views.FormView
  initialize: (options) ->
    @toggleFields()

  # We use $= because the start of the ID can vary depending on whether
  # it's a question form or questioning form.
  # Note, these events must be redefined in any child classes.
  events:
    'change select[id$="_qtype_name"]': 'toggleFields'
    'change select[id$="_metadata_type"]': 'toggleFields'

  toggleFields: ->
    @showField('auto_increment', @showAutoIncrement())
    @showField('metadata_type', @showMetaDataType())

  showAutoIncrement: ->
    @fieldValue('qtype_name') == 'counter'

  showMetaDataType: ->
    @fieldValue('qtype_name') == 'datetime'

  metadataTypeBlank: ->
    !@showMetaDataType() || @fieldValue('metadata_type') == ''

  # Gets form field value, or static value if field is read-only
  fieldValue: (attrib) ->
    div = @$(".form-field[data-field-name=#{attrib}] .control")
    if div.is('.read-only')
      wrapper = div.find('.ro-val')
      wrapper.data('val') || wrapper.text()
    else
      # Rails checkbox fields have a hidden field followed by a checkbox. We need to ignore the hidden.
      field = div.find('input[type!=hidden], select, textarea')
      if field.attr('type') == 'checkbox'
        field.is(':checked')
      else
        field.val()

# Newer view to manage Question form.
class ELMO.Views.QuestionFormView extends ELMO.Views.FormView
  initialize: (options) ->
    @toggleFields()

  # We use $= because the start of the ID can vary depending on whether
  # it's a question form or questioning form.
  # Note, these events must be redefined in any child classes.
  events:
    'change select[id$="_qtype_name"]': 'toggleFields'
    'change select[id$="_metadata_type"]': 'toggleFields'

  toggleFields: ->
    @showField('auto_increment', @showAutoIncrement())
    @showField('metadata_type', @showMetaDataType())

  showAutoIncrement: ->
    @fieldValue('qtype_name') == 'counter'

  showMetaDataType: ->
    @fieldValue('qtype_name') == 'datetime'

  metadataTypeBlank: ->
    !@showMetaDataType() || @fieldValue('metadata_type') == ''

  # Gets form field value, or static value if field is read-only
  fieldValue: (attrib) ->
    div = @$(".form-field[data-field-name=#{attrib}] .control")
    if div.is('.read-only')
      wrapper = div.find('.ro-val')
      if typeof wrapper.data('val') != 'undefined' then wrapper.data('val') else wrapper.text()
    else
      # Rails checkbox fields have a hidden field followed by a checkbox. We need to ignore the hidden.
      field = div.find('input[type!=hidden], select, textarea')
      if field.attr('type') == 'checkbox'
        field.is(':checked')
      else
        field.val()

10139: Fix bug with read-only view of questioning form


{BufferedProcess} = require 'atom'
StatusView = require './status-view'

# if all param true, then 'git add .'
gitAdd = (all=false)->
  dir = atom.project.getRepo().getWorkingDirectory()
  currentFile = atom.workspace.getActiveEditor().getPath()
  toStage = if all then '.' else currentFile
  new BufferedProcess({
    command: 'git'
    args: ['add', '--all', toStage]
    options:
      cwd: dir
    stderr: (data) ->
      new StatusView(type: 'alert', message: data.toString())
    exit: (data) ->
      file = if toStage is '.' then 'all files' else prettify(dir, toStage)
      new StatusView(type: 'success', message: "Added #{file}")
  })

# only show filepaths inside the project
prettify = (dir, file) ->
  i = dir.lastIndexOf('/')
  root = dir.slice(i + 1)
  path = file.slice(i + root.length + 2)

module.exports = gitAdd

{BufferedProcess} = require 'atom'
StatusView = require './status-view'

# if all param true, then 'git add .'
gitAdd = (all=false)->
  dir = atom.project.getRepo().getWorkingDirectory()
  currentFile = atom.workspace.getActiveEditor()?.getPath()
  toStage = if all then '.' else currentFile
  if (toStage?)
    new BufferedProcess({
      command: 'git'
      args: ['add', '--all', toStage]
      options:
        cwd: dir
      stderr: (data) ->
        new StatusView(type: 'alert', message: data.toString())
      exit: (data) ->
        file = if toStage is '.' then 'all files' else prettify(dir, toStage)
        new StatusView(type: 'success', message: "Added #{file}")
    })
  else
    new StatusView(type: 'alert', message: "I don't know which file(s) to add!")

# only show filepaths inside the project
prettify = (dir, file) ->
  i = dir.lastIndexOf('/')
  root = dir.slice(i + 1)
  path = file.slice(i + root.length + 2)

module.exports = gitAdd

Fix "Git Plus: Add (all)" without open editor

In the context, it would give a type error because
`atom.workspace.getActiveEditor()` was `undefined`.


path = require 'path'
fs = require 'fs-plus'
optimist = require 'optimist'
Highlights = require './highlights'

module.exports = ->
  cli = optimist.describe('help', 'Show this message').alias('h', 'help')
                .describe('scope', 'Scope name of grammar to use').alias('s', 'scopeName')
  optimist.usage """
    Usage: highlights file

    Output the syntax highlighted HTML for a file.

    If no file is specified then the text of highlight is read from standard in.
  """

  if cli.argv.help
    cli.showHelp()
    return

  [filePath] = cli.argv._
  if filePath
    filePath = path.resolve(filePath)
    unless fs.isFileSync(filePath)
      console.error("Specified path is not a file: #{filePath}")
      process.exit(1)
      return

    html = new Highlights().highlightSync({filePath, scopeName: cli.argv.scope})
    console.log(html)
  else
    process.stdin.resume()
    process.stdin.setEncoding('utf8')
    fileContents = ''
    process.stdin.on 'data', (chunk) -> fileContents += chunk.toString()
    process.stdin.on 'end', ->
      html = new Highlights().highlightSync({fileContents, scopeName: cli.argv.scope})
      console.log(html)

path = require 'path'
fs = require 'fs-plus'
optimist = require 'optimist'
Highlights = require './highlights'

module.exports = ->
  cli = optimist.describe('help', 'Show this message').alias('h', 'help')
                .describe('scope', 'Scope name of the grammar to use').alias('s', 'scopeName')
  optimist.usage """
    Usage: highlights file

    Output the syntax highlighted HTML for a file.

    If no file is specified then the text of highlight is read from standard in.
  """

  if cli.argv.help
    cli.showHelp()
    return

  [filePath] = cli.argv._
  if filePath
    filePath = path.resolve(filePath)
    unless fs.isFileSync(filePath)
      console.error("Specified path is not a file: #{filePath}")
      process.exit(1)
      return

    html = new Highlights().highlightSync({filePath, scopeName: cli.argv.scope})
    console.log(html)
  else
    process.stdin.resume()
    process.stdin.setEncoding('utf8')
    fileContents = ''
    process.stdin.on 'data', (chunk) -> fileContents += chunk.toString()
    process.stdin.on 'end', ->
      html = new Highlights().highlightSync({fileContents, scopeName: cli.argv.scope})
      console.log(html)

Add the to arg doc

Add the to arg doc


# Description:
#   A simple interaction with the built in HTTP Daemon
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   None
#
# URLS:
#   /hubot/version
#   /hubot/ping
#   /hubot/time
#   /hubot/info

spawn = require('child_process').spawn

module.exports = (robot) ->

  robot.router.get "/hubot/version", (req, res) ->
    res.end robot.version

  robot.router.post "/hubot/ping", (req, res) ->
    res.end "PONG"

  robot.router.get "/hubot/time", (req, res) ->
    res.end "Server time is: #{new Date()}"

  robot.router.get "/hubot/info", (req, res) ->
    child = spawn('/bin/sh', ['-c', "echo I\\'m $LOGNAME@$(hostname):$(pwd) \\($(git rev-parse HEAD)\\)"])

    child.stdout.on 'data', (data) ->
      res.end "#{data.toString().trim()} running node #{process.version} [pid: #{process.pid}]"
      child.stdin.end()

# Description:
#   A simple interaction with the built in HTTP Daemon
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   None
#
# URLS:
#   /hubot/version
#   /hubot/ping
#   /hubot/time
#   /hubot/info
#   /hubot/ip

spawn = require('child_process').spawn

module.exports = (robot) ->

  robot.router.get "/hubot/version", (req, res) ->
    res.end robot.version

  robot.router.post "/hubot/ping", (req, res) ->
    res.end "PONG"

  robot.router.get "/hubot/time", (req, res) ->
    res.end "Server time is: #{new Date()}"

  robot.router.get "/hubot/info", (req, res) ->
    child = spawn('/bin/sh', ['-c', "echo I\\'m $LOGNAME@$(hostname):$(pwd) \\($(git rev-parse HEAD)\\)"])

    child.stdout.on 'data', (data) ->
      res.end "#{data.toString().trim()} running node #{process.version} [pid: #{process.pid}]"
      child.stdin.end()

  robot.router.get "/hubot/ip", (req, res) ->
    robot.http('http://checkip.dyndns.org').get() (err, r, body) ->
      res.end body

Add route for knowing the IP where the bot is host


# Public: An object that aggregates multiple {Disposable} instances together
# into a single disposable, so they can all be disposed as a group.
module.exports =
class CompositeDisposable
  disposed: false

  constructor: ->
    @disposables = []

  # Public: Add a disposable to be disposed when the composite is disposed.
  #
  # If this object has already been disposed, this method has no effect.
  #
  # * `disposable` {Disposable} instance or any object with a `.dispose()`
  #   method.
  add: (disposable) ->
    unless @disposed
      @disposables.push(disposable)

  # Public: Remove a previously added disposable.
  #
  # * `disposable` {Disposable} instance or any object with a `.dispose()`
  #   method.
  remove: (disposable) ->
    index = @disposables.indexOf(disposable)
    @disposables.splice(index, 1) if index isnt -1

  # Public: Dispose all disposables added to this composite disposable.
  #
  # If this object has already been disposed, this method has no effect.
  dispose: ->
    unless @disposed
      @disposed = true
      disposable.dispose() for disposable in @disposables
      @clear()

  # Public: Clear all disposables. They will not be disposed by the next call
  # to dispose.
  clear: ->
    @disposables.length = 0

# Public: An object that aggregates multiple {Disposable} instances together
# into a single disposable, so they can all be disposed as a group.
module.exports =
class CompositeDisposable
  disposed: false

  # Public: Construct an instance, optionally with one or more
  constructor: ->
    @disposables = []
    @add(disposable) for disposable in arguments

  # Public: Add a disposable to be disposed when the composite is disposed.
  #
  # If this object has already been disposed, this method has no effect.
  #
  # * `disposable` {Disposable} instance or any object with a `.dispose()`
  #   method.
  add: (disposable) ->
    unless @disposed
      @disposables.push(disposable)

  # Public: Remove a previously added disposable.
  #
  # * `disposable` {Disposable} instance or any object with a `.dispose()`
  #   method.
  remove: (disposable) ->
    index = @disposables.indexOf(disposable)
    @disposables.splice(index, 1) if index isnt -1

  # Public: Dispose all disposables added to this composite disposable.
  #
  # If this object has already been disposed, this method has no effect.
  dispose: ->
    unless @disposed
      @disposed = true
      disposable.dispose() for disposable in @disposables
      @clear()

  # Public: Clear all disposables. They will not be disposed by the next call
  # to dispose.
  clear: ->
    @disposables.length = 0

Allow CompositeDisposable to be constructed with multiple disposables