{WorkspaceView} = require 'atom'
NotationalVelocity = require '../lib/notational-velocity'

# Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs.
#
# To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit`
# or `fdescribe`). Remove the `f` to unfocus the block.

describe "NotationalVelocity", ->
  activationPromise = null

  beforeEach ->
    atom.workspaceView = new WorkspaceView
    activationPromise = atom.packages.activatePackage('notational-velocity')

  describe "when the notational-velocity:toggle event is triggered", ->
    it "attaches and then detaches the view", ->
      expect(atom.workspaceView.find('.notational-velocity')).not.toExist()

      # This is an activation event, triggering it will cause the package to be
      # activated.
      atom.commands.dispatch atom.workspaceView.element, 'notational-velocity:toggle'

      waitsForPromise ->
        activationPromise

      runs ->
        expect(atom.workspaceView.find('.notational-velocity')).toExist()
        atom.commands.dispatch atom.workspaceView.element, 'notational-velocity:toggle'

{WorkspaceView} = require 'atom'
NotationalVelocity = require '../lib/notational-velocity'

# Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs.
#
# To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit`
# or `fdescribe`). Remove the `f` to unfocus the block.

describe "NotationalVelocity", ->
  defaultDirectory = atom.config.get('notational-velocity.directory')
  activationPromise = null

  beforeEach ->
    atom.workspaceView = new WorkspaceView
    activationPromise = atom.packages.activatePackage('notational-velocity')
    atom.config.set('notational-velocity.directory', 'testdata')

  afterEach ->
    atom.config.set('notational-velocity.directory', defaultDirectory)

  describe "when the notational-velocity:toggle event is triggered", ->
    it "attaches and then detaches the view", ->
      expect(atom.workspaceView.find('.notational-velocity')).not.toExist()

      # This is an activation event, triggering it will cause the package to be
      # activated.
      atom.commands.dispatch atom.workspaceView.element, 'notational-velocity:toggle'

      waitsForPromise ->
        activationPromise

      runs ->
        expect(atom.workspaceView.find('.notational-velocity')).toExist()
        atom.commands.dispatch atom.workspaceView.element, 'notational-velocity:toggle'

Fix a test failure caused by non-existing default directory in test environment


packages: [
  "editorconfig"
  "file-icons"
  "highlight-selected"
  "language-docker"
  "language-typescript-grammars-only"
  "linter"
  "linter-coffeelint"
  "linter-csslint"
  "linter-docker"
  "linter-flake8"
  "linter-htmlhint"
  "linter-js-yaml"
  "linter-jshint"
  "linter-jsonlint"
  "linter-less"
  "linter-php"
  "linter-scss-lint"
  "linter-shellcheck"
  "linter-tslint"
  "linter-write-good"
  "linter-xmllint"
  "minimap"
  "omni-ruler"
  "package-sync"
  "pigments"
  "platformio-ide-terminal"
  "pretty-json"
  "sort-lines"
]

packages: [
  "autocomplete-emojis"
  "editorconfig"
  "file-icons"
  "highlight-selected"
  "language-docker"
  "language-typescript-grammars-only"
  "linter"
  "linter-coffeelint"
  "linter-csslint"
  "linter-docker"
  "linter-flake8"
  "linter-htmlhint"
  "linter-js-yaml"
  "linter-jshint"
  "linter-jsonlint"
  "linter-less"
  "linter-php"
  "linter-scss-lint"
  "linter-shellcheck"
  "linter-tslint"
  "linter-write-good"
  "linter-xmllint"
  "minimap"
  "omni-ruler"
  "package-sync"
  "pigments"
  "platformio-ide-terminal"
  "pretty-json"
  "sort-lines"
]

Add autocomplete-emojis package to Atom

Add autocomplete-emojis package to Atom


_ = require('underscore')._
CONS = require '../lib/constants'
Q = require 'q'

class Categories
  constructor: ->
    @id2index = {}
    @name2id = {}
    @fqName2id = {}
    @duplicateNames = []

  getAll: (rest) ->
    deferred = Q.defer()
    rest.GET "/categories?limit=1000", (error, response, body) ->
      if error
        deferred.reject 'Error on getting categories: ' + error
      else if response.statusCode isnt 200
        deferred.reject "Problem on getting categories:\n" +
          "status #{response.statusCode})\n" +
          "body " + response.body
      else
        categories = body.results
        deferred.resolve categories
    deferred.promise

  buildMaps: (categories) ->
    for category, index in categories
      name = category.name[CONS.DEFAULT_LANGUAGE]
      id = category.id
      @id2index[id] = index
      if _.has @name2id, name
        @duplicateNames.push name
      @name2id[name] = id

    for category, index in categories
      fqName = ''
      if category.ancestors
        for anchestor in category.ancestors
          cat = categories[@id2index[anchestor.id]]
          name = cat.name[CONS.DEFAULT_LANGUAGE]
          fqName = "#{fqName}#{name}#{CONS.DELIM_CATEGORY_CHILD}"
      @fqName2id["#{fqName}#{category.name[CONS.DEFAULT_LANGUAGE]}"] = category.id

module.exports = Categories

_ = require('underscore')._
CONS = require '../lib/constants'
Q = require 'q'

class Categories
  constructor: ->
    @id2index = {}
    @name2id = {}
    @fqName2id = {}
    @duplicateNames = []

  getAll: (rest) ->
    deferred = Q.defer()
    rest.GET "/categories?limit=0", (error, response, body) ->
      if error
        deferred.reject 'Error on getting categories: ' + error
      else if response.statusCode isnt 200
        deferred.reject "Problem on getting categories:\n" +
          "status #{response.statusCode})\n" +
          "body " + response.body
      else
        categories = body.results
        deferred.resolve categories
    deferred.promise

  buildMaps: (categories) ->
    for category, index in categories
      name = category.name[CONS.DEFAULT_LANGUAGE]
      id = category.id
      @id2index[id] = index
      if _.has @name2id, name
        @duplicateNames.push name
      @name2id[name] = id

    for category, index in categories
      fqName = ''
      if category.ancestors
        for anchestor in category.ancestors
          cat = categories[@id2index[anchestor.id]]
          name = cat.name[CONS.DEFAULT_LANGUAGE]
          fqName = "#{fqName}#{name}#{CONS.DELIM_CATEGORY_CHILD}"
      @fqName2id["#{fqName}#{category.name[CONS.DEFAULT_LANGUAGE]}"] = category.id

module.exports = Categories

Adjust limit to take max.

Adjust limit to take max.


{Emitter} = require 'atom'

module.exports =
class MessageManager
  constructor: (csound, Csound) ->
    @emitter = new Emitter

    messageCallback = (Csound, attributes, string) =>
      @emitter.emit 'did-receive-message', {string: string, attributes: attributes}
    csound.SetDefaultMessageCallback messageCallback
    csound.SetMessageCallback Csound, messageCallback

    csound.SetIsGraphable Csound, true
    csound.SetMakeGraphCallback Csound, (data, name) =>
      @emitter.emit 'graph-creation-request', {name: name, data: data}
    csound.SetDrawGraphCallback Csound, (data) =>
      @emitter.emit 'graph-drawing-request', data

  onDidReceiveMessage: (callback) ->
    @emitter.on 'did-receive-message', callback

  onGraphCreationRequest: (callback) ->
    @emitter.on 'graph-creation-request', callback

  onGraphDrawingRequest: (callback) ->
    @emitter.on 'graph-drawing-request', callback

{Emitter} = require 'atom'

module.exports =
class MessageManager
  constructor: (csound, Csound) ->
    @emitter = new Emitter

    messageCallback = (attributes, string) =>
      @emitter.emit 'did-receive-message', {string: string, attributes: attributes}
    csound.SetDefaultMessageCallback messageCallback
    csound.SetMessageCallback Csound, messageCallback

    csound.SetIsGraphable Csound, true
    csound.SetMakeGraphCallback Csound, (data, name) =>
      @emitter.emit 'graph-creation-request', {name: name, data: data}
    csound.SetDrawGraphCallback Csound, (data) =>
      @emitter.emit 'graph-drawing-request', data

  onDidReceiveMessage: (callback) ->
    @emitter.on 'did-receive-message', callback

  onGraphCreationRequest: (callback) ->
    @emitter.on 'graph-creation-request', callback

  onGraphDrawingRequest: (callback) ->
    @emitter.on 'graph-drawing-request', callback

Update Csound message callback functions


{CompositeDisposable} = require 'atom'

module.exports =
class VariableMarker
  constructor: ({@marker, @variable}) ->
    @subscriptions = new CompositeDisposable
    @subscriptions.add @marker.onDidDestroy => @destroyed()
    @subscriptions.add @variable.onDidDestroy => @destroy()

  destroy: ->
    return if @wasDestroyed
    @marker.destroy()

  destroyed: ->
    return if @wasDestroyed
    @subscriptions.dispose()
    {@marker, @variable} = {}
    @wasDestroyed = true

  match: (properties) ->
    bool = true

    if properties.bufferRange?
      bool &&= @marker?.getBufferRange().isEqual(properties.bufferRange)

    if properties.variable
      bool &&= @variable?.isEqual(properties.variable)

    bool

  serialize: ->
    return if @wasDestroyed
    {
      markerId: @marker.id
      bufferRange: @marker.getBufferRange().serialize()
      variable: @variable.name
    }

{CompositeDisposable} = require 'atom'

module.exports =
class VariableMarker
  constructor: ({@marker, @variable}) ->
    @subscriptions = new CompositeDisposable
    @subscriptions.add @marker.onDidDestroy => @destroyed()
    @subscriptions.add @variable.onDidDestroy => @destroy()

  destroy: ->
    return if @wasDestroyed
    @marker.destroy()

  destroyed: ->
    return if @wasDestroyed
    @subscriptions.dispose()
    {@marker, @variable} = {}
    @wasDestroyed = true

  match: (properties) ->
    bool = true

    if properties.bufferRange?
      bool &&= @marker?.getBufferRange().isEqual(properties.bufferRange)

    if properties.variable
      bool &&= @variable?.isEqual(properties.variable)

    bool

  serialize: ->
    return if @wasDestroyed
    {
      markerId: String(@marker.id)
      bufferRange: @marker.getBufferRange().serialize()
      variable: @variable.name
    }

:green_heart: Fix variable markers id still as numbers


Transformations["Checkmark"] = (object) -> Transformations.static(Checkmarks.Checkmark, object)
Checkmarks = Collections["Checkmark"] = new Mongo.Collection("Checkmarks", {transform: if Meteor.isClient then Transformations.Checkmark else null})

class Checkmarks.Checkmark
  constructor: (doc) ->
    _.extend(@, doc)

CheckmarkPreSave = (userId, changes) ->
  now = new Date()
  changes.updatedAt = changes.updatedAt or now

Checkmarks.before.insert (userId, Checkmark) ->
  Checkmark._id ||= Random.id()
  now = new Date()
  _.defaults(Checkmark,
    userId: userId
    updatedAt: now
    createdAt: now
  )
  throw new Meteor.Error("Checkmark:userId:empty", "Checkmark::userId is empty", Checkmark) if not Checkmark.userId
  CheckmarkPreSave.call(@, userId, Checkmark)
  true

Checkmarks.before.update (userId, Checkmark, fieldNames, modifier, options) ->
  modifier.$set = modifier.$set or {}
  CheckmarkPreSave.call(@, userId, modifier.$set)
  true

Transformations["Checkmark"] = (object) -> Transformations.static(Checkmarks.Checkmark, object)
Checkmarks = Collections["Checkmark"] = new Mongo.Collection("Checkmarks", {transform: if Meteor.isClient then Transformations.Checkmark else null})

class Checkmarks.Checkmark
  constructor: (doc) ->
    _.extend(@, doc)

CheckmarkPreSave = (userId, changes) ->
  now = new Date()
  changes.updatedAt = changes.updatedAt or now

Checkmarks.before.insert (userId, Checkmark) ->
  Checkmark._id ||= Random.id()
  now = new Date()
  _.autovalues(Checkmark,
    userId: userId
    updatedAt: now
    createdAt: now
  )
  throw new Meteor.Error("Checkmark:userId:empty", "Checkmark::userId is empty", Checkmark) if not Checkmark.userId
  CheckmarkPreSave.call(@, userId, Checkmark)
  true

Checkmarks.before.update (userId, Checkmark, fieldNames, modifier, options) ->
  modifier.$set = modifier.$set or {}
  CheckmarkPreSave.call(@, userId, modifier.$set)
  true

Implement Categories, clean up old code

Implement Categories, clean up old code


class Lanes.Components.Input extends Lanes.React.Component

    mixins: [
        Lanes.Components.Form.FieldMixin
    ]
    formGroupClass: 'input'

    getDefaultProps: ->
        type: 'text'

    propTypes:
        unlabled:  React.PropTypes.bool

    getValue: ->
        @refs.input.getValue()

    handleKeyDown: (ev) ->
        @props.onEnter() if ev.key is 'Enter'

    renderEdit: (label) ->
        value = @props.model[@props.name] or ''
        label = @props.label or _.field2title(@props.name)
        props = _.extend({
            ref:       'input'
            className: _.classnames('value', changeset: @state.changeset)
            label:     if @props.unlabeled then label else false
            value:     value
            onKeyDown: @handleKeyDown if @props.onEnter
            onChange:  @handleChange
        }, @props)

        if @props.inputOnly then @renderPlain(props) else @renderStyled(props, label)

    renderPlain: (props) ->
        <input {...props}/>

    renderStyled: (props, label) ->
        colProps = _.omit(props, 'name')
        <BS.Col {...colProps} >
            <BS.Input {...props} />
        </BS.Col>

class Lanes.Components.Input extends Lanes.React.Component

    mixins: [
        Lanes.Components.Form.FieldMixin
    ]
    formGroupClass: 'input'

    getDefaultProps: ->
        type: 'text'

    propTypes:
        unlabled:  React.PropTypes.bool

    getValue: ->
        @refs.input.getValue()

    handleKeyDown: (ev) ->
        @props.onEnter() if ev.key is 'Enter'

    renderEdit: (label) ->
        value = @model[@props.name] or ''
        label ||= @props.label or _.field2title(@props.name)
        props = _.extend({
            ref:       'input'
            className: _.classnames('value', changeset: @state.changeset)
            label:     if @props.unlabeled then false else label
            value:     value
            onKeyDown: @handleKeyDown if @props.onEnter
            onChange:  @handleChange
        }, @props)
        if @props.inputOnly then @renderPlain(props) else @renderStyled(props, label)

    renderPlain: (props) ->
        <input {...props}/>

    renderStyled: (props, label) ->
        colProps = _.omit(props, 'name')
        <BS.Col {...colProps} >
            <BS.Input {...props} />
        </BS.Col>

Use default label value if present

Use default label value if present


[
  {
    title: "OPCUA-All"
    paths: [
      "/Users/randy/src/github/node-opcua"
      "/Users/randy/Documents/Projects/OPCUA/WSDL-1.03"
    ]
  }
]

Add project for OPCA docs and code

Add project for OPCA docs and code


mongoose = require '../connection'

Schema = mongoose.Schema
ObjectId = Schema.ObjectId

MessageSchema = new Schema(
  Name: String
  Subject: String
  Message: String
  Date: Date
  Phone: String
  Country: String
  Attachments: String
)

Message = mongoose.model('Message', MessageSchema)

module.exports = Message

mongoose = require '../connection'

Schema = mongoose.Schema
ObjectId = Schema.ObjectId

MessageSchema = new Schema(
  Name: String
  Subject: String
  Message: String
  Date: Date
  Phone: String
  Country: String
  Attachments: String
)

MessageSchema.statics.byCount = (cb) ->
    this.aggregate [
        {
            $group:
                _id: '$Phone Number'
                count: $sum: 1
        }
        {
            $sort:
                count: -1
        }
        {
            $project:
                'Phone Number': '$_id'
                count: 1
                _id: 0
        }
    ], cb

MessageSchema.index({'Phone Number': 1})

Message = mongoose.model('Message', MessageSchema)

module.exports = Message

Add index for phone numbers and byCount aggregation


window.LOG = () ->
  console?.log?(arguments...)

window.init_loading_button = () ->
  $('body').on 'click', '.btn-loading', ->
    $(this).button('loading')

window.init_time = () ->
  if ($ 'time').length > 0
    recalculate = ->
      ($ 'time[datetime]').each ->
        date = moment.utc ($ this).attr 'datetime'
        diff = moment().diff date , 'days'
        if diff > 25
          ($ this).text date.local().format 'YYYY-DD-MM'
        else
          ($ this).text date.fromNow()
        ($ this).attr 'title', date.local().format 'dddd, MMMM Do YYYY, HH:mm:ss Z'

    recalculate()
    setInterval ->
        recalculate()
      , 1000 * 60

window.LOG = () ->
  console?.log?(arguments...)

window.init_loading_button = () ->
  $('body').on 'click', '.btn-loading', ->
    th = $(this)
    th.button('loading')
    setTimeout (->th.button('reset')), 3000

window.init_time = () ->
  if ($ 'time').length > 0
    recalculate = ->
      ($ 'time[datetime]').each ->
        date = moment.utc ($ this).attr 'datetime'
        diff = moment().diff date , 'days'
        if diff > 25
          ($ this).text date.local().format 'YYYY-DD-MM'
        else
          ($ this).text date.fromNow()
        ($ this).attr 'title', date.local().format 'dddd, MMMM Do YYYY, HH:mm:ss Z'

    recalculate()
    setInterval ->
        recalculate()
      , 1000 * 60

Reset submit button after 3000 ms

Reset submit button after 3000 ms


module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON "package.json"
    sass:
      dist:
        files:
          "{{ app_name }}/static/{{ app_name }}/css/app.css": "{{ app_name }}/static/{{ app_name }}/sass/app.sass"
        options:
          style: "compressed"
    watch:
      css:
        files: "{{ app_name }}/**/*.s?ss"
        tasks: ["sass", ]

  TASKS = [
    "grunt-contrib-sass",
    "grunt-contrib-watch"
  ]
  [grunt.loadNpmTasks a for a in TASKS]

  grunt.registerTask "default", ["watch", ]

module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON "package.json"
    sass:
      dist:
        files:
          "{{ app_name }}/static/{{ app_name }}/css/app.css": "{{ app_name }}/static/{{ app_name }}/sass/app.sass"
        options:
          style: "compressed"
    watch:
      css:
        files: "{{ app_name }}/**/*.s?ss"
        tasks: ["sass", ]

  grunt.loadNpmTasks "grunt-contrib-sass"
  grunt.loadNpmTasks "grunt-contrib-watch"

  grunt.registerTask "default", ["watch", ]

Switch to explicit call instead of inside the loop


module.exports = (grunt, options) ->
  return {
    options:
      client: true
      files:
        '<%= build %>/js/templates.js': ['views/templates/**/*.jade']
    dev:
      options:
        data:
          debug: true
    dist:
      options:
        data:
          debug: false
  }

module.exports = (grunt, options) ->
  return {
    options:
      client: true
    dev:
      files:
        '<%= build %>/js/templates.js': ['views/templates/**/*.jade']
      options:
        data:
          debug: true
    dist:
      files:
        '<%= build %>/js/templates.js': ['views/templates/**/*.jade']
      options:
        data:
          debug: false
  }

Fix Grunt Jade task configuration

Fix Grunt Jade task configuration


fs         = require 'fs'
expect     = require 'expect.js'
config     = require '../../../test/test_config'
models     = require('../lib/schema').load(config)
common     = require '../../../test/common'

describe "Dotstorm Canvas to image from idea", ->
  before (done) ->
    @mahId = undefined
    common.startUp (server) =>
      @server = server
      done()

  after (done) ->
    common.shutDown(@server, done)

  it "creates idea", (done) ->
    idea = new models.Idea
      dotstorm_id: "aaaaaaaaaaaaaaaaaaaaaaaa"
      background: "#ffffdd"
      tags: "ok"
      description: "whatevs"
      drawing: [["pencil", 0, 0, 400, 400]]

    idea.save (err) =>
      @mahId = idea._id
      expect(err).to.be null
      expect(fs.existsSync idea.getDrawingPath("small")).to.be true
      done()
      return true

  it "removes the idea", (done) ->
    models.Idea.findOne {_id: @mahId}, (err, idea) ->
      expect(err).to.be null
      expect(idea).to.not.be null
      idea.remove (err) ->
        expect(fs.existsSync idea.getDrawingPath("small")).to.be false
        done()

fs         = require 'fs'
expect     = require 'expect.js'
config     = require '../../../test/test_config'
models     = require('../lib/schema').load(config)
common     = require '../../../test/common'

describe "Dotstorm Canvas to image from idea", ->
  this.timeout(10000)
  before (done) ->
    @mahId = undefined
    common.startUp (server) =>
      @server = server
      done()

  after (done) ->
    common.shutDown(@server, done)

  it "creates idea", (done) ->
    idea = new models.Idea
      dotstorm_id: "aaaaaaaaaaaaaaaaaaaaaaaa"
      background: "#ffffdd"
      tags: "ok"
      description: "whatevs"
      drawing: [["pencil", 0, 0, 400, 400]]

    idea.save (err) =>
      @mahId = idea._id
      expect(err).to.be null
      expect(fs.existsSync idea.getDrawingPath("small")).to.be true
      done()
      return true

  it "removes the idea", (done) ->
    models.Idea.findOne {_id: @mahId}, (err, idea) ->
      expect(err).to.be null
      expect(idea).to.not.be null
      idea.remove (err) ->
        expect(fs.existsSync idea.getDrawingPath("small")).to.be false
        done()

Increase timeout for thumbnail test

Increase timeout for thumbnail test


setTimeout ->

  if /^(interactive|complete)$/.test(document.readyState)
    FactlinkJailRoot.host_ready_promise.resolve()
  else
    document.addEventListener('DOMContentLoaded', -> FactlinkJailRoot.host_ready_promise.resolve())

  if 'complete' == document.readyState
    FactlinkJailRoot.host_loaded_promise.resolve()
  else
    window.addEventListener('load', -> FactlinkJailRoot.host_loaded_promise.resolve())
, 0

setTimeout ->
  ok =
    loaded: true
    interactive: !(document.documentMode < 11)
    complete: true

  if ok[document.readyState]
    FactlinkJailRoot.host_ready_promise.resolve()
  else
    document.addEventListener('DOMContentLoaded', -> FactlinkJailRoot.host_ready_promise.resolve())

  if 'complete' == document.readyState
    FactlinkJailRoot.host_loaded_promise.resolve()
  else
    window.addEventListener('load', ->
      FactlinkJailRoot.host_ready_promise.resolve()
      #IE pre 11's readyStates are weird; to ensure we can't miss anything,
      #trigger ready at the latest on load
      FactlinkJailRoot.host_loaded_promise.resolve()
    )
, 0

Fix IE 9/10 host_ready event

Fix IE 9/10 host_ready event


'global':
  'core':
    'themes': [
      'inbox-light-ui'
    ]
    'disabledPackages': [
      "atom-dark-syntax",
      "atom-dark-ui",
      "atom-light-syntax",
      "atom-light-ui",
      "one-dark-syntax",
      "one-dark-ui",
      "one-light-syntax",
      "one-light-ui",
      "base16-tomorrow-dark-theme",
      "base16-tomorrow-light-theme",
      "solarized-dark-syntax",
      "solarized-light-syntax",
      "archive-view",
      "autocomplete",
      "autoflow",
      "autosave",
      "background-tips",
      "bookmarks",
      "bracket-matcher",
      "command-palette",
      "deprecation-cop",
      "encoding-selector",
      "dev-live-reload",
      "exception-reporting",
      "feedback",
      "find-and-replace",
      "fuzzy-finder",
      "git-diff",
      "go-to-line",
      "grammar-selector",
      "image-view",
      "incompatible-packages",
      "keybinding-resolver",
      "link",
      "markdown-preview",
      "metrics",
      "open-on-github",
      "package-generator",
      "release-notes",
      "settings-view",
      "snippets",
      "spell-check",
      "status-bar",
      "styleguide",
      "symbols-view",
      "tabs",
      "timecop",
      "tree-view",
      "update-package-dependencies",
      "welcome",
      "whitespace",
      "wrap-guide",
      "language-c",
      "language-coffee-script",
      "language-css",
      "language-gfm",
      "language-git",
      "language-go",
      "language-html",
      "language-hyperlink",
      "language-java",
      "language-javascript",
      "language-json",
      "language-less",
      "language-make",
      "language-mustache",
      "language-objective-c",
      "language-perl",
      "language-php",
      "language-property-list",
      "language-python",
      "language-ruby",
      "language-ruby-on-rails",
      "language-sass",
      "language-shellscript",
      "language-source",
      "language-sql",
      "language-text",
      "language-todo",
      "language-toml",
      "language-xml",
      "language-yaml",

      # Temporarily disabled
      "sidebar-fullcontact",
      "message-templates",
      "calendar-bar",
      "salesforce"
    ]

'global':
  'core':
    'themes': [
      'inbox-light-ui'
    ]
    'disabledPackages': [
      "sidebar-fullcontact",
      "message-templates",
      "calendar-bar",
      "salesforce"
    ]

refactor(*): Remove disabledPackages that no longer exist


init = ->
  primary_lang = $("#catalog_primary_language")
  other_lang_boxes = \
    $("input[type=checkbox][name='catalog[other_languages][]']")

  update_boxes = (evt)->
    primary_value = primary_lang.val()
    other_lang_boxes.attr("disabled", false)
    match_box = $("input[type=checkbox][value=#{primary_value}]")
    match_box.attr("disabled", true)

  if primary_lang.length > 0
    primary_lang.on "change", update_boxes
    update_boxes()

  $('#catalog_data_only').on 'change', (e) ->
    if $('#catalog_data_only')[0].checked
      $('#catalog_custom_root_page_id').attr 'disabled', 'disabled'
      $('#catalog_advertize').attr 'disabled', 'disabled'
    else
      $('#catalog_custom_root_page_id').attr 'disabled', null
      $('#catalog_advertize').attr 'disabled', null
    return

$(document).ready(init)

init = ->
  primary_lang = $("#catalog_primary_language")
  other_lang_boxes = \
    $("input[type=checkbox][name='catalog[other_languages][]']")

  update_boxes = (evt)->
    primary_value = primary_lang.val()
    other_lang_boxes.attr("disabled", false)
    match_box = $("input[type=checkbox][value=#{primary_value}]")
    match_box.attr("disabled", true)

  if primary_lang.length > 0
    primary_lang.on "change", update_boxes
    update_boxes()

  $('#catalog_data_only').on 'change', (e) ->
    if $('#catalog_data_only')[0].checked
      $('#catalog_custom_root_page_id').attr 'disabled', 'disabled'
      $('#catalog_advertize').prop 'checked', false
      $('#catalog_advertize').attr 'disabled', 'disabled'
    else
      $('#catalog_custom_root_page_id').attr 'disabled', null
      $('#catalog_advertize').attr 'disabled', null
    return

$(document).ready(init)

Remove advertize if data only enabled

Remove advertize if data only enabled


define (require) ->
  $ = require('jquery')
  linksHelper = require('cs!helpers/links')
  BaseView = require('cs!helpers/backbone/views/base')
  template = require('hbs!./filter-template')
  require('less!./filter')

  return class SearchResultsFilterView extends BaseView
    template: template
    templateHelpers:
      url: () ->
        queryString = linksHelper.serializeQuery(window.location.search)
        q = queryString.q
        delete queryString.page
        delete queryString.q

        params = linksHelper.param(queryString)
        params += '&' if params

        url = "#{location.pathname}?#{params}q=#{q}"

        return url

    events:
      'click .toggle': 'toggleLimits'

    initialize: () ->
      super()
      @listenTo(@model, 'change:results', @render)

    onRender: () ->
      @$el.find('.collapsed').append('
More...
')

    toggleLimits: (e) ->
      $target = $(e.currentTarget)
      $limits = $target.siblings('.overflow')
      $text = $target.children('.text')

      if @expanded
        $limits.addClass('hidden')
        $text.text('More...')
        $text.removeClass('less')
        @expanded = false
      else
        $limits.removeClass('hidden')
        $text.text('Less...')
        $text.addClass('less')
        @expanded = true

define (require) ->
  $ = require('jquery')
  linksHelper = require('cs!helpers/links')
  BaseView = require('cs!helpers/backbone/views/base')
  template = require('hbs!./filter-template')
  require('less!./filter')

  return class SearchResultsFilterView extends BaseView
    template: template
    templateHelpers:
      url: () ->
        queryString = linksHelper.serializeQuery(window.location.search)
        q = queryString.q
        delete queryString.page
        delete queryString.q

        params = linksHelper.param(queryString)
        params += '&' if params

        url = "#{location.pathname}?#{params}q=#{q}"

        return url

    events:
      'click .toggle, keydown .toggle': 'toggleLimits'
      'keydown .toggle': 'toggleLimitsKeyboard'

    initialize: () ->
      super()
      @listenTo(@model, 'change:results', @render)

    onRender: () ->
      @$el.find('.collapsed').append('
More...
')

    toggleLimit: ($target) ->
      $limits = $target.siblings('.overflow')
      $text = $target.children('.text')

      if @expanded
        $limits.addClass('hidden')
        $text.text('More...')
        $text.removeClass('less')
        @expanded = false
      else
        $limits.removeClass('hidden')
        $text.text('Less...')
        $text.addClass('less')
        @expanded = true

    toggleLimits: (e) ->
      $target = $(e.currentTarget)
      @toggleLimit($target)

    toggleLimitsKeyboard: (e) ->
      if e.keyCode is 13 or e.keyCode is 32
        $target = $(e.currentTarget)
        @toggleLimit($target)

Enable keyboard interaction with 'More...' toggle


goog.provide 'app.react.Layout'

class app.react.Layout

  ###*
    PATTERN(steida): Here we can choose mobile/tablet/desktop layout.
    @param {app.Routes} routes
    @param {app.react.Header} header
    @param {app.react.Footer} footer
    @constructor
  ###
  constructor: (routes, header, footer) ->

    {div} = React.DOM

    @create = React.createClass

      render: ->
        div className: 'layout',
          header.create()
          @props.page.create()
          footer.create()

goog.provide 'app.react.Layout'

class app.react.Layout

  ###*
    PATTERN(steida): Layout is responsible for mobile/tablet/desktop look.
    @param {app.Routes} routes
    @param {app.react.Header} header
    @param {app.react.Footer} footer
    @param {app.react.pages.Song} song
    @constructor
  ###
  constructor: (routes, header, footer, song) ->

    {div} = React.DOM

    @create = React.createClass

      render: ->
        page = @props.page
        songPageIsShown = page == song

        div className: 'layout',
          header.create() unless songPageIsShown
          page.create()
          footer.create() unless songPageIsShown

Hide header and footer when song page is shown.

App needs maximum space to shown lyrics as big as possible.


class NumberFieldUpdater
  @hideReadOnly: (id) ->
    toggleReadOnly(id, false)
    resetInput(id)

  @showReadOnly: (id) ->
    toggleReadOnly(id, true)

  @showForm: (id) ->
    toggleForm(id, true)

  @hideForm: (id) ->
    toggleForm(id, false)

  @successHandler: (id, newNumber) ->
    $("#number-update-#{id} span").text(newNumber)
    @hideForm(id)
    @showReadOnly(id)

  toggleReadOnly = (id, show) ->
    toggleButtonVisibility('edit', id, show)
    toggleButtonVisibility('trash', id, show)
    cssDisplay = if show then 'block' else 'none'
    $("#number-update-#{id} span").css('display', cssDisplay)

  toggleForm = (id, show) ->
    toggleButtonVisibility('cancel', id, show)
    toggleButtonVisibility('check', id, show)
    cssDisplay = if show then 'block' else 'none'
    $("#number-update-#{id} input[type='number']").css('display', cssDisplay)

  toggleButtonVisibility = (buttonIcon, id, show) ->
    cssDisplay = if show then 'inline-block' else 'none'
    $(".fa-#{buttonIcon}[data-id='#{id}']").css('display', cssDisplay)

  resetInput = (id) ->
    tableCell = $("#number-update-#{id}")
    countText = tableCell.find('span').text().trim()
    tableCell.find("input[type='number']").val(countText)

Spree.NumberFieldUpdater = NumberFieldUpdater

class NumberFieldUpdater
  @hideReadOnly: (id) ->
    toggleReadOnly(id, false)
    resetInput(id)

  @showReadOnly: (id) ->
    toggleReadOnly(id, true)

  @showForm: (id) ->
    toggleForm(id, true)

  @hideForm: (id) ->
    toggleForm(id, false)

  @successHandler: (id, newNumber) ->
    $("#number-update-#{id} span").text(newNumber)
    @hideForm(id)
    @showReadOnly(id)

  toggleReadOnly = (id, show) ->
    toggleButtonVisibility('edit', id, show)
    toggleButtonVisibility('remove', id, show)
    cssDisplay = if show then 'block' else 'none'
    $("#number-update-#{id} span").css('display', cssDisplay)

  toggleForm = (id, show) ->
    toggleButtonVisibility('cancel', id, show)
    toggleButtonVisibility('save', id, show)
    cssDisplay = if show then 'block' else 'none'
    $("#number-update-#{id} input[type='number']").css('display', cssDisplay)

  toggleButtonVisibility = (buttonAction, id, show) ->
    cssDisplay = if show then 'inline-block' else 'none'
    $("[data-action='#{buttonAction}'][data-id='#{id}']").css('display', cssDisplay)

  resetInput = (id) ->
    tableCell = $("#number-update-#{id}")
    countText = tableCell.find('span').text().trim()
    tableCell.find("input[type='number']").val(countText)

Spree.NumberFieldUpdater = NumberFieldUpdater

Use buttons data-actions in NumberFieldUpdater component

It will survive if we change icons framework, also it is more
samantically correct.


class Workbench.Routers.WorkbenchRouter extends Backbone.Router
  initialize: (options) ->
    @sensor = options.sensor
    @navigate(@sensor.id)

  routes:
    '': 'index'
    ':id/': 'show'

  index: ->
    console.log "loading index route"
    # render index view

  show: (id) ->
    console.log "loading show route", id
    # render show view
    showView = new Workbench.Views.SensorShowView
      model: new Workbench.Models.Sensor(@sensor)
      el: $("#sensorView")
    showView.render()

class Workbench.Routers.WorkbenchRouter extends Backbone.Router
  initialize: (options) ->
    @sensor = options.sensor
    @navigate(@sensor.id)

  routes:
    '': 'index'
    ':id(/)': 'show'

  index: ->
    console.log "loading index route"
    # render index view

  show: (id) ->
    console.log "loading show route", id
    # render show view
    showView = new Workbench.Views.SensorShowView
      model: new Workbench.Models.Sensor(@sensor)
      el: $("#sensorView")
    showView.render()

Allow routes to load without trailing slash


class Workbench.Controllers.SensorsController extends Backbone.Marionette.Controller
  initialize: (options) ->
    @$el = options.el
    @getApiKey()
    Workbench.source = new Geocens.DataService({ api_key: @apiKey })

  # Ensure the API Key is displayed in the URL params.
  addApiKeyParam: (base) ->
    # if (location.search.length < 1)
    #   Backbone.history.navigate "#{base}?api_key=#{@apiKey}", { replace: true }

  # Check params for API Key.
  getApiKey: ->
    if (location.search.length > 0)
      params = deparam(location.search.split('?')[1])
      @apiKey ||= params.api_key

  #
  # Actions
  #

  index: =>
    @addApiKeyParam("sensors")

    @sensors = new Workbench.Collections.SensorsCollection
      source: Workbench.source

    mainView = new Workbench.Views.SensorIndexView
      collection: @sensors
      el: @$el
    mainView.render()
    @sensors.fetch()

  show: (id) =>
    @addApiKeyParam("sensors/#{id}")

    @sensor = new Workbench.Models.Sensor
      source: Workbench.source
      uid: id
    @sensor.fetch()

    mainView = new Workbench.Views.SensorShowView
      model: @sensor
      el: @$el
    mainView.render()

class Workbench.Controllers.SensorsController extends Backbone.Marionette.Controller
  initialize: (options) ->
    @getApiKey()
    Workbench.source = new Geocens.DataService({ api_key: @apiKey })

  # Check params for API Key.
  getApiKey: ->
    if (location.search.length > 0)
      params = deparam(location.search.split('?')[1])
      @apiKey ||= params.api_key

  #
  # Actions
  #

  index: =>
    @sensors = new Workbench.Collections.SensorsCollection
      source: Workbench.source

    mainView = new Workbench.Views.SensorIndexView
      collection: @sensors
    window.rm.get('main').show(mainView)
    @sensors.fetch()

  show: (id) =>
    @sensor = new Workbench.Models.Sensor
      source: Workbench.source
      uid: id
    @sensor.fetch()

    mainView = new Workbench.Views.SensorShowView
      model: @sensor
    window.rm.get('main').show(mainView)

Use region manager for sensors views

Use region manager for sensors views


Steam.ModelSelectionView = (_) ->
  _selections = nodes$ []
  _hasSelection = lift$ _selections, (selections) -> selections.length > 0
  _caption = lift$ _selections, (selections) ->
    "#{describeCount selections.length, 'model'} selected."

  scoreSelections = ->
    _.promptForFrame (action, frameKey) ->
      switch action
        when 'confirm'
          scorings = map _selections(), (selection) ->
            frameKey: frameKey
            model: selection.data
            status: null
            time: null
            result: null
            timestamp: Date.now()

          _.switchToScoring type: 'scoring', scorings: scorings
          _.deselectAllModels()
        when 'error'
          _.fail 'Error', 'An error occured while fetching the list of datasets.', error, noop

  clearSelections = ->
    _.deselectAllModels()

  link$ _.modelSelectionChanged, (isSelected, model) ->
    if isSelected
      _selections.push model
    else
      _selections.remove model

  link$ _.modelSelectionCleared, ->
    _selections.removeAll()

  caption: _caption
  hasSelection: _hasSelection
  clearSelections: clearSelections
  scoreSelections: scoreSelections
  template: 'model-selection-view'

defaultScoringSelectionMessage = 'Score selected models.'
Steam.ModelSelectionView = (_) ->
  _selections = nodes$ []
  _hasSelection = lift$ _selections, (selections) -> selections.length > 0
  _caption = lift$ _selections, (selections) ->
    "#{describeCount selections.length, 'model'} selected."

  _compatibleFrames = lift$ _selections, (selections) ->
    framesPerModel = map selections, (selection) -> selection.data.compatible_frames
    framesByKey = indexBy (flatten framesPerModel), (frame) -> frame.key
    commonFrameKeys = sortBy intersection.apply null, map framesPerModel, (frames) -> map frames, (frame) -> frame.key
    map commonFrameKeys, (key) -> framesByKey[key]

  _canScoreSelections = lift$ _compatibleFrames, (frames) -> frames.length > 0

  _modelSelectionMessage = lift$ _compatibleFrames, (frames) ->
    if frames.length
      defaultScoringSelectionMessage
    else
      'No compatible datasets found.'

  scoreSelections = ->
    _.promptForFrame _compatibleFrames(), (action, frameKey) ->
      switch action
        when 'confirm'
          scorings = map _selections(), (selection) ->
            frameKey: frameKey
            model: selection.data
            status: null
            time: null
            result: null
            timestamp: Date.now()

          _.switchToScoring type: 'scoring', scorings: scorings
          _.deselectAllModels()
        when 'error'
          _.fail 'Error', 'An error occured while fetching the list of datasets.', error, noop

  tryScoreSelections = (hover) ->
    _.status if hover then _modelSelectionMessage() else null

  clearSelections = ->
    _.deselectAllModels()

  link$ _.modelSelectionChanged, (isSelected, model) ->
    if isSelected
      _selections.push model
    else
      _selections.remove model

  link$ _.modelSelectionCleared, ->
    _selections.removeAll()

  caption: _caption
  hasSelection: _hasSelection
  clearSelections: clearSelections
  canScoreSelections: _canScoreSelections
  tryScoreSelections: tryScoreSelections
  scoreSelections: scoreSelections
  template: 'model-selection-view'

Validate compatible frames for all selected models prior to displaying frame selection dialog. PP-71 PP-82


#= require jiffy_enum
#= require_self

class window.JiffyEnums
  constructor: (@hash) ->

  # equavalent to [] in ruby
  get: (key) =>
    @hash[key]

  each: (func) =>
    _.each(@hash, func)

  all: (func) =>
    _.values(@hash)

  for_value: (value) =>
    _.each( all(), (_enum) ->
      return _enum if value == _enum.value
    )

  for_ordinal: (ordinal) =>
    _.each( all(), (_enum) ->
      return _enum if ordinal == _enum.ordinal
    )

  all_to_hash: () =>
    hash = {}
    each( (_enum, key) ->
      hash[key] = _enum.value
    )
    hash

#= require jiffy_enum
#= require_self

class window.JiffyEnums
  constructor: (@hash) ->

  # equavalent to [] in ruby
  get: (key) =>
    @hash[key]

  each: (func) =>
    _.each(@hash, func)

  all: (func) =>
    _.values(@hash)

  for_value: (value) =>
    _.find( all(), (_enum) ->
      value == _enum.value
    )

  for_ordinal: (ordinal) =>
    _.find( all(), (_enum) ->
      ordinal == _enum.ordinal
    )

  all_to_hash: () =>
    hash = {}
    each( (_enum, key) ->
      hash[key] = _enum.value
    )
    hash

Fix for_value and for_ordinal in JS

Fix for_value and for_ordinal in JS


###
# Copyright 2015 ppy Pty. Ltd.
#
# This file is part of osu!web. osu!web is distributed with the hope of
# attracting more community contributions to the core ecosystem of osu!.
#
# osu!web is free software: you can redistribute it and/or modify
# it under the terms of the Affero GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# osu!web is distributed 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 osu!web.  If not, see <http://www.gnu.org/licenses/>.
###

# How to use:
# 1. create a marker on when it should be fixed, with class including
#    'js-sticky-header' and data attribute 'data-sticky-header-target'
# 2. subscribe to 'stickyHeader' event
# 3. in the function, check if second parameter (first one is unused event
#    object) is the correct target
# 4. stick if matches, unstick otherwise
class @StickyHeader
  stickMarker: document.getElementsByClassName('js-sticky-header')

  constructor: ->
    $(window).on 'scroll', @stickOrUnstick
    $(document).on 'ready page:load osu:page:change', @stickOrUnstick

  stickOrUnstick: =>
    return if @stickMarker.length == 0

    for marker in @stickMarker by -1
      if marker.getBoundingClientRect().top < 0
        $.publish 'stickyHeader', marker.getAttribute('data-sticky-header-target')
        return

    $.publish 'stickyHeader'

Add licence and usage guide

Add licence and usage guide


_ = require 'underscore'
pkg = require '../package.json'

module.exports = (app) ->

  # homepage
  app.get '/', (req, res, next) ->
    res.json _.omit pkg, 'devDependencies'

  # retrieve a link to the generated pdf
  app.post '/api/pdf/url', (req, res, next) ->
    # - generate pdf
    # - respond with JSON containing link to PDF

  # generate and render pdf in the browser
  app.post '/api/pdf/render', (req, res, next) ->
    # - generate pdf
    # - respond with pdf

  # generate and download pdf
  app.post '/api/pdf/download', (req, res, next) ->
    # - generate pdf
    # - respond with download

_ = require 'underscore'
pkg = require '../package.json'

module.exports = (app) ->

  # homepage
  app.get '/', (req, res, next) ->
    res.json _.omit pkg, 'devDependencies'

  # generate and render pdf in the browser
  app.get '/api/pdf/:token', (req, res, next) ->
    res.send 501,
      message: 'Endpoint not implemented yet'

  # retrieve a link to the generated pdf
  app.post '/api/pdf/url', (req, res, next) ->
    # - generate pdf
    # - respond with JSON containing link to PDF

  # generate and render pdf in the browser
  app.post '/api/pdf/render', (req, res, next) ->
    res.send 401,
      message: 'Not authorized'
    # - generate pdf
    # - respond with pdf

  # generate and download pdf
  app.post '/api/pdf/download', (req, res, next) ->
    res.send 401,
      message: 'Not authorized'
    # - generate pdf
    # - respond with download

Define error reponses for unimplemented endpoints


$ ->
  DIC_URL_PREFIX = 'http://alldic.daum.net/search.do?dic=eng&q='
  IMAGES_URL_PREFIX = 'http://images.search.yahoo.com/search/images?p='
  $input = $('input')
  $button = $('button')
  $dicIframe = $('iframe.dic')
  $imagesIframe = $('iframe.images')
  search = ->
    query = $input.val()
    return if query is ''

    $dicIframe.prop 'src', DIC_URL_PREFIX + query
    $imagesIframe.prop 'src', IMAGES_URL_PREFIX + query
    return

  do bindEvents = ->
    $(document).on 'keydown', (e) ->
      NUM_1_KEY = 49
      NUM_2_KEY = 50

      if e.ctrlKey and (e.which is NUM_1_KEY)
        $dicIframe.contentWindow.focus()

      if e.ctrlKey and (e.which is NUM_2_KEY)
        $imagesIframe.contentWindow.focus()

    $input.on 'keydown', (e) ->
      search() if e.which is 13

    $button.click search

  do init = ->
    $input.focus()

$ ->
  DIC_URL_PREFIX = 'http://alldic.daum.net/search.do?dic=eng&q='
  IMAGES_URL_PREFIX = 'https://duckduckgo.com/?%3Fiax=1&iax=1&ia=images&q='
  $input = $('input')
  $button = $('button')
  $dicIframe = $('iframe.dic')
  $imagesIframe = $('iframe.images')
  search = ->
    query = $input.val()
    return if query is ''

    $dicIframe.prop 'src', DIC_URL_PREFIX + query
    $imagesIframe.prop 'src', IMAGES_URL_PREFIX + query
    return

  do bindEvents = ->
    $(document).on 'keydown', (e) ->
      NUM_1_KEY = 49
      NUM_2_KEY = 50

      if e.ctrlKey and (e.which is NUM_1_KEY)
        $dicIframe.contentWindow.focus()

      if e.ctrlKey and (e.which is NUM_2_KEY)
        $imagesIframe.contentWindow.focus()

    $input.on 'keydown', (e) ->
      search() if e.which is 13

    $button.click search

  do init = ->
    $input.focus()

Change from Yahoo to DuckDuckGo

Change from Yahoo to DuckDuckGo


define [
  'phaser'
  'underscore'
  'app/helpers'
], (Phaser, _, Helpers) ->

  'use strict'

  {Keyboard} = Phaser

  class InStateMenu

    constructor: (@textItems, game, options = {}) ->
      {@pauseHandler, @layout, @toggleKeyCode} = _.defaults options,
        layout: { y: 120, baseline: 40 }
        pauseHandler: (paused) -> game.paused = paused
        toggleKeyCode: Keyboard.P

      {@add, @height, @input, @width, @world} = game

      @_initialize()

    _initialize: ->
      @group = @add.group()

      @overlay = @add.graphics 0, 0, @group
      @overlay.beginFill 0x000000, 0.2
      @overlay.drawRect 0, 0, @width, @height
      @overlay.endFill()

      for [text, style] in @textItems
        _.defaults style, { fill: '#fff', font: 'Enriqueta' }
        @addCenteredText text, @layout, style, @group

      @toggleKey = @input.keyboard.addKey @toggleKeyCode
      @toggleKey.onDown.add => @toggle()

      @toggle off

    destroy: ->
      @toggleKey.onDown.removeAll()

    toggle: (toggled) ->
      toggled ?= not @group.visible
      @group.visible = toggled
      @pauseHandler toggled

  _.extend InStateMenu::, Helpers.TextMixin

  InStateMenu

define [
  'phaser'
  'underscore'
  'app/helpers'
], (Phaser, _, Helpers) ->

  'use strict'

  {Keyboard} = Phaser

  class InStateMenu

    constructor: (@textItems, game, options = {}) ->
      {@pauseHandler, @layout, @toggleKeyCode} = _.defaults options,
        layout: { y: 120, baseline: 40 }
        pauseHandler: (paused) -> game.paused = paused
        toggleKeyCode: Keyboard.P

      {@add, @height, @input, @width, @world} = game

      @_initialize()

    _initialize: ->
      @group = @add.group null, 'in-state-menu', yes

      @overlay = @add.graphics 0, 0, @group
      @overlay.beginFill 0x000000, 0.2
      @overlay.drawRect 0, 0, @width, @height
      @overlay.endFill()

      for [text, style] in @textItems
        _.defaults style, { fill: '#fff', font: 'Enriqueta' }
        @addCenteredText text, @layout, style, @group

      @toggleKey = @input.keyboard.addKey @toggleKeyCode
      @toggleKey.onDown.add => @toggle()

      @toggle off

    destroy: ->
      @toggleKey.onDown.removeAll()

    toggle: (toggled) ->
      toggled ?= not @group.visible
      @group.visible = toggled
      @pauseHandler toggled

  _.extend InStateMenu::, Helpers.TextMixin

  InStateMenu

Fix InStateMenu not positioning correctly.

Don't add to world, add to stage. Note that Group#fixedToCamera doesn't
seem to work by itself.


Slack = require('slack-client')
require('events').EventEmitter
config = require('../../../config.json').slack;

class SlackIntegration
  DEFAULT_MESSAGE = "#{player} is playing #{game}. Go join them!"

  constructor: (opts)->
    {
      @token
    } = opts

    @slack = new Slack(@token, true, true)
    @slack.login()
    @slack_channels = []
    @config_channels = config.channels

    @slack.on 'error', (err)->
      console.log 'Slack error!', err

    @slack.on 'open', (data)=>
      @slack_channels = (channel for id, channel of @slack.channels when channel.is_member)

    @slack.on 'message', (message)=>
      channel = @slack.getChannelGroupOrDMByID(message.channel)
      #event.emit()

  sendNotification: (player, game)->
    return if not @config_channels or not @slack_channels

    channels = @getChannelsToNotify(player)

    message = if config.message then formatMessage(config.message, player, game) else formatMessage(DEFAULT_MESSAGE, player, game)

    channel.send(message) for channel in channels

  getChannelsToNotify: (player)=>
    userChannels = (channel for channel in @config_channels when channel.indexOf(player) isnt -1)
    notifyChannels = (channel for channel in @slack_channels when userChannels[channel.name] isnt -1)

    notifyChannels

  formatMessage: (message, player, game)->
    message.replace('#{player}', player) if player
    message.replace('#{game}', game) if game
    message

  module.exports = SlackIntegration

Slack = require('slack-client')
require('events').EventEmitter
config = require('../../../config.json').slack;

class SlackIntegration
  DEFAULT_MESSAGE = '#{player} is playing #{game}. Go join them!'

  constructor: (opts)->
    {
      @token
    } = opts

    @slack = new Slack(@token, true, true)
    @slack.login()
    @slack_channels = []
    @config_channels = config.channels

    @slack.on 'error', (err)->
      console.log 'Slack error!', err

    @slack.on 'open', (data)=>
      @slack_channels = (channel for id, channel of @slack.channels when channel.is_member)

    @slack.on 'message', (message)=>
      channel = @slack.getChannelGroupOrDMByID(message.channel)
      #event.emit()

  sendNotification: (player, game)->
    return if not @config_channels or not @slack_channels

    channels = @getChannelsToNotify(player)

    message = if config.message then formatMessage(config.message, player, game) else formatMessage(DEFAULT_MESSAGE, player, game)

    channel.send(message) for channel in channels

  getChannelsToNotify: (player)=>
    userChannels = (channel for channel in @config_channels when channel.indexOf(player) isnt -1)
    notifyChannels = (channel for channel in @slack_channels when userChannels[channel.name] isnt -1)

    notifyChannels

  formatMessage: (message, player, game)->
    message.replace('#{player}', player)
    message.replace('#{game}', game)
    message

  module.exports = SlackIntegration

Use single quotes to avoid coffeescript parsing string as variable


Slack = require('slack-client')
require('events').EventEmitter
config = require('../../../config.json').slack;

class SlackIntegration

  constructor: (opts)->
    {
      @token
    } = opts

    @slack = new Slack(@token, true, true)
    @slack.login()
    @slack_channels = []
    @config_channels = config.channels

    @slack.on 'error', (err)->
      console.log 'Slack error!', err

    @slack.on 'open', (data)=>
      @slack_channels = (channel for id, channel of @slack.channels when channel.is_member)

    @slack.on 'message', (message)=>
      channel = @slack.getChannelGroupOrDMByID(message.channel)
      #event.emit()

  sendNotification: (player, game)->
    return if not @config_channels or not @slack_channels

    channels = @getChannelsToNotify(player)
    message = config.message.replace('#{player}', player).replace('#{game}', game)
    channel.send(message) for channel in channels

  getChannelsToNotify: (player)=>
    userChannels = (channel for channel in @config_channels when channel.indexOf(player) isnt -1)
    notifyChannels = (channel for channel in @slack_channels when userChannels[channel.name] isnt -1)

    notifyChannels

  module.exports = SlackIntegration

Slack = require('slack-client')
require('events').EventEmitter
config = require('../../../config.json').slack;

class SlackIntegration
  DEFAULT_MESSAGE = "#{player} is playing #{game}. Go join them!"

  constructor: (opts)->
    {
      @token
    } = opts

    @slack = new Slack(@token, true, true)
    @slack.login()
    @slack_channels = []
    @config_channels = config.channels

    @slack.on 'error', (err)->
      console.log 'Slack error!', err

    @slack.on 'open', (data)=>
      @slack_channels = (channel for id, channel of @slack.channels when channel.is_member)

    @slack.on 'message', (message)=>
      channel = @slack.getChannelGroupOrDMByID(message.channel)
      #event.emit()

  sendNotification: (player, game)->
    return if not @config_channels or not @slack_channels

    channels = @getChannelsToNotify(player)

    message = if config.message then formatMessage(config.message, player, game) else formatMessage(DEFAULT_MESSAGE, player, game)

    channel.send(message) for channel in channels

  getChannelsToNotify: (player)=>
    userChannels = (channel for channel in @config_channels when channel.indexOf(player) isnt -1)
    notifyChannels = (channel for channel in @slack_channels when userChannels[channel.name] isnt -1)

    notifyChannels

  formatMessage: (message, player, game)->
    message.replace('#{player}', player) if player
    message.replace('#{game}', game) if game
    message

  module.exports = SlackIntegration

Add default message if none defined in config


# tael.js
# Copyright (c) 2015 Carter Hinsley
# MIT License

module.exports = ->
    ($ document).ready ->
        ($ '.tael-container')
        .append(
            ($ '<div>')
            .addClass 'tael-node-leaf'
            .text 'Hello, world!'
        )

# tael.js
# Copyright (c) 2015 Carter Hinsley
# MIT License

tiles = [{
    type: 'container'
}]

newTile = (parent) ->
    # Add a new tile to the `tiles` array.
    pushTile = ->
        # Push a new tile to the `tiles` array and return its index.
        (
            tiles.push
                type: 'leaf'
        ) - 1
    switch parent.type
        when 'container'
            parent.child = do pushTile
        when 'leaf'
            parent =
                type: 'branch'
                children:
                    left: do pushTile
                    right: do pushTile
                layout:
                    split: 'horizontal'
                    divider_location: 1
        when 'branch'
            throw "Branch tiles cannot spawn new children post-creation."

newTile(tiles[0])

module.exports = ->
    ($ document).ready ->
        ($ '.tael-container')
        .append(
            ($ '<div>')
            .addClass 'tael-node-leaf'
            .text 'Hello, world!'
        )

Add `tiles` array and `newTile` function


helper =
  settingsPath: "#{__dirname}/projects.test.cson"
  savedProjects: null

  readFile: (callback) ->
    callback(helper.projects)

  writeFile: (projects, callback) ->
    helper.projects = projects
    callback?()

  projects:
    testproject1:
      title: "Test project 1"
      group: "Test"
      paths: [
        "/Users/project-1"
      ]
    testproject2:
      title: "Test project 2"
      group: "Test"
      paths: [
        "/Users/project-2"
      ]

helper.savedProjects = Object.keys(helper.projects).length

module.exports = helper

helper =
  settingsPath: "#{__dirname}/projects.test.cson"
  savedProjects: null

  readFile: (callback) ->
    callback(helper.projects)

  writeFile: (projects, callback) ->
    helper.projects = projects
    callback?()

  projects:
    testproject1:
      title: "Test project 1"
      group: "Test"
      paths: [
        "/Users/project-1"
      ]
    testproject2:
      title: "Test project 2"
      paths: [
        "/Users/project-2"
      ]

helper.savedProjects = Object.keys(helper.projects).length

module.exports = helper

Make test projects diff more

Make test projects diff more


gulp      = require 'gulp'
sequence  = require 'gulp-run-sequence'

require('./clean') gulp
require('./coffee') gulp
require('./jade') gulp
require('./scss') gulp
require('./vendor') gulp
require('./watch') gulp
require('./webserver') gulp
require('./specs') gulp

module.exports = (gulp) ->
  gulp.task 'build', ->
    sequence(
      'build:clean'
      [
        'build:scss'
        'build:jade'
        'build:coffee'
        'build:bower'
        'build:copy:scripts'
      ]
      'build:webserver'
      'build:watch'
    )

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

gulp      = require 'gulp'
sequence  = require 'gulp-run-sequence'

require('./clean') gulp
require('./coffee') gulp
require('./jade') gulp
require('./scss') gulp
require('./vendor') gulp
require('./watch') gulp
require('./webserver') gulp
require('./specs') gulp

module.exports = (gulp) ->
  gulp.task 'build', ->
    sequence(
      'build:clean'
      [
        'build:scss'
        'build:jade'
        'build:coffee'
        'build:bower'
        'build:copy:scripts'
      ]
      'build:webserver'
      'build:watch'
    )

  gulp.task 'build:once', ->
    sequence(
      'build:clean'
      [
        'build:scss'
        'build:jade'
        'build:coffee'
        'build:bower'
        'build:copy:scripts'
      ]
    )

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

Add "build:once" task without webserver and watcher


if Meteor.isServer
  Parse = require 'parse/node'
else
  Parse = require 'parse'

exports.Survey = Parse.Object.extend 'Survey',
  getForms: (returnMeteorCollection, collection) ->
    query = @relation('forms').query()
    query.find().then (forms) ->
      if returnMeteorCollection and forms
        formCollection = collection or new Meteor.Collection null
        _.each forms, (form) ->
          props = _.extend {}, form.attributes
          props.parseId = form.id
          formCollection.insert props
        formCollection
      else
        forms

exports.Form = Parse.Object.extend 'Form',
  getLastQuestionOrder: ->
    query = @relation('questions').query()
    query.descending 'order'
    query.select 'order'
    query.first().then (lastQuestion) ->
      lastQuestion?.get('order')

exports.Question = Parse.Object.extend 'Question'

if Meteor.isServer
  Parse = require 'parse/node'
else
  Parse = require 'parse'

exports.Survey = Parse.Object.extend 'Survey',
  getForms: (returnMeteorCollection, collection) ->
    query = @relation('forms').query()
    query.find().then (forms) ->
      if returnMeteorCollection and forms
        formCollection = collection or new Meteor.Collection null
        _.each forms, (form) ->
          props = _.extend {}, form.attributes
          props.parseId = form.id
          formCollection.insert props
        formCollection
      else
        forms

exports.Form = Parse.Object.extend 'Form',
  getQuestions: ->
    query = @relation('questions').query()
    query.find().then (questions) ->
      questions

  getLastQuestionOrder: ->
    query = @relation('questions').query()
    query.descending 'order'
    query.select 'order'
    query.first().then (lastQuestion) ->
      lastQuestion?.get('order')

exports.Question = Parse.Object.extend 'Question'

Add getQuestions method to Form class

Add getQuestions method to Form class


# Description:
#   Find the build status of an open-source project on Travis
#   Can also notify about builds, just enable the webhook notification on travis http://about.travis-ci.org/docs/user/build-configuration/ -> 'Webhook notification'
#
# Dependencies:
#
# Configuration:
#   None
#
# Commands:
#   hubot travis me <user>/<repo> - Returns the build status of https://github.com/<user>/<repo>
#
# URLS:
#   POST /hubot/travis?room=<room>[&type=<type]
#     - for XMPP servers (such as HipChat) this is the XMPP room id which has the form id@server
#
# Author:
#   sferik
#   nesQuick
#   sergeylukin

url = require('url')

module.exports = (robot) ->

  robot.router.post "/hubot/magnum-ci", (req, res) ->

    try
      payload = JSON.parse req.body.payload
      user = {}
      user.room = payload.room if payload.room
      user.type = payload.type if payload.type

      robot.send "#{payload.title}"

    catch error
      console.log "travis hook error: #{error}. Payload: #{req.body.payload}"

    res.end JSON.stringify {
      send: true #some client have problems with and empty response, sending that response ion sync makes debugging easier
    }

# Description:
#   Find the build status of an open-source project on Travis
#   Can also notify about builds, just enable the webhook notification on travis http://about.travis-ci.org/docs/user/build-configuration/ -> 'Webhook notification'
#
# Dependencies:
#
# Configuration:
#   None
#
# Commands:
#   hubot travis me <user>/<repo> - Returns the build status of https://github.com/<user>/<repo>
#
# URLS:
#   POST /hubot/travis?room=<room>[&type=<type]
#     - for XMPP servers (such as HipChat) this is the XMPP room id which has the form id@server
#
# Author:
#   sferik
#   nesQuick
#   sergeylukin

url = require('url')

module.exports = (robot) ->

  robot.router.post "/hubot/magnum-ci", (req, res) ->

    try
      payload = JSON.parse req.body.payload
      user = {}
      user.room = payload.room if payload.room
      user.type = payload.type if payload.type

      robot.messageRoom '#tool-mobile', "#{payload.title}"

    catch error
      console.log "travis hook error: #{error}. Payload: #{req.body.payload}"

    res.end JSON.stringify {
      send: true #some client have problems with and empty response, sending that response ion sync makes debugging easier
    }

Use the slack way of sending message

Use the slack way of sending message


TitleBar = require '../src/title-bar'

describe "TitleBar", ->
  it 'updates the title based on document.title when the active pane item changes', ->
    titleBar = new TitleBar({
      workspace: atom.workspace,
      themes: atom.themes,
      applicationDelegate: atom.applicationDelegate,
    })

    expect(titleBar.element.querySelector('.title').textContent).toBe document.title
    initialTitle = document.title

    atom.workspace.getActivePane().activateItem({
      getTitle: -> 'Test Title'
    })

    expect(document.title).not.toBe(initialTitle)
    expect(titleBar.element.querySelector('.title').textContent).toBe document.title

TitleBar = require '../src/title-bar'

describe "TitleBar", ->
  it "updates the title based on document.title when the active pane item changes", ->
    titleBar = new TitleBar({
      workspace: atom.workspace,
      themes: atom.themes,
      applicationDelegate: atom.applicationDelegate,
    })

    expect(titleBar.element.querySelector('.title').textContent).toBe document.title
    initialTitle = document.title

    atom.workspace.getActivePane().activateItem({
      getTitle: -> 'Test Title'
    })

    expect(document.title).not.toBe(initialTitle)
    expect(titleBar.element.querySelector('.title').textContent).toBe document.title

  it "can update the sheet offset for the current window based on its height", ->
    titleBar = new TitleBar({
      workspace: atom.workspace,
      themes: atom.themes,
      applicationDelegate: atom.applicationDelegate,
    })
    expect(->
      titleBar.updateWindowSheetOffset()
    ).not.toThrow()

Test that updateWindowSheetOffset can be called

Testing the wiring to themes isn't worth it, but this at least makes sure we don't break if Electron APIs change.


App.Store = DS.Store.extend
  revision: 11
  adapter: App.Adapter.create()

App.Store = DS.Store.extend
  revision: 11
  adapter: 'App.Adapter'

Use a string to specify adapter

Use a string to specify adapter


SidebarMachineList = require './sidebarmachinelist'

module.exports = class SidebarSharedMachinesList extends SidebarMachineList

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

    options.title       = 'Shared VMs'
    options.hasPlusIcon = no
    options.cssClass    = 'shared-machines'

    { shared, collaboration } = data

    data.machine.isSharedMachine = yes  for data in shared
    data.machine.isCollaborationMachine = yes  for data in collaboration

    data = shared.concat collaboration

    super options, data

SidebarMachineList = require './sidebarmachinelist'
kd = require 'kd'

module.exports = class SidebarSharedMachinesList extends SidebarMachineList

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

    options.title       = 'Shared VMs'
    options.hasPlusIcon = no
    options.cssClass    = 'shared-machines'

    { shared, collaboration } = data

    data.machine.isSharedMachine = yes  for data in shared
    data.machine.isCollaborationMachine = yes  for data in collaboration

    data = shared.concat collaboration

    super options, data

    @hide()  if data.length is 0

Hide if there is no machine.

SidebarSharedMachinesList: Hide if there is no machine.


module.exports = ->
  highlightSelectedPackage = atom.packages.getLoadedPackage('highlight-selected')

  highlightSelected = require (highlightSelectedPackage.path)
  HighlightedAreaView = require (highlightSelectedPackage.path + '/lib/highlighted-area-view')

  class FakeEditor
    constructor: (@minimap) ->

    getActiveMinimap: -> @minimap.getActiveMinimap()

    getActiveTextEditor: -> @getActiveMinimap()?.getTextEditor()

    ['markBufferRange', 'scanInBufferRange', 'getEofBufferPosition', 'getSelections', 'getLastSelection', 'bufferRangeForBufferRow', 'getTextInBufferRange', 'onDidChangeSelectionRange'].forEach (key) ->
      FakeEditor::[key] = -> @getActiveTextEditor()?[key](arguments...)

    ['decorateMarker'].forEach (key) ->
      FakeEditor::[key] = -> @getActiveMinimap()[key](arguments...)

  class MinimapHighlightSelectedView extends HighlightedAreaView
    constructor: (minimap) ->
      @fakeEditor = new FakeEditor(minimap)
      super

    getActiveEditor: -> @fakeEditor

    handleSelection: ->
      return unless atom.workspace.getActiveTextEditor()?
      return unless @fakeEditor.getActiveTextEditor()?
      super

module.exports = ->
  highlightSelectedPackage = atom.packages.getLoadedPackage('highlight-selected')

  highlightSelected = require (highlightSelectedPackage.path)
  HighlightedAreaView = require (highlightSelectedPackage.path + '/lib/highlighted-area-view')

  class FakeEditor
    constructor: (@minimap) ->

    getActiveMinimap: -> @minimap.getActiveMinimap()

    getActiveTextEditor: -> @getActiveMinimap()?.getTextEditor()

    ['markBufferRange', 'scanInBufferRange', 'getEofBufferPosition', 'getSelections', 'getLastSelection', 'bufferRangeForBufferRow', 'getTextInBufferRange', 'onDidAddSelection', 'onDidChangeSelectionRange'].forEach (key) ->
      FakeEditor::[key] = -> @getActiveTextEditor()?[key](arguments...)

    ['decorateMarker'].forEach (key) ->
      FakeEditor::[key] = -> @getActiveMinimap()[key](arguments...)

  class MinimapHighlightSelectedView extends HighlightedAreaView
    constructor: (minimap) ->
      @fakeEditor = new FakeEditor(minimap)
      super

    getActiveEditor: -> @fakeEditor

    handleSelection: ->
      return unless atom.workspace.getActiveTextEditor()?
      return unless @fakeEditor.getActiveTextEditor()?
      super

:bug: Fix plugin broken by latest highlight-selected update

Fixes #8, Closes #7


module.exports = ->
  chai = require 'chai'
  chai.use require 'chai-as-promised'
  @World.prototype.expect = chai.expect

module.exports = ->
  chai = require 'chai'
  @World.prototype.expect = chai.expect

Remove chai-as-promised; it isn’t working properly.


$(document).ready ->
  # Photo grid
  photoGrid = $(".photo-grid")
  photoGrid.imagesLoaded ->
    photoGrid.trigger "reload:grid"

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

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

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

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

$(document).ready ->
  # Photo grid
  photoGrid = $(".photo-grid")
  photoGrid.imagesLoaded ->
    photoGrid.trigger "reload:grid"

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

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

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

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

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

Fix for slow loading images

Fix for slow loading images


###* @jsx React.DOM ###

window.CwbSimpleInput = React.createClass
  getInitialState: ->
    searchText: ''

  displayedQuery: ->
    ''

  handleTextChange: (e) ->
    console.log('text')
    @setState(searchText: e.target.value)

  handleSearch: (e) ->
    console.log('search')

  render: ->
    `

      <form className="form-inline span12">

          <input type="text" className="searchfield span12" defaultValue={this.state.searchText} onBlur={this.handleTextChange} />
          <button type="button" className="btn btn-success" onClick={this.handleSearch}>Search</button>

      </form>

`

###* @jsx React.DOM ###

window.CwbSimpleInput = React.createClass
  propTypes:
    query: React.PropTypes.string.isRequired
    handleQueryChanged: React.PropTypes.func.isRequired

  displayedQuery: ->
    # Take the CQP expression and just remove quotes
    @props.query.replace(/"/g, '')

  handleTextChange: (e) ->
    # Wrap each search term in quotes
    query = ("\"#{term}\"" for term in e.target.value.split(/\s+/)).join(' ')
    @props.handleQueryChanged(query)

  handleSearch: (e) ->
    console.log('search')

  render: ->
    `

      <form className="form-inline span12">

          <input type="text" className="searchfield span12" value={this.displayedQuery()} onChange={this.handleTextChange} />
          <button type="button" className="btn btn-success" onClick={this.handleSearch}>Search</button>

      </form>

`

Convert to and from underlying query in CwbSimpleInput


{$$, BufferedNodeProcess} = require 'atom'

module.exports =
  activate: ->
    atom.workspaceView.command 'update-package-dependencies:update', => @update()

  update: ->
    view = @createProgressView()
    atom.workspaceView.append(view)

    command = atom.packages.getApmPath()
    args = ['install']
    options = {cwd: atom.project.getPath()}
    exit = (code, signal) ->
      atom.workspaceView.one 'core:cancel', -> view.remove()
      view.empty().focus().on 'focusout', -> view.remove()

      success = (code == 0)
      if success
        view.append $$ ->
          @div class: 'text-success', 'Package depencencies updated.'
      else
        view.append $$ ->
          @div class: 'text-error', 'Failed to update package depencencies.'

    new BufferedNodeProcess({command, args, exit, options})

  createProgressView: ->
    $$ ->
      @div tabindex: -1, class: 'overlay from-top', =>
        @span class: 'loading loading-spinner-small inline-block'
        @span "Updating package dependencies\u2026"

{$$, BufferedProcess} = require 'atom'

module.exports =
  activate: ->
    atom.workspaceView.command 'update-package-dependencies:update', => @update()

  update: ->
    view = @createProgressView()
    atom.workspaceView.append(view)

    command = atom.packages.getApmPath()
    args = ['install']
    options = {cwd: atom.project.getPath()}
    exit = (code, signal) ->
      atom.workspaceView.one 'core:cancel', -> view.remove()
      view.empty().focus().on 'focusout', -> view.remove()

      success = (code == 0)
      if success
        view.append $$ ->
          @div class: 'text-success', 'Package depencencies updated.'
      else
        view.append $$ ->
          @div class: 'text-error', 'Failed to update package depencencies.'

    new BufferedProcess({command, args, exit, options})

  createProgressView: ->
    $$ ->
      @div tabindex: -1, class: 'overlay from-top', =>
        @span class: 'loading loading-spinner-small inline-block'
        @span "Updating package dependencies\u2026"

Use BufferedProcess instead of BufferedNodeProcess


{Range} = require('atom')
path = require 'path'
child_process = require('child_process')

Helpers = module.exports =
  error: (e) ->
    atom.notifications.addError(e.toString(), {detail: e.stack or '', dismissable: true})
  shouldTriggerLinter: (linter, onChange, scopes) ->
    # Trigger lint-on-Fly linters on both events but on-save linters only on save
    # Because we want to trigger onFly linters on save when the
    # user has disabled lintOnFly from config
    return false if onChange and not linter.lintOnFly
    return false unless scopes.some (entry) -> entry in linter.grammarScopes
    return true
  requestUpdateFrame: (callback) ->
    setTimeout(callback, 100)
  debounce: (callback, delay) ->
    timeout = null
    return (arg) ->
      clearTimeout(timeout)
      timeout = setTimeout(() =>
        callback.call(this, arg)
      , delay)
  isPathIgnored: (filePath) ->
    repo = null
    for projectPath, i in atom.project.getPaths()
      if filePath.indexOf(projectPath + path.sep) is 0
        repo = atom.project.getRepositories()[i]
        break
    return true if repo and repo.isProjectAtRoot() and repo.isPathIgnored(filePath)
    return false

{Range} = require('atom')
path = require 'path'
child_process = require('child_process')
minimatch = require('minimatch')

Helpers = module.exports =
  error: (e) ->
    atom.notifications.addError(e.toString(), {detail: e.stack or '', dismissable: true})
  shouldTriggerLinter: (linter, onChange, scopes) ->
    # Trigger lint-on-Fly linters on both events but on-save linters only on save
    # Because we want to trigger onFly linters on save when the
    # user has disabled lintOnFly from config
    return false if onChange and not linter.lintOnFly
    return false unless scopes.some (entry) -> entry in linter.grammarScopes
    return true
  requestUpdateFrame: (callback) ->
    setTimeout(callback, 100)
  debounce: (callback, delay) ->
    timeout = null
    return (arg) ->
      clearTimeout(timeout)
      timeout = setTimeout(() =>
        callback.call(this, arg)
      , delay)
  isPathIgnored: (filePath) ->
    repo = null
    for projectPath, i in atom.project.getPaths()
      if filePath.indexOf(projectPath + path.sep) is 0
        repo = atom.project.getRepositories()[i]
        break
    return true if repo and repo.isProjectAtRoot() and repo.isPathIgnored(filePath)
    return minimatch(atom.config.get('linter.ignoreMatchedFiles'), filePath)

:new: Add minimatch to ignore files matching glob


program = require 'commander'
msgflo_nodejs = require 'msgflo-nodejs'
fs = require 'fs'
path = require 'path'
foreigner = require '../foreign-participant'
yaml = require 'js-yaml'

onError = (err) ->
  console.log err
  process.exit 1

onComplete = ->
  process.exit 0

main = ->
  program
    .option('--broker <uri>', 'Broker address', String, 'amqp://localhost')
    .usage('[options] <definition>')
    .parse(process.argv)

  defPath = path.resolve process.cwd(), program.args[0]
  fs.readFile defPath, 'utf-8', (err, contents) ->
    return onError err if err
    return onError "No definition found in #{defPath}" unless contents
    try
      definition = yaml.safeLoad contents
    catch e
      return onError e
    definition.id = path.basename defPath, path.extname defPath unless definition.id
    definition.role = path.basename defPath, path.extname defPath unless definition.role

    inPorts = definition.inports or {}
    definition.inports = Object.keys(inPorts).map (id) ->
      def = inPorts[id]
      def.id = id
      def
    outPorts = definition.outports or {}
    definition.outports = Object.keys(outPorts).map (id) ->
      def = outPorts[id]
      def.id = id
      def

    foreigner.register program.broker, definition, (err) ->
      return onError err if err
      onComplete()

exports.main = main

program = require 'commander'
msgflo_nodejs = require 'msgflo-nodejs'
fs = require 'fs'
path = require 'path'
foreigner = require '../foreign-participant'
yaml = require 'js-yaml'

onError = (err) ->
  console.log err
  process.exit 1

onComplete = ->
  process.exit 0

main = ->
  program
    .option('--broker <uri>', 'Broker address', String, 'amqp://localhost')
    .usage('[options] <definition>')
    .parse(process.argv)

  defPath = path.resolve process.cwd(), program.args[0]
  fs.readFile defPath, 'utf-8', (err, contents) ->
    return onError err if err
    return onError "No definition found in #{defPath}" unless contents
    try
      definition = yaml.safeLoad contents
    catch e
      return onError e
    definition.id = path.basename defPath, path.extname defPath unless definition.id
    definition.role = path.basename defPath, path.extname defPath unless definition.role

    inPorts = definition.inports or {}
    definition.inports = Object.keys(inPorts).map (id) ->
      def = inPorts[id]
      def.id = id
      def
    outPorts = definition.outports or {}
    definition.outports = Object.keys(outPorts).map (id) ->
      def = outPorts[id]
      def.id = id
      def

    messaging = msgflo_nodejs.transport.getClient program.broker
    messaging.connect (err) ->
      return onError err if err
      foreigner.register messaging, definition, (err) ->
        return onError err if err
        onComplete()

exports.main = main

Connect to broker before registering

Connect to broker before registering


make_element = (name, v) ->
  e = $ "<#{name}>"
  e.append v

for n in ["label", "div", "span", "button", "img", "figure", "figcaption",
          "h1", "h2", "h3",
          "table", "thead", "tfoot", "tbody", "tr", "th", "td",
          "form", "select", "option"]
  @[n] = do (n) -> (v) -> make_element n, v

make_element = (name, v) ->
  e = $ "<#{name}>"
  e.append v

# Make HTML element constructors of the same names as the elements.
for n in [# Root element
          "html",
          # Document metadata
          "head", "title", "base", "link", "meta", "style",
          # Scripting
          "script", "noscript", "template",
          # Sections
          "body", "section", "nav", "article", "aside",
          "h1", "h2", "h3", "h4", "h5", "h6",
          "header", "footer", "address", "main",
          # Grouping content
          "p", "hr", "pre", "blockquote", "ol", "ul", "li", "dl",
          "dt", "dd", "figure", "figcaption", "div",
          # Text-level semantics
          "a", "em", "strong", "small", "s", "cite", "q", "dfn",
          "abbr", "data", "time", "code", #"var",
          "samp", "kdb", "sub", "sup", "i", "b", "u", "mark",
          "ruby", "rt", "rp", "bdi", "bdo", "span", "br", "wbr",
          # Edit
          "ins", "del",
          # Embedded content
          "img", "iframe", "embed", "object", "param", "video",
          "audio", "source", "track", "canvas", "map", "area",
          "svg", "math",
          # Tabular data
          "table", "caption", "colgroup", "col", "tbody", "thead",
          "tfoot", "tr", "td", "th",
          # Forms
          "form", "fieldset", "legend", "label", "input", "button",
          "select", "datalist", "optgroup", "option", "textarea",
          "keygen", "output", "progress", "meter",
          # Interactive elements.
          "details", "summary", "meuitem", "menu"]
  @[n] = do (n) -> (v) -> make_element n, v

Make constructors for all HTML5 elements.


$(document).on 'page:change', ->
  if window._gaq?
    _gaq.push ['_trackPageview']
  else if window.pageTracker?
    pageTracker._trackPageview()

if window.history?.pushState and window.history.replaceState
  document.addEventListener 'page:change', (event) =>

  # Google Analytics
  if window.ga != undefined
    ga('set', 'location', location.href.split('#')[0])
    ga('send', 'pageview', {"title": document.title})
  else if window._gaq != undefined
    _gaq.push(['_trackPageview'])
  else if window.pageTracker != undefined
    pageTracker._trackPageview();

Update Google Analytics script to reflect location of the user


[
  {
    title: "CDS-411 Instructors"
    group: "CDS-411"
    paths: [
      "~/Courses/CDS-411/instructors"
    ]
  }
  {
    title: "Spyns"
    group: "Development"
    paths: [
      "~/Development/spyns"
    ]
  }
  {
    title: "CSI-702 Spr17: Homework02 Instructor Attempt"
    group: "CSI-702"
    paths: [
      "~/Documents/work/teaching/2017_Spring_Semester/CSI-702_High_Performance_Computing/assignments/homework02-instructor-attempt"
    ]
  }
  {
    title: "JS Random Walk"
    group: "Development"
    paths: [
      "~/Development/js-random-walk"
    ]
  }
]

[
  {
    title: "CDS-411 Instructors"
    group: "CDS-411"
    paths: [
      "~/Courses/CDS-411/instructors"
    ]
  }
  {
    title: "Spyns"
    group: "Development"
    paths: [
      "~/Development/spyns"
    ]
  }
  {
    title: "CSI-702 Spr17: Homework02 Instructor Attempt"
    group: "CSI-702"
    paths: [
      "~/Documents/work/teaching/2017_Spring_Semester/CSI-702_High_Performance_Computing/assignments/homework02-instructor-attempt"
    ]
  }
  {
    title: "ising.js"
    group: "teaching"
    paths: [
      "~/Courses/CDS-101/simulations/ising-model"
    ]
  }
]

Add javascript Ising Model as project

Add javascript Ising Model as project


class Lanes.Components.Grid.Selections
    id: 'selected'
    query: false
    textAlign: 'center'
    fixedWidth: 90
    defaultClicked: true
    constructor: (options) ->
        @onChange = options.onChange
        @choices = {}
        _.bindAll(@, 'onColumnClick')
        @render = _.partial(@render, _, @)

    onColumnClick: (ev, {rowNum, field, query}) ->
        unless ev.target.tagName is 'INPUT'
            input = ev.target.querySelector('input')
            input.checked = !input.checked
            @select({target: input}, @, query.results, rowNum)
        ev.stopPropagation()

    select: (ev, me, results, index) ->
        x = results.xtraData(index)
        x.selected = ev.target.checked
        me.onChange?(index)

    render: (props, me) ->
        id = props.row[props.query.idIndex]
        x = props.query.results.xtraData(props.index)
        x.selected = me.defaultClicked unless x.selected?
        <input type="checkbox" defaultChecked={x.selected}
            onChange={_.partial(me.select, _, me, props.query.results, props.index)} />

class CheckBox extends Lanes.React.BaseComponent
    d: -> @props.query.results.xtraData(@props.row)

    onChange: (ev) -> #, me, results, index) ->
        @d().selected = ev.target.checked
        @props.selections.onChange?(@props)
        @forceUpdate()

    render: ->
        selected = @d().selected
        selected = @props.selections.selectionDefault unless selected?
        <input type="checkbox" checked={selected} onChange={@onChange} />

class Lanes.Components.Grid.Selections
    id: 'selected'
    query: false
    textAlign: 'center'
    fixedWidth: 90
    selectionDefault: true
    sortBy: (row, indx, all) ->
        false == this.xtraData(indx)?.selected

    constructor: (options) ->
        @onChange = options.onChange
        @choices = {}
        _.bindAll(@, 'onColumnClick')
        @component = _.partial(@component, _, @)

    onColumnClick: (ev, {rowNum, field, query}) ->
        unless ev.target.tagName is 'INPUT'
            input = ev.target.querySelector('input')
            input.checked = !input.checked
            @select({target: input}, @, query.results, rowNum)
        ev.stopPropagation()

    component: (props, me) ->
        <CheckBox {...props} selections={me} />

Break logic out into a CheckBox component


'use strict'

apiResource = ($resource, resource, args) ->
  $resource "/api/#{resource}/:id"
  , # Default arguments
    args
  , # Override methods
    query:
      method: 'GET'
      isArray: false

angular.module('taarifaWaterpointsApp')
  .factory 'Waterpoint', ($resource) ->
    apiResource $resource, 'waterpoints',
      projection:
        _id: 1
        district: 1
        latitude: 1
        longitude: 1
        wpt_code: 1
        status: 1

'use strict'

apiResource = ($resource, resource, args) ->
  $resource "/api/#{resource}/:id"
  , # Default arguments
    args
  , # Override methods
    query:
      method: 'GET'
      isArray: false
    update:
      method: 'PUT'

angular.module('taarifaWaterpointsApp')
  .factory 'Waterpoint', ($resource) ->
    apiResource $resource, 'waterpoints',
      projection:
        _id: 1
        district: 1
        latitude: 1
        longitude: 1
        wpt_code: 1
        status: 1

Add update method using PUT to resource factory


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

    propTypes:
        onModelSet: React.PropTypes.func
        commands:   React.PropTypes.object
        autoFocus:  React.PropTypes.bool
        name:       React.PropTypes.string
        selectField:   React.PropTypes.bool

    getDefaultProps: ->
        autoFocus: false, label: 'Project Code', name: 'code'

    dataObjects:
        query: ->
            new Lanes.Models.Query({
                syncOptions:
                    include: [ 'customer', 'sku' ]
                src: Skr.Models.CustomerProject, fields: [
                    {id:'id', visible: false}
                    { id: 'code', fixedWidth: 120 }
                    { id: 'description', flex: 1 }
                    { id: 'notes', flex: 1.5 }
                ]
            })

    select: (model, proj) ->
        if @props.onModelSet
            @props.onModelSet(proj)
        else
            model.set(customer_project: proj)

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

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

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

    propTypes:
        onModelSet: React.PropTypes.func
        commands:   React.PropTypes.object
        autoFocus:  React.PropTypes.bool
        name:       React.PropTypes.string
        selectField:   React.PropTypes.bool

    getDefaultProps: ->
        autoFocus: false, label: 'Project Code', name: 'code'

    dataObjects:
        query: ->
            new Lanes.Models.Query({
                syncOptions:
                    include: [ 'customer', 'sku' ]
                    with: ['with_details']
                title: 'Customer Project'
                src: Skr.Models.CustomerProject, fields: [
                    { id:'id', visible: false     }
                    { id: 'code', fixedWidth: 120 }
                    { id: 'po_num', flex: 1       }
                    { id: 'description', flex: 2  }
                    { id: 'customer_code', fixedWidth: 120 }
                ]
            })

    select: (model, proj) ->
        if @props.onModelSet
            @props.onModelSet(proj)
        else
            model.set(customer_project: proj)

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

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

Update fields that are shown

Update fields that are shown


BaseStackEditorView = require './basestackeditorview'

module.exports = class StackTemplateEditorView extends BaseStackEditorView

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

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

    super options, data

    @on 'EditorReady', =>
      return  if options.inEditMode

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

      """
      @aceView.ace.editor.session.insert position, content

StackTemplateEditorView: Put introduction text into editor when ready.


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Fix issue where not all arguments would be pushed to GA


class Controller
	_redirecting: false

	constructor: (@request, @response, view, layout) ->
		View = Import 'class.View$cs'
		@view = new View view, @response
		@view.setLayout layout

	beforeLoad: ->

	beforeRender: ->

	redirect: (args...) ->
		if args.length is 2
			@response.redirect args[0], args[1]
		else
			@response.redirect args[0]
		@_redirecting = true

	render: (viewFile) ->
		viewFile ?= null
		if not @_redirecting then @view.render viewFile

	getQuery: (param, def) ->
		def ?= null
		return @request.query if typeof param is 'undefined' or not param?
		param = @request.query[param]
		if typeof param is 'undefined' then return def
		param

	getPost: (param, def) ->
		def ?= null
		return @request.body if typeof param is 'undefined' or not param?
		param = @request.body[param]
		if typeof param is 'undefined' then return def
		param

	getParam: (param, def) ->
		def ?= null
		param = @request.param param
		if typeof param is 'undefined' then return def
		param

module.exports = Controller

class Controller
	_redirecting: false

	constructor: (@request, @response, view, layout) ->
		View = Import 'class.View$cs'
		@view = new View view, @response
		@view.setLayout layout

	beforeAction: ->

	beforeRender: ->

	redirect: (args...) ->
		if args.length is 2
			@response.redirect args[0], args[1]
		else
			@response.redirect args[0]
		@_redirecting = true

	render: (viewFile) ->
		viewFile ?= null
		if not @_redirecting then @view.render viewFile

	getQuery: (param, def) ->
		def ?= null
		return @request.query if typeof param is 'undefined' or not param?
		param = @request.query[param]
		if typeof param is 'undefined' then return def
		param

	getPost: (param, def) ->
		def ?= null
		return @request.body if typeof param is 'undefined' or not param?
		param = @request.body[param]
		if typeof param is 'undefined' then return def
		param

	getParam: (param, def) ->
		def ?= null
		param = @request.param param
		if typeof param is 'undefined' then return def
		param

module.exports = Controller

Update base controller to use new beforeLoad api


toggleQuotes = (editor) ->
  editor.transact ->
    for cursor in editor.getCursors()
      position = cursor.getBufferPosition()
      toggleQuoteAtPosition(editor, position)
      cursor.setBufferPosition(position)

toggleQuoteAtPosition = (editor, position) ->
  range = editor.displayBuffer.bufferRangeForScopeAtPosition('.string.quoted', position)
  return unless range?

  text = editor.getTextInBufferRange(range)
  quoteCharacter = text[0]
  oppositeQuoteCharacter = getOppositeQuote(quoteCharacter)
  quoteRegex = new RegExp(quoteCharacter, 'g')
  escapedQuoteRegex = new RegExp("\\\\#{quoteCharacter}", 'g')
  oppositeQuoteRegex = new RegExp(oppositeQuoteCharacter, 'g')

  newText = text
    .replace(oppositeQuoteRegex, "\\#{oppositeQuoteCharacter}")
    .replace(escapedQuoteRegex, quoteCharacter)
  newText = oppositeQuoteCharacter + newText[1...-1] + oppositeQuoteCharacter

  editor.setTextInBufferRange(range, newText)

getOppositeQuote = (quoteCharacter) ->
  if quoteCharacter is '"'
    "'"
  else
    '"'

module.exports =
  activate: ->
    atom.workspaceView.command 'toggle-quotes:toggle', '.editor', ->
      editor = atom.workspace.getActiveEditor()
      toggleQuotes(editor)

  toggleQuotes: toggleQuotes

toggleQuotes = (editor) ->
  editor.transact ->
    for cursor in editor.getCursors()
      position = cursor.getBufferPosition()
      toggleQuoteAtPosition(editor, position)
      cursor.setBufferPosition(position)

toggleQuoteAtPosition = (editor, position) ->
  range = editor.displayBuffer.bufferRangeForScopeAtPosition('.string.quoted', position)

  unless range?
    # Attempt to match the current invalid region if it is wrapped in quotes
    # This is useful for languages where changing the quotes makes the range
    # invalid and so toggling again should properly restore the valid quotes
    if range = editor.displayBuffer.bufferRangeForScopeAtPosition('.invalid.illegal', position)
      return unless /^(".*"|'.*')$/.test(editor.getTextInBufferRange(range))

  return unless range?

  text = editor.getTextInBufferRange(range)
  quoteCharacter = text[0]
  oppositeQuoteCharacter = getOppositeQuote(quoteCharacter)
  quoteRegex = new RegExp(quoteCharacter, 'g')
  escapedQuoteRegex = new RegExp("\\\\#{quoteCharacter}", 'g')
  oppositeQuoteRegex = new RegExp(oppositeQuoteCharacter, 'g')

  newText = text
    .replace(oppositeQuoteRegex, "\\#{oppositeQuoteCharacter}")
    .replace(escapedQuoteRegex, quoteCharacter)
  newText = oppositeQuoteCharacter + newText[1...-1] + oppositeQuoteCharacter

  editor.setTextInBufferRange(range, newText)

getOppositeQuote = (quoteCharacter) ->
  if quoteCharacter is '"'
    "'"
  else
    '"'

module.exports =
  activate: ->
    atom.workspaceView.command 'toggle-quotes:toggle', '.editor', ->
      editor = atom.workspace.getActiveEditor()
      toggleQuotes(editor)

  toggleQuotes: toggleQuotes

Handle toggling quoted invalid regions

Handle toggling quoted invalid regions


{File} = require 'file-utils'
fs = require 'fs'

class LocaleTempFileRepository

  items : null

  constructor : (@items = {}) ->
    setInterval (=> @gc()), 60000

  gc : ->
    console.log 'LocaleTempFileRepository.gc'
    now = new Date()
    validUntil = now - 60
    for id, item of @items #when item.created < validUntil
      filePath = @items[id].filePath
      console.info item.created.getTime(), validUntil
      console.log "LocaleTempFileRepository.gc >> Deleting #{filePath}..."
      @remove id
    return

  add : (id) ->
    @items[id] =
      filePath : new File('../' + id).getAbsolutePath()
      created : new Date()

  remove : (id) ->
    if @items[id]
      fs.unlink @items[id].filePath, => delete @items[id]
    return

  exist : (id) ->
    @items[id] isnt undefined

  get : (id) ->
    if @exist id
      @items[id].filePath

exports.LocaleTempFileRepository = LocaleTempFileRepository

{File} = require 'file-utils'
fs = require 'fs'

class LocaleTempFileRepository

  items : null

  constructor : (@items = {}) ->
    setInterval (=> @gc()), 60000

  gc : ->
    console.log 'LocaleTempFileRepository.gc'
    now = new Date()
    validUntil = now - 60
    for id, item of @items when item.created.getTime() < validUntil
      filePath = @items[id].filePath
      console.log "LocaleTempFileRepository.gc >> Deleting #{filePath}..."
      @remove id
    return

  add : (id) ->
    @items[id] =
      filePath : new File('../' + id).getAbsolutePath()
      created : new Date()

  remove : (id) ->
    if @items[id]
      fs.unlink @items[id].filePath, => delete @items[id]
    return

  exist : (id) ->
    @items[id] isnt undefined

  get : (id) ->
    if @exist id
      @items[id].filePath

exports.LocaleTempFileRepository = LocaleTempFileRepository

Delete only files which are generated at least 60 seconds ago.