window.App ||= {}

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

$(document).ready ->

  $body = $('body')

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

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

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

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

window.App ||= {}

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

$(document).ready ->

  $body = $('body')

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

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

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

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

Fix body class check to avoid initialize Visualization or Story classes in templates different to show or edit


{CompositeDisposable} = require 'atom'

module.exports =
class MinimapPigmentsBinding
  constructor: ({@editor, @minimap, @colorBuffer}) ->
    @displayedMarkers = []
    @decorationsByMarkerId = {}
    @subscriptionsByMarkerId = {}

    @subscriptions = new CompositeDisposable

    @colorBuffer.initialize().then => @updateMarkers()

    @subscriptions.add @colorBuffer.editor.displayBuffer.onDidTokenize =>
      @updateMarkers()
    @subscriptions.add @colorBuffer.onDidUpdateColorMarkers =>
      @updateMarkers()

    @decorations = []

  updateMarkers: ->
    markers = @colorBuffer.findValidColorMarkers()

    for m in @displayedMarkers when m not in markers
      @decorationsByMarkerId[m.id]?.destroy()

    for m in markers when m.color?.isValid() and m not in @displayedMarkers
      decoration = @minimap.decorateMarker(m.marker, type: 'highlight', color: m.color.toCSS())

      @decorationsByMarkerId[m.id] = decoration
      @subscriptionsByMarkerId[m.id] = decoration.onDidDestroy =>
        @subscriptionsByMarkerId[m.id]?.dispose()
        delete @subscriptionsByMarkerId[m.id]
        delete @decorationsByMarkerId[m.id]

    @displayedMarkers = markers

  destroy: ->
    @destroyDecorations()
    @subscriptions.dispose()

  destroyDecorations: ->
    sub?.dispose() for id,sub of @subscriptionsByMarkerId
    decoration?.destroy() for id,decoration of @decorationsByMarkerId

    @decorationsByMarkerId = {}
    @subscriptionsByMarkerId = {}

{CompositeDisposable} = require 'atom'

module.exports =
class MinimapPigmentsBinding
  constructor: ({@editor, @minimap, @colorBuffer}) ->
    @displayedMarkers = []
    @decorationsByMarkerId = {}
    @subscriptionsByMarkerId = {}

    @subscriptions = new CompositeDisposable

    @colorBuffer.initialize().then => @updateMarkers()

    @subscriptions.add @colorBuffer.editor.displayBuffer.onDidTokenize =>
      @updateMarkers()
    @subscriptions.add @colorBuffer.onDidUpdateColorMarkers =>
      @updateMarkers()

    @decorations = []

  updateMarkers: ->
    markers = @colorBuffer.findValidColorMarkers()

    for m in @displayedMarkers when m not in markers
      @decorationsByMarkerId[m.id]?.destroy()

    for m in markers when m.color?.isValid() and m not in @displayedMarkers
      decoration = @minimap.decorateMarker(m.marker, type: 'highlight', color: m.color.toCSS(), plugin: 'pigments')

      @decorationsByMarkerId[m.id] = decoration
      @subscriptionsByMarkerId[m.id] = decoration.onDidDestroy =>
        @subscriptionsByMarkerId[m.id]?.dispose()
        delete @subscriptionsByMarkerId[m.id]
        delete @decorationsByMarkerId[m.id]

    @displayedMarkers = markers

  destroy: ->
    @destroyDecorations()
    @subscriptions.dispose()

  destroyDecorations: ->
    sub?.dispose() for id,sub of @subscriptionsByMarkerId
    decoration?.destroy() for id,decoration of @decorationsByMarkerId

    @decorationsByMarkerId = {}
    @subscriptionsByMarkerId = {}

Add plugin origin on created markers

Add plugin origin on created markers


fs = require 'fs'
PEG = require 'pegjs'

module.exports =
class CommandInterpreter
  constructor: ->
    @parser = PEG.buildParser(fs.read(require.resolve 'command-interpreter/commands.pegjs'))

  eval: (editor, string) ->
    command = @parser.parse(string)
    @lastRelativeAddress = command if command.isRelativeAddress()
    command.execute(editor)

  repeatRelativeAddress: (editor) ->
    @lastRelativeAddress?.execute(editor)

fs = require 'fs'
PEG = require 'pegjs'

module.exports =
class CommandInterpreter
  constructor: ->
    @parser = PEG.buildParser(fs.read(require.resolve 'command-interpreter/commands.pegjs'))

  eval: (editor, string) ->
    compositeCommand = @parser.parse(string)
    @lastRelativeAddress = compositeCommand if compositeCommand.isRelativeAddress()
    compositeCommand.execute(editor)

  repeatRelativeAddress: (editor) ->
    @lastRelativeAddress?.execute(editor)

Rename command to compositCommand in command interpreter


define ->
  class Biskoto
    @get: (name) ->
      if document.cookie
        cookies = decodeURIComponent(document.cookie).split(/;\s/g)

        for cookie in cookies
          if cookie.indexOf(name) is 0
            return cookie.split('=')[1]

      return null

  return Biskoto

define ->
  class Biskoto
    encode = encodeURIComponent
    decode = decodeURIComponent

    @get: (name) ->
      if document.cookie
        cookies = decode(document.cookie).split(/;\s/g)

        for cookie in cookies
          if cookie.indexOf(name) is 0
            return cookie.split('=')[1]

      return null

    @set: (name, value, options = {}) ->
      if typeof value is 'string'
        json_value = value
      else
        json_value = JSON.stringify(value)

      document.cookie = "#{name}=#{json_value}#{@_cookieOptions(options)}"

    @expire: (name, options = {}) ->
      options.expires = -1
      @set(name, '', options)

    ###
      options = {
        expires : Integer (seconds)
        secure  : Boolean
        domain  : String
        path    : String
      }
    ###
    @_cookieOptions: (options = {}) ->
      cookie_str = ''

      for key, value of options
        if key is 'expires'
          cookie_str += "; expires=#{@_createExpireDate(options.expires)}"
        else if key is 'domain'
          cookie_str += "; domain=#{value}"

      cookie_str += "; path=#{if options.path then options.path else '/'}"

    @_createExpireDate: (seconds) ->
      new Date(
        +new Date() + (seconds * 1000)
      ).toUTCString()

  window.Biskoto = Biskoto
  return Biskoto

Add .get() and .expire() methods to Biskoto


H2O.PredictOutput = (_, _go, prediction) ->
  { frame, model } = prediction
  _isBinomial = signal prediction.model_category is 'Binomial'
  _isMultinomial = signal prediction.model_category is 'Multinomial'
  _isRegression = signal prediction.model_category is 'Regression'
  _isClustering = signal prediction.model_category is 'Clustering'

  _predictionRecord = signal null
  _rocCurve = signal null

  #_predictionTable = _.inspect 'prediction', prediction

  renderPlot = (target, render) ->
    render (error, vis) ->
      if error
        debug error
      else
        target vis.element

  if _isBinomial()
    renderPlot _predictionRecord, _.enumerate _.inspect 'Prediction', prediction
    renderPlot _rocCurve, _.plot (g) ->
      g(
        g.path g.position 'FPR', 'TPR'
        g.from _.inspect 'Confusion Matrices', prediction
      )

  inspect = ->
    #XXX get this from prediction table
    _.insertAndExecuteCell 'cs', "inspect getPrediction model: #{stringify model.name}, frame: #{stringify frame.name}"

  viewPredictionFrame = ->
    _.insertAndExecuteCell 'cs', "getFrame #{stringify prediction.predictions.key.name}"

  defer _go

  isBinomial: _isBinomial
  isMultinomial: _isMultinomial
  isRegression: _isRegression
  isClustering: _isClustering
  predictionRecord: _predictionRecord
  rocCurve: _rocCurve
  inspect: inspect
  viewPredictionFrame: viewPredictionFrame
  template: 'flow-predict-output'

H2O.PredictOutput = (_, _go, prediction) ->
  { frame, model } = prediction
  _isBinomial = signal prediction.model_category is 'Binomial'
  _isMultinomial = signal prediction.model_category is 'Multinomial'
  _isRegression = signal prediction.model_category is 'Regression'
  _isClustering = signal prediction.model_category is 'Clustering'

  _predictionRecord = signal null
  _rocCurve = signal null

  #_predictionTable = _.inspect 'prediction', prediction

  renderPlot = (target, render) ->
    render (error, vis) ->
      if error
        debug error
      else
        target vis.element

  if _isBinomial()
    renderPlot _predictionRecord, _.enumerate _.inspect 'Prediction', prediction
    renderPlot _rocCurve, _.plot (g) ->
      g(
        g.path g.position 'FPR', 'TPR'
        g.line(
          g.position (g.value 1), (g.value 0)
          g.strokeColor g.value 'red'
        )
        g.from _.inspect 'Confusion Matrices', prediction
      )

  inspect = ->
    #XXX get this from prediction table
    _.insertAndExecuteCell 'cs', "inspect getPrediction model: #{stringify model.name}, frame: #{stringify frame.name}"

  viewPredictionFrame = ->
    _.insertAndExecuteCell 'cs', "getFrame #{stringify prediction.predictions.key.name}"

  defer _go

  isBinomial: _isBinomial
  isMultinomial: _isMultinomial
  isRegression: _isRegression
  isClustering: _isClustering
  predictionRecord: _predictionRecord
  rocCurve: _rocCurve
  inspect: inspect
  viewPredictionFrame: viewPredictionFrame
  template: 'flow-predict-output'

Add random chance line to RoC chart HEXDEV-168


class @VoteController extends RouteController

  waitOn: ->
    q = {}
    if filterType = @params.filterType
      q.type = filterType
    if filterTag = @params.filterTag
      q.tags = filterTag
    Meteor.subscribe('proposals-min', q)

  after: -> document.title = "Vote | Reversim Summit 2014"

  tempalte: 'vote'

  data: ->
    speakers = User.allSpeakers()
    if speakers and speakers.length > 0
      user = User.current()
      speakers = if user and (user.admin() or user.moderator()) then sort(speakers) else _.shuffle(speakers)
    return {
      page: 'vote'
      speakers: speakers
      filterType: @params.filterType
      filterTag: @params.filterTag
    }

sort = (speakers) ->
  _.sortBy(speakers, (speaker) ->
    - sum(speaker.proposals().map((p) -> p.voteCount()))
  )

sum = (arr) -> if arr.length == 0 return 0 else return _.reduce(arr, (sum, num) -> sum + num)

class @VoteController extends RouteController

  waitOn: ->
    q = {}
    if filterType = @params.filterType
      q.type = filterType
    if filterTag = @params.filterTag
      q.tags = filterTag
    Meteor.subscribe('proposals-min', q)

  after: -> document.title = "Vote | Reversim Summit 2014"

  tempalte: 'vote'

  data: ->
    speakers = User.allSpeakers()
    if speakers and speakers.length > 0
      user = User.current()
      speakers = if user and (user.admin() or user.moderator()) then sort(speakers) else _.shuffle(speakers)
    return {
      page: 'vote'
      speakers: speakers
      filterType: @params.filterType
      filterTag: @params.filterTag
    }

sort = (speakers) ->
  _.sortBy(speakers, (speaker) ->
    - sum(speaker.proposals().map((p) -> p.voteCount()))
  )

sum = (arr) -> _.reduce(arr, ((sum, num) -> sum + num), 0)

Fix the reduce function. Yet again...

Fix the reduce function. Yet again...


window.$ = window.jQuery = require('jquery')
require('semantic-ui-css/semantic')
React = require('react/addons')
ReactDOM = require('react-dom')
reactRouter = require('react-router')

Header = require('./header')

CodeEditor = require('./CodeEditor')
Documentation = require('./Documentation')
Master = require('./Master')

{Router, Route, IndexRoute} = reactRouter

Home = React.createClass
  render: ->

          <CodeEditor />

          <Documentation />

Teacher = React.createClass
  render: ->

            <Master />

About = React.createClass
  render: ->

This is the about page.

Main = React.createClass
  render: ->

        { @props.children }

routes =
  <Route path="/" component={Main}>
    <IndexRoute component={Home}/>
    <Route path="about" component={About}/>
    <Route path="master" component={Teacher}/>
  </Route>

$ ->
  ReactDOM.render(<Router>{routes}</Router>, document.body)

Reduce overhead DIVs in layout

Reduce overhead DIVs in layout


Trix.config.textAttributes =
  bold:
    tagName: "strong"
    inheritable: true
    parser: (element) ->
      return false if /H\d$/.test(element.tagName) or element.tagName is "BR"
      style = window.getComputedStyle(element)
      style["fontWeight"] is "bold" or style["fontWeight"] >= 600

  italic:
    tagName: "em"
    inheritable: true
    parser: (element) ->
      style = window.getComputedStyle(element)
      style["fontStyle"] is "italic"
  href:
    groupTagName: "a"
    parser: (element) ->
      {attachmentSelector} = Trix.AttachmentView
      matchingSelector = "a:not(#{attachmentSelector})"
      if link = Trix.findClosestElementFromNode(element, {matchingSelector})
        link.getAttribute("href")
  strike:
    tagName: "del"
    inheritable: true
  frozen:
    style: { "backgroundColor": "highlight" }

Trix.config.textAttributes =
  bold:
    tagName: "strong"
    inheritable: true
    parser: (element) ->
      style = window.getComputedStyle(element)
      style["fontWeight"] is "bold" or style["fontWeight"] >= 600

  italic:
    tagName: "em"
    inheritable: true
    parser: (element) ->
      style = window.getComputedStyle(element)
      style["fontStyle"] is "italic"
  href:
    groupTagName: "a"
    parser: (element) ->
      {attachmentSelector} = Trix.AttachmentView
      matchingSelector = "a:not(#{attachmentSelector})"
      if link = Trix.findClosestElementFromNode(element, {matchingSelector})
        link.getAttribute("href")
  strike:
    tagName: "del"
    inheritable: true
  frozen:
    style: { "backgroundColor": "highlight" }

Remove redundant text attribute condition


SettingsController = require 'controllers/settings_controller'
TemplatesController = require 'controllers/templates_controller'
BucketsController = require 'controllers/buckets_controller'
InstallController = require 'controllers/install_controller'
RoutesController = require 'controllers/routes_controller'
AuthController = require 'controllers/auth_controller'

module.exports = (match) ->
  match 'install', 'install#firstuser', params: authRequired: no
  match 'login', 'auth#login', params: authRequired: no

  match 'buckets/add', 'buckets#add'
  match 'buckets/:slug', 'buckets#listEntries'
  match 'buckets/:slug/add', 'buckets#addEntry'
  match 'buckets/:slug/settings', 'buckets#settings'
  match 'buckets/:slug/:entryID', 'buckets#editEntry'

  match 'templates(/*filename)', 'templates#edit'
  match 'routes', 'routes#list'

  match 'settings', 'settings#basic'
  match 'users(/:userID)?', 'settings#users'

  match '', 'buckets#dashboard'

  match ':missing*', 'buckets#missing'

SettingsController = require 'controllers/settings_controller'
TemplatesController = require 'controllers/templates_controller'
BucketsController = require 'controllers/buckets_controller'
InstallController = require 'controllers/install_controller'
RoutesController = require 'controllers/routes_controller'
AuthController = require 'controllers/auth_controller'

module.exports = (match) ->
  match 'install', 'install#firstuser', params: authRequired: no
  match 'login', 'auth#login', params: authRequired: no

  match 'buckets/add', 'buckets#add'
  match 'buckets/:slug', 'buckets#listEntries'
  match 'buckets/:slug/add', 'buckets#addEntry'
  match 'buckets/:slug/settings', 'buckets#settings'
  match 'buckets/:slug/:entryID', 'buckets#editEntry'

  match 'templates(/*filename)', 'templates#edit'
  match 'routes', 'routes#list'

  match 'settings', 'settings#basic'
  match 'users(/:userID)', 'settings#users'

  match '', 'buckets#dashboard'

  match ':missing*', 'buckets#missing'

Fix for user route (still no view)

Fix for user route (still no view)


# Error Formating
# ---------------

# Ensure that errors of different kinds (lexer, parser and compiler) are shown
# in a consistent way.

{prettyErrorMessage} = CoffeeScript.helpers

assertErrorFormat = (code, expectedErrorFormat) ->
  throws (-> CoffeeScript.compile code), (err) ->
    message = prettyErrorMessage err, 'test.coffee', code
    eq expectedErrorFormat, message
    yes

test "lexer errors formating", ->
  assertErrorFormat '''
    normalObject    = {}
    insideOutObject = }{
  ''',
  '''
    test.coffee:2:19: error: unmatched }
    insideOutObject = }{
                      ^
  '''

test "parser error formating", ->
  assertErrorFormat '''
    foo in bar or in baz
  ''',
  '''
    test.coffee:1:15: error: unexpected RELATION
    foo in bar or in baz
                  ^^
  '''

test "compiler error formatting", ->
  assertErrorFormat '''
    evil = (foo, eval, bar) ->
  ''',
  '''
    test.coffee:1:14: error: parameter name "eval" is not allowed
    evil = (foo, eval, bar) ->
                 ^^^^
  '''

# Error Formating
# ---------------

# Ensure that errors of different kinds (lexer, parser and compiler) are shown
# in a consistent way.

{prettyErrorMessage} = CoffeeScript.helpers

assertErrorFormat = (code, expectedErrorFormat) ->
  throws (-> CoffeeScript.run code), (err) ->
    message = prettyErrorMessage err, 'test.coffee', code
    eq expectedErrorFormat, message
    yes

test "lexer errors formating", ->
  assertErrorFormat '''
    normalObject    = {}
    insideOutObject = }{
  ''',
  '''
    test.coffee:2:19: error: unmatched }
    insideOutObject = }{
                      ^
  '''

test "parser error formating", ->
  assertErrorFormat '''
    foo in bar or in baz
  ''',
  '''
    test.coffee:1:15: error: unexpected RELATION
    foo in bar or in baz
                  ^^
  '''

test "compiler error formatting", ->
  assertErrorFormat '''
    evil = (foo, eval, bar) ->
  ''',
  '''
    test.coffee:1:14: error: parameter name "eval" is not allowed
    evil = (foo, eval, bar) ->
                 ^^^^
  '''

fs = require 'fs'

test "#2849: compilation error in a require()d file", ->
  # Create a temporary file to require().
  ok not fs.existsSync 'test/syntax-error.coffee'
  fs.writeFileSync 'test/syntax-error.coffee', 'foo in bar or in baz'

  try
    assertErrorFormat '''
      require './test/syntax-error'
    ''',
    """
      #{__dirname}/syntax-error.coffee:1:15: error: unexpected RELATION
      foo in bar or in baz
                    ^^
    """
  finally
    fs.unlink 'test/syntax-error.coffee'

Add test for compiler errors on require()d files


App.MatchersShowController = Em.ObjectController.extend
  needs: ['transactions']
  syncTransactions: (->
    categoryTransactions = @get('model.transactions')

    transactionsController = @get 'controllers.transactions'
    transactionsController.set 'model', categoryTransactions
    Em.debug "#{this} syncTransactions was called"
  ).observes('model.transactions.@each')
 App.MatcherController = Em.ObjectController.extend
  needs: ['transactions', 'categories']
  actions:
    setEdit: ->
      editing = @get('isEditing')
      if editing
        @get('model').revert()
      @set 'isEditing', !editing
    delete: ->
      @destroy()
    save: ->
      promise = @get('content').save()
      my = @
      promise.then ->
        my.set 'isEditing', false

App.MatchersShowController = Em.ObjectController.extend
  needs: ['transactions']
  syncTransactions: (->
    categoryTransactions = @get('model.transactions')

    transactionsController = @get 'controllers.transactions'
    transactionsController.set 'model', categoryTransactions
    Em.debug "#{this} syncTransactions was called"
  ).observes('model.transactions.@each')
 App.MatcherController = Em.ObjectController.extend
  needs: ['transactions', 'categories', 'matchers']
  actions:
    setEdit: ->
      editing = @get('isEditing')
      if editing
        @get('model').revert()
      @set 'isEditing', !editing
    delete: ->
      matcher = @get 'model'
      @get('controllers.matchers').removeObject matcher
      matcher.deleteRecord()
    save: ->
      promise = @get('content').save()
      my = @
      promise.then ->
        my.set 'isEditing', false

Add delete to matcher contorller

Add delete to matcher contorller


App.Category = App.Model.extend
  id: Ember.attr()
  name: Ember.attr()
  count: Ember.attr(Number)
  total: Ember.attr(Number)
  transactions: Ember.hasMany 'App.Transaction',
    key: 'transaction_ids'
  matchers: Ember.hasMany 'App.Matcher',
    key: 'matcher_id'
App.Category.url = "/categories"
App.Category.adapter = Ember.RESTAdapter.create()

App.Category = App.Model.extend
  id: Ember.attr()
  name: Ember.attr()
  system_type: Ember.attr()
  count: Ember.attr(Number)
  total: Ember.attr(Number)
  transactions: Ember.hasMany 'App.Transaction',
    key: 'transaction_ids'
  matchers: Ember.hasMany 'App.Matcher',
    key: 'matcher_id'
App.Category.url = "/categories"
App.Category.adapter = Ember.RESTAdapter.create()

Add category system type attribute

Add category system type attribute


{ extend } = require 'underscore'
JSONPage = require '../../components/json_page'
resizer = require '../../components/resizer'
markdown = require '../../components/util/markdown'

page = new JSONPage name: 'gallery-partnerships'

@index = (req, res, next) ->
  page.get()
    .then (data) ->
      res.render 'index', extend {},
        page.data,
        resizer,
        markdown: markdown

    .catch next

{ extend } = require 'underscore'
JSONPage = require '../../components/json_page'
resizer = require '../../components/resizer'
markdown = require '../../components/util/markdown'

page = new JSONPage name: 'gallery-partnerships2'

@index = (req, res, next) ->
  page.get()
    .then (data) ->
      res.render 'index', extend {},
        page.data,
        resizer,
        markdown: markdown

    .catch next

Use correct file name for s3

Use correct file name for s3

Signed-off-by: Yuki Nishijima <a6aa6c594f3f904825833313c0bab3e292e95764@artsymail.com>


DeprecationCopView = require '../lib/deprecation-cop-view'

describe "DeprecationCop", ->
  [activationPromise, workspaceElement] = []

  beforeEach ->
    workspaceElement = atom.views.getView(atom.workspace)
    activationPromise = atom.packages.activatePackage('deprecation-cop')
    expect(atom.workspace.getActivePane().getActiveItem()).not.toExist()

  describe "when the deprecation-cop:view event is triggered", ->
    it "displays the deprecation cop pane", ->
      atom.commands.dispatch workspaceElement, 'deprecation-cop:view'

      waitsForPromise ->
        activationPromise

      deprecationCopView = null
      waitsFor ->
        deprecationCopView = atom.workspace.getActivePane().getActiveItem()

      runs ->
        expect(deprecationCopView instanceof DeprecationCopView).toBeTruthy()

  describe "deactivating the package", ->
    it "removes the deprecation cop pane item", ->
      atom.commands.dispatch workspaceElement, 'deprecation-cop:view'

      waitsForPromise ->
        activationPromise

      runs ->
        atom.packages.deactivatePackage('deprecation-cop')
        expect(atom.workspace.getActivePane().getActiveItem()).not.toExist()

DeprecationCopView = require '../lib/deprecation-cop-view'

describe "DeprecationCop", ->
  [activationPromise, workspaceElement] = []

  beforeEach ->
    workspaceElement = atom.views.getView(atom.workspace)
    activationPromise = atom.packages.activatePackage('deprecation-cop')
    expect(atom.workspace.getActivePane().getActiveItem()).not.toExist()

  describe "when the deprecation-cop:view event is triggered", ->
    it "displays the deprecation cop pane", ->
      atom.commands.dispatch workspaceElement, 'deprecation-cop:view'

      waitsForPromise ->
        activationPromise

      deprecationCopView = null
      waitsFor ->
        deprecationCopView = atom.workspace.getActivePane().getActiveItem()

      runs ->
        expect(deprecationCopView instanceof DeprecationCopView).toBeTruthy()

  describe "deactivating the package", ->
    it "removes the deprecation cop pane item", ->
      atom.commands.dispatch workspaceElement, 'deprecation-cop:view'

      waitsForPromise ->
        activationPromise

      waitsForPromise ->
        Promise.resolve(atom.packages.deactivatePackage('deprecation-cop')) # Wrapped for Promise & non-Promise deactivate

      runs ->
        expect(atom.workspace.getActivePane().getActiveItem()).not.toExist()

Make tests run with promise and non-promise package deactivate


sinon = require 'sinon'
Backbone = require 'backbone'
ArtworkInquiry = require '../../models/artwork_inquiry'

describe 'ArtworkInquiry', ->
  beforeEach ->
    @inquiry = new ArtworkInquiry

  describe '#send', ->
    beforeEach ->
      sinon.stub Backbone, 'sync'
        .yieldsTo 'success'
        .returns Promise.resolve()

    afterEach ->
      Backbone.sync.restore()

    it 'sends the inquiry immediately', ->
      @inquiry.set(id: 'foo').send(null, success: ->
        true.should.be.true()
      ).then ->
        Backbone.sync.args[0][2].url
          .should.containEql '/api/v1/me/artwork_inquiry_request/foo/send'

    it 'saves the inquiry first if its new', ->
      @inquiry.save = sinon.stub().returns Promise.resolve()
      @inquiry.send()
      @inquiry.save.called.should.be.ok()

sinon = require 'sinon'
Backbone = require 'backbone'
ArtworkInquiry = require '../../models/artwork_inquiry'

describe 'ArtworkInquiry', ->
  beforeEach ->
    @inquiry = new ArtworkInquiry

  describe '#send', ->
    beforeEach ->
      sinon.stub Backbone, 'sync'
        .yieldsTo 'success'
        .returns Promise.resolve()

    afterEach ->
      Backbone.sync.restore()

    it 'sends the inquiry immediately', ->
      success = sinon.spy()
      @inquiry.set(id: 'foo').send(null, success: success).then ->
        success.called.should.be.ok()
        Backbone.sync.args[0][2].url
          .should.containEql '/api/v1/me/artwork_inquiry_request/foo/send'

    it 'saves the inquiry first if its new', ->
      @inquiry.save = sinon.stub().returns Promise.resolve()
      @inquiry.send()
      @inquiry.save.called.should.be.ok()

Refactor inquiry test using spies to be slightly more readable.


observe = require './observe'

prototype =
  autoRender: true

  initialize: (object) ->
    if object.constructor.name == 'Object' and @Model?
      @model = new @Model object
    else
      @model = object

    observe @model, @bindings, @

    if @autoRender
      @render object

  cacheTemplate: ->
    # Cache on prototype so it can be reused
    @::_cachedEl = el

  renderTemplate: (ctx) ->
    if @_cachedEl? and cache
      # Clone node, rather than re-rendering template for each instance.
      @el = @_cachedEl.cloneNode true
      return @

    # Generate element template
    el = @template.call @, ctx

    # Coerce strings to HTML dom fragments
    if typeof el is 'string' or el instanceof String
      div = createElement 'div'
      div.insertAdjacentHTML 'afterbegin', el
      el = div.removeChild childNodes[0]

    # Use el
    @el = el

  render: (ctx) ->
    @renderTemplate ctx
    @cacheTemplate()

    for prop, fn in @bindings
      if (value = @model[prop]?)
        fn.call @, value

    @

  remove: ->
    parent = @el.parentNode
    parent.removeChild @el if parent
    @

  template: ->
    '

'

module.exports =
  View: (options) ->
    View = (object = {}) ->
      unless @ instanceof View
        return new View object

      @initialize object

    View:: = Object.create prototype
    View::constructor = View

    for k,v of options
      View::[k] = v

    View

observe = require './observe'

prototype =
  autoRender: true

  initialize: (object) ->
    if object.constructor.name == 'Object' and @Model?
      @model = new @Model object
    else
      @model = object

    observe @model, @bindings, @

    if @autoRender
      @render object

  cacheTemplate: (el) ->
    # Cache on prototype so it can be reused
    @::_cachedEl = el

  renderTemplate: (ctx) ->
    if @_cachedEl? and cache
      # Clone node, rather than re-rendering template for each instance.
      return @_cachedEl.cloneNode true

    # Generate element template
    el = @template.call @, ctx

    # Coerce strings to HTML dom fragments
    if typeof el is 'string' or el instanceof String
      div = createElement 'div'
      div.insertAdjacentHTML 'afterbegin', el
      el = div.removeChild childNodes[0]

    # Use el
    el

  render: (ctx, cache=true) ->
    @el = @renderTemplate ctx
    @cacheTemplate @el if cache

    for prop, fn in @bindings
      if (value = @model[prop]?)
        fn.call @, value

    @

  remove: ->
    parent = @el.parentNode
    parent.removeChild @el if parent
    @

  template: ->
    '

'

module.exports =
  View: (options) ->
    View = (object = {}) ->
      unless @ instanceof View
        return new View object

      @initialize object

    View:: = Object.create prototype
    View::constructor = View

    for k,v of options
      View::[k] = v

    View

Make it easy to disable caching.

Make it easy to disable caching.


{View, EditorView} = require 'atom'

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

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

  class MinimapHighlightSelectedView extends HighlightedAreaView
    constructor: ->
      super
      @paneView = @editorView.getPane()
      @subscribe @paneView.model.$activeItem, @onActiveItemChanged

    attach: ->
      @subscribe @editorView, "selection:changed", @handleSelection

      minimapView = @getMinimap()

      if minimapView?
        minimapView.miniOverlayer.append(this)
        @adjustResults()

    detach: ->
      super
      @unsubscribe @editorView, "selection:changed", @handleSelection

    adjustResults: ->
      @css '-webkit-transform', "scale3d(#{minimap.getCharWidthRatio()},1,1)"

    onActiveItemChanged: (item) =>
      return if item is @activeItem

      if @paneView.activeView is @editorView
        @attach()
      else
        @detach()

    getMinimap: ->
      if @editorView instanceof EditorView
        return minimap.minimapForEditorView(@editorView)

{View} = require 'atom'

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

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

  class MinimapHighlightSelectedView extends HighlightedAreaView
    constructor: ->
      super
      @paneView = @editorView.getPane()
      @subscribe @paneView.model.$activeItem, @onActiveItemChanged

    attach: ->
      @subscribe @editorView, "selection:changed", @handleSelection

      minimapView = @getMinimap()

      if minimapView?
        minimapView.miniOverlayer.append(this)
        @adjustResults()

    detach: ->
      super
      @unsubscribe @editorView, "selection:changed", @handleSelection

    adjustResults: ->
      @css '-webkit-transform', "scale3d(#{minimap.getCharWidthRatio()},1,1)"

    onActiveItemChanged: (item) =>
      return if item is @activeItem

      if @paneView.activeView is @editorView
        @attach()
      else
        @detach()

    getMinimap: ->
      if @editorView.hasClass('editor')
        return minimap.minimapForEditorView(@editorView)

Add compatibility for upcoming react support in minimap


class RecentlyViewedFactView extends Backbone.Marionette.ItemView
  tagName: 'li'
  template: 'facts/recently_viewed_fact'

  templateHelpers: =>
    evidence_type: @options.evidence_type

  triggers:
    'click button': 'click'

  ui:
    factWheel: '.js-fact-wheel'

  onRender: ->
    @ui.factWheel.html @wheelView().render().el

  onClose: ->
    @wheelView().close()

  wheelView: ->
    @_wheelView ?= new InteractiveWheelView
      fact: @model.get("fact_base")
      model: new Wheel @model.get("fact_wheel")
      respondsToMouse: false

class window.RecentlyViewedFactsView extends Backbone.Marionette.CompositeView
  template: 'facts/recently_viewed_facts'

  className: 'recently-viewed-facts'

  itemView: RecentlyViewedFactView
  itemViewContainer: '.js-itemview-container'
  itemViewOptions: -> evidence_type: @options.evidence_type

class RecentlyViewedFactView extends Backbone.Marionette.ItemView
  tagName: 'li'
  template: 'facts/recently_viewed_fact'

  templateHelpers: =>
    evidence_type: @options.evidence_type

  triggers:
    'click button': 'click'

  ui:
    factWheel: '.js-fact-wheel'

  onRender: ->
    @ui.factWheel.html @wheelView().render().el

  onClose: ->
    @wheelView().close()

  wheelView: ->
    @_wheelView ?= new InteractiveWheelView
      fact: @model.get("fact_base")
      model: new Wheel @model.get("fact_wheel")

class window.RecentlyViewedFactsView extends Backbone.Marionette.CompositeView
  template: 'facts/recently_viewed_facts'

  className: 'recently-viewed-facts'

  itemView: RecentlyViewedFactView
  itemViewContainer: '.js-itemview-container'
  itemViewOptions: -> evidence_type: @options.evidence_type

Make the fact wheel in recently viewed facts responding to the mouse for now.


noflo = require "noflo"
couch = require "couch-client"

class SaveObject extends noflo.Component
    constructor: ->
        @request = null
        @database = "default"
        @connection = null
        @data = []

        @inPorts =
            in: new noflo.Port()
            database: new noflo.Port()
            connection: new noflo.Port()

        @inPorts.connection.on "data", (data) =>
            @connection = data
        @inPorts.connection.on "disconnect", =>
            return unless @data.length
            saveObject data for data in @data

        @inPorts.in.on "begingroup", (group) =>
            do @openRequest
        @inPorts.in.on "data", (data) =>
            return @saveObject data if @connection
            @data.push data
        @inPorts.in.on "endgroup", =>
            @request = null

    openRequest: ->
        return if @request
        throw new "No CouchDB connection available" unless @connection
        @request = @connection.request "PUT", "/#{@database}", (err, result) ->
            console.error err if err

    saveObject: (object) ->
        do @openRequest unless @request

        # FIXME: Support for updating existing
        console.log "SAVING"

        @connection.save object, (err, result) ->
            console.error err if err
            console.error result

exports.getComponent = -> new SaveObject

noflo = require "noflo"
couch = require "couch-client"

class SaveObject extends noflo.Component
    constructor: ->
        @request = null
        @database = "default"
        @connection = null
        @data = []

        @inPorts =
            in: new noflo.ArrayPort()
            database: new noflo.Port()
            connection: new noflo.Port()

        @inPorts.connection.on "data", (data) =>
            @connection = data
        @inPorts.connection.on "disconnect", =>
            return unless @data.length
            saveObject data for data in @data

        @inPorts.in.on "begingroup", (group) =>
            do @openRequest
        @inPorts.in.on "data", (data) =>
            return @saveObject data if @connection
            @data.push data
        @inPorts.in.on "endgroup", =>
            @request = null

    openRequest: ->
        return if @request
        throw new "No CouchDB connection available" unless @connection
        @request = @connection.request "PUT", "/#{@database}", (err, result) ->
            console.error err if err

    saveObject: (object) ->
        do @openRequest unless @request

        @connection.save object, (err, result) ->
            console.error err if err

exports.getComponent = -> new SaveObject

Allow multiple IN sources for saving

Allow multiple IN sources for saving


Entity   = require 'models/Entity'
mediator = require 'mediator'

module.exports = class Event extends Entity

  mediator.factory['Event'] = this

  constructor: (x, y, width, height, owningLevel, settings) ->
    # settings.physicsType = 'static'
    # settings.isSensor    = true

    super x, y, width, height, owningLevel, settings

  onTouchBegin: (body, point, impulse) =>
    if @name == 'FirstYeti'
      @name = ''
      @level.tasks.push =>
        yeti =
          name: 'Yeti'
          type: 'Yeti'
          x: 16*32
          y: 16
          width: 32
          height: 32
          properties: {
          }

        @level.addEntity yeti

        mediator.soundManager.stopAll()
        mediator.soundManager.playSound @level.manifest.sounds.sounds[0], 1, true

Entity   = require 'models/Entity'
mediator = require 'mediator'

module.exports = class Event extends Entity

  mediator.factory['Event'] = this

  constructor: (x, y, width, height, owningLevel, settings) ->
    # settings.physicsType = 'static'
    # settings.isSensor    = true

    super x, y, width, height, owningLevel, settings

  onTouchBegin: (body, point, impulse) =>
    if @name == 'FirstYeti'
      @name = ''
      @level.tasks.push =>
        yeti =
          name: 'Yeti'
          type: 'Yeti'
          x: 16*32
          y: 16
          width: 32
          height: 32
          properties: {
          }

        @level.addEntity yeti

        mediator.soundManager.stopAll config =
          themeSound: true
          backgroundSounds: true

        mediator.soundManager.playSound @level.manifest.sounds.sounds[0], 1, true

Update event to use new SoundManager.stopAll(config)


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

$ ->
	$('.update').on 'input', (event) ->
		console.log event
		$(this).parent().find('.update').val(this.value)

$ ->
	$('#select_all_btn').on 'click', (e) ->
		document.getElementById("lights_"+i).checked = true for i in [1..6]
$ ->
	$('#deselect_all_btn').on 'click', (e) ->
		document.getElementById("lights_"+i).checked = false for i in [1..6]

$ ->
  $('#party_canvas').on 'click', (e) ->
    $.ajax(url: 'lights/party_on_off')
    togglePartyMode()

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

$ ->
	$('.update').on 'input', (event) ->
		console.log event
		$(this).parent().find('.update').val(this.value)

$ ->
	$('#select_all_btn').on 'click', (e) ->
		document.getElementById("lights_"+i).checked = true for i in [1..6]
$ ->
	$('#deselect_all_btn').on 'click', (e) ->
		document.getElementById("lights_"+i).checked = false for i in [1..6]

$ ->
  $('#toggle_all_btn').on 'click', (e) ->
    document.getElementById("lights_" + i).checked = !$("#lights_" + i + ":checked").val() for i in [1..6]

$ ->
  $('#party_canvas').on 'click', (e) ->
    $.ajax(url: 'lights/party_on_off')
    togglePartyMode()

Add logic that toggles the selection when the button is pressed


class @Scenario extends Backbone.Model
  apiSessionID: ->
    key = App.settings.get('api_session_id')
    return if key? then key else null

  api_session_id: ->
    @apiSessionID()

  apiAttributes: ->
    s = App.settings
    data =
      area_code: s.get('area_code')
      end_year: s.get('end_year')
      preset_scenario_id: s.get('preset_scenario_id')
      use_fce: s.get('use_fce')
      source: 'ETM'

  api_attributes: ->
    @apiAttributes()

  # Returns the base scenario URL, taking into account CORS support
  urlPath: -> App.api.path "scenarios/#{@api_session_id()}"

  url_path: -> @urlPath()

  etenginePath: ->
    App.scenario_url()

  countryCode: ->
    if App.settings.get('area_code').match(/^UKNI/)
      App.settings.get('area_code')
    else
      App.settings.get('country_code')

  reset: => App.reset_scenario()

class @Scenario extends Backbone.Model
  apiSessionID: ->
    key = App.settings.get('api_session_id')
    return if key? then key else null

  api_session_id: =>
    @apiSessionID()

  apiAttributes: ->
    s = App.settings
    data =
      area_code: s.get('area_code')
      end_year: s.get('end_year')
      preset_scenario_id: s.get('preset_scenario_id')
      use_fce: s.get('use_fce')
      source: 'ETM'

  api_attributes: ->
    @apiAttributes()

  # Returns the base scenario URL, taking into account CORS support
  urlPath: -> App.api.path "scenarios/#{@api_session_id()}"

  url_path: -> @urlPath()

  etenginePath: ->
    App.scenario_url()

  countryCode: ->
    if App.settings.get('area_code').match(/^UKNI/)
      App.settings.get('area_code')
    else
      App.settings.get('country_code')

  reset: => App.reset_scenario()

Fix inability to dismiss "Results" attention grabber


# load modules in CommonJS/Node.js environment, not needed in browser

if exports? && require?
  exports.ObjectTemplate = require './ObjectTemplate'
  exports.TemplateConfig = require './TemplateConfig'

Handle loading classes in browser

Handle loading classes in browser


goog.provide 'app.react.Link'

class app.react.Link

  ###*
    @param {app.Routes} routes
    @param {app.react.Touch} touch
    @constructor
  ###
  constructor: (@routes, @touch) ->

  ###*
    @param {este.Route} route
    @param {string} text
    @param {Object=} params
  ###
  to: (route, text, params) ->
    {a} = @touch.none 'a'

    a
      className: if @routes.active == route then 'active' else null
      href: route.url params
    , text

goog.provide 'app.react.Link'

class app.react.Link

  ###*
    @param {app.Routes} routes
    @param {app.react.Touch} touch
    @constructor
  ###
  constructor: (@routes, @touch) ->

  ###*
    @param {este.Route} route
    @param {string} text
    @param {Object=} urlParams
    @param {Object=} props
  ###
  to: (route, text, urlParams, props) ->
    {a} = @touch.none 'a'

    linkProps = href: route.url urlParams
    goog.mixin linkProps, props if props
    linkProps.className ?= ''
    linkProps.className += ' ' + if @routes.active == route then 'active' else ''
    delete linkProps.className if !linkProps.className.trim()

    a linkProps, text

Add arg props to app.react.Link

Add arg props to app.react.Link


class GameState
  customers: []
  agents: []

  requestQueues: {}
  chanceOfRequest: 0.02

  tickables: []
  tick: 0

  money: 1000000
  reputation: 0.5
  agentSpawner: new AgentSpawner()

  addAgent: (agent) ->
    @agents.push(agent)
    @tickables.push(agent)

  fireAgent: (agent) ->
    @agents.filter((item) ->
      item != agent
    )

  removeCustomer: (customer) ->
    customers.pop(customer)

  calculateReputation: ->
    totalWorth = 0
    totalRep = 0
    for customer in @customers
      totalRep += customer.mood * customer.worth
      totalWorth += customer.worth
    if totalWorth != 0
      @reputation = totalRep / totalWorth

  constructor: ->
    @level = new Level

  numberOfRequests: ->
    requests = 0
    for queue of @requestQueues
      requests += @requestQueues[queue].length()
    requests

  toString: ->
    "Customers: " + @customers.length +
    "\nRequest queue: " + @numberOfRequests() +
    "\nReputation: " + (@reputation * 100) + "%" +
    "\nAgents: " + @agents.join(", ")

class GameState
  customers: []
  agents: []

  requestQueues: {}
  chanceOfRequest: 0.005

  tickables: []
  tick: 0

  money: 1000000
  reputation: 0.5
  agentSpawner: new AgentSpawner()

  addAgent: (agent) ->
    @agents.push(agent)
    @tickables.push(agent)

  fireAgent: (agent) ->
    @agents.filter((item) ->
      item != agent
    )

  removeCustomer: (customer) ->
    customers.pop(customer)

  calculateReputation: ->
    totalWorth = 0
    totalRep = 0
    for customer in @customers
      totalRep += customer.mood * customer.worth
      totalWorth += customer.worth
    if totalWorth != 0
      @reputation = totalRep / totalWorth

  constructor: ->
    @level = new Level

  numberOfRequests: ->
    requests = 0
    for queue of @requestQueues
      requests += @requestQueues[queue].length()
    requests

  toString: ->
    "Customers: " + @customers.length +
    "\nRequest queue: " + @numberOfRequests() +
    "\nReputation: " + (@reputation * 100) + "%" +
    "\nAgents: " + @agents.join(", ")

Make requests significantly rarer (more realistic)


config =
	serverURL: 'https://gitlab.com'
	identityPath: '/api/v3/user'
	addAutopublishFields:
		forLoggedInUser: ['services.gitlab']
		forOtherUsers: ['services.gitlab.username']

Gitlab = new CustomOAuth 'gitlab', config

if Meteor.isServer
	Meteor.startup ->
		RocketChat.models.Settings.findById('API_Gitlab_URL').observe
			added: (record) ->
				config.serverURL = RocketChat.settings.get 'API_Gitlab_URL'
				Gitlab.configure config
			changed: (record) ->
				config.serverURL = RocketChat.settings.get 'API_Gitlab_URL'
				Gitlab.configure config
else
	Meteor.startup ->
		Tracker.autorun ->
			if RocketChat.settings.get 'API_Gitlab_URL'
				config.serverURL = RocketChat.settings.get 'API_Gitlab_URL'
				Gitlab.configure config

config =
	serverURL: 'https://gitlab.com'
	identityPath: '/api/v3/user'
	scope: 'api'
	addAutopublishFields:
		forLoggedInUser: ['services.gitlab']
		forOtherUsers: ['services.gitlab.username']

Gitlab = new CustomOAuth 'gitlab', config

if Meteor.isServer
	Meteor.startup ->
		RocketChat.models.Settings.findById('API_Gitlab_URL').observe
			added: (record) ->
				config.serverURL = RocketChat.settings.get 'API_Gitlab_URL'
				Gitlab.configure config
			changed: (record) ->
				config.serverURL = RocketChat.settings.get 'API_Gitlab_URL'
				Gitlab.configure config
else
	Meteor.startup ->
		Tracker.autorun ->
			if RocketChat.settings.get 'API_Gitlab_URL'
				config.serverURL = RocketChat.settings.get 'API_Gitlab_URL'
				Gitlab.configure config

Set gitlabs scope to 'api', the only support scope.

Fixes #3987


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

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

$ ->
  animateMetric = $(".metric-box strong").each (index) ->
    $this = $(this)
    starting_point = 0
    $target_count = parseInt($this.text().replace(/\,/g, ''))

    $this.counter = starting_point

    tween = createjs.Tween.get($this).to( {counter: $target_count}, (1200 + index * 800) , createjs.Ease.quintOut)

    tween.addEventListener 'change', (event) ->
      # if the number is under 90 of the target, increment number by thousands
      if $this.counter < $target_count * 0.7
        $this.counter = roundUpBy($this.counter, 1000)
      else if $this.counter < $target_count * 0.8
        $this.counter = roundUpBy($this.counter, 100)
      else if $this.counter < $target_count * 0.99
        $this.counter = roundUpBy($this.counter, 10)
      $this.text(Math.round($this.counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","))
      return

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

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

$ ->
  animateMetric = $(".metric-box strong").each (index) ->
    $this = $(this)
    starting_point = 0
    $target_count = parseInt($this.text().replace(/\,/g, ''))

    $this.counter = starting_point

    tween = createjs.Tween.get($this).to( {counter: $target_count}, (1000 + index * 400) , createjs.Ease.quintOut)

    tween.addEventListener 'change', (event) ->
      # if the number is under 90 of the target, increment number by thousands
      if $this.counter < $target_count * 0.7
        $this.counter = roundUpBy($this.counter, 1000)
      else if $this.counter < $target_count * 0.8
        $this.counter = roundUpBy($this.counter, 100)
      else if $this.counter < $target_count * 0.99
        $this.counter = roundUpBy($this.counter, 10)
      $this.text(Math.round($this.counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","))
      return

Reduce the animation duration more

Reduce the animation duration more


Impromptu = require './impromptu'

class Cacheable
  constructor: (@impromptu, @name, @options) ->
  run: (fn) => throw Impromptu.AbstractError
  get: (fn) -> throw Impromptu.AbstractError
  set: (fn) -> throw Impromptu.AbstractError
  unset: (fn) -> throw Impromptu.AbstractError

# Expose `Cacheable`.
exports = module.exports = Cacheable

Impromptu = require './impromptu'

# An abstract class that manages how a method is cached.
class Cacheable
  constructor: (@impromptu, @name, @options) ->

  # The main method.
  #
  # Accepts a `fn` with a signature of `err, results`, where `results` is the
  # cached value. Optionally updates the cache.
  #
  # This should be bound to the instance so the method can be passed around
  # without the instance.
  run: (fn) => throw Impromptu.AbstractError

  # Gets the cached value.
  #
  # Accepts a `fn` with a signature of `err, results`, where `results` is the
  # cached value. Does not update the cache.
  get: (fn) -> throw Impromptu.AbstractError

  # Updates the cached value.
  #
  # Accepts a `fn` with a signature of `err, success`, where `success` is a
  # boolean indicating whether the cached value was updated.
  set: (fn) -> throw Impromptu.AbstractError

  # Clears the cached value.
  #
  # Accepts a `fn` with a signature of `err, success`, where `success` is a
  # boolean indicating whether the value was removed from the cache.
  unset: (fn) -> throw Impromptu.AbstractError

# Expose `Cacheable`.
exports = module.exports = Cacheable

Document the abstract Cacheable class.

Document the abstract Cacheable class.


Steam.ScoringListView = (_) ->
  _items = do nodes$

  #TODO ugly
  _isLive = node$ yes

  activateItem = (item) ->
    for other in _items()
      if other is item
        other.isActive yes
      else
        other.isActive no

    _.displayScoring item.data

  createItem = (scoring) ->
    #TODO replace with type checking
    self =
      data: scoring
      title: scoring.frameKey
      caption: describeCount scoring.scores.length, 'model'
      cutline: new Date(scoring.timestamp).toString()
      display: -> activateItem self
      isActive: node$ no
      isSelected: node$ no

    apply$ _isLive, self.isSelected, (isLive, isSelected) ->
      _.scoringSelectionChanged isSelected, _predicate, scoring if isLive
    self

  displayScorings = (scorings) ->
    _items items = map scorings, createItem
    activateItem head items unless isEmpty items

  _predicate = null
  loadScorings = (predicate) ->
    console.assert isDefined predicate
    _predicate = predicate

    pastScorings = (_.getFromCache 'scoring') or _.putIntoCache 'scoring', []
    if predicate.type is 'scoring'
      pastScorings.unshift predicate.scoring

    displayScorings pastScorings

    return

  link$ _.loadScorings, loadScorings
  link$ _.deselectAllScorings, ->
    #TODO ugly
    _isLive no
    for item in _items()
      item.isSelected no
    _isLive yes

  items: _items
  template: 'scoring-list-view'

Steam.ScoringListView = (_) ->
  _items = do nodes$
  _hasItems = lift$ _items, (items) -> items.length > 0

  #TODO ugly
  _isLive = node$ yes

  activateItem = (item) ->
    for other in _items()
      if other is item
        other.isActive yes
      else
        other.isActive no

    _.displayScoring item.data

  createItem = (scoring) ->
    #TODO replace with type checking
    self =
      data: scoring
      title: scoring.frameKey
      caption: describeCount scoring.scores.length, 'model'
      cutline: new Date(scoring.timestamp).toString()
      display: -> activateItem self
      isActive: node$ no
      isSelected: node$ no

    apply$ _isLive, self.isSelected, (isLive, isSelected) ->
      _.scoringSelectionChanged isSelected, _predicate, scoring if isLive
    self

  displayScorings = (scorings) ->
    _items items = map scorings, createItem
    if isEmpty items
      _.displayEmpty()
    else
      activateItem head items

  _predicate = null
  loadScorings = (predicate) ->
    console.assert isDefined predicate
    _predicate = predicate

    pastScorings = (_.getFromCache 'scoring') or _.putIntoCache 'scoring', []
    if predicate.type is 'scoring'
      pastScorings.unshift predicate.scoring

    displayScorings pastScorings

    return

  link$ _.loadScorings, loadScorings
  link$ _.deselectAllScorings, ->
    #TODO ugly
    _isLive no
    for item in _items()
      item.isSelected no
    _isLive yes

  items: _items
  hasItems: _hasItems
  template: 'scoring-list-view'

Handle empty scoring lists properly PP-8


Template.date.helpers

Template.date.rendered = ->
  template = @
  $editor = template.$("input")
  $editor.datepicker(
    changeMonth: true
    changeYear: true
    dateFormat: "yy/mm/dd"
    constrainInput: false
    onSelect: (date) ->
      $set = {}
      $set[template.data.property] = date
      editor = share.EditorCache.editors[template.data.family]
      editor.collection.update(template.data._id, {$set: $set})
  )
  $editor.datepicker("setDate", @data.value)

Template.date.events

Template.date.helpers

Template.date.rendered = ->
  template = @
  $editor = template.$("input")
  $editor.datepicker(
    changeMonth: true
    changeYear: true
    dateFormat: "yy/mm/dd"
    constrainInput: false
    onSelect: (date) ->
      $set = {}
      $set[template.data.property] = date
      editor = share.EditorCache.editors[template.data.family]
      editor.collection.update(template.data._id, {$set: $set})
  )
  date = @data.value.replace(/\:.+$/i, "") # actually, the format is yy/mm/dd:hh, but ":hh" part should be stripped for datepicker
  $editor.datepicker("setDate", date)
  $editor.val(@data.value)

Template.date.events

Fix date with hours display

Fix date with hours display


###
# # Write JSON File Tree
###

fs = require 'fs'
path = require 'path'
through = require 'through2'

log = require '../utils/log'

module.exports = (fileName, opts={}) ->
  unless fileName
    throw new PluginError("Render File Tree", "Missing fileName option")

  filePrefix = opts.filePrefix or "window.#{opts.varName or 'files'} = [\n"
  fileSuffix = opts.fileSuffix or "\n];"

  output = fs.createWriteStream(fileName)
  output.write filePrefix
  first = true

  bufferContents = (file, enc, cb) ->
    output.write (if first then '' else ',\n') + JSON.stringify({
      path: file.relative
      originalName: path.basename file.originalPath
      originalPath: file.originalRelative
      name: path.basename file.path
      lang: file.extra?.lang?.highlightJS or file.extra?.lang?.pygmentsLexer
      title: file.extra?.toc?[0]?.title
      toc: file.extra?.toc
    }, false, 2)
    first = false

    cb null, file

  endStream = (cb) ->
    output.write fileSuffix
    if opts.verbose
      log "File tree written to #{path.basename fileName}"
    cb()

  through.obj bufferContents, endStream

###
# # Write JSON File Tree
###

fs = require 'fs'
path = require 'path'
through = require 'through2'
_ = require 'lodash'

log = require '../utils/log'

module.exports = (fileName, opts={}) ->
  unless fileName
    throw new PluginError("Render File Tree", "Missing fileName option")

  filePrefix = opts.filePrefix or "window.#{opts.varName or 'files'} = [\n"
  fileSuffix = opts.fileSuffix or "\n];"

  output = fs.createWriteStream(fileName)
  output.write filePrefix
  first = true

  bufferContents = (file, enc, cb) ->
    output.write (if first then '' else ',\n') + JSON.stringify({
      path: file.relative
      originalName: path.basename file.originalPath
      originalPath: file.originalRelative
      name: path.basename file.path
      lang: file.extra?.lang?.highlightJS or file.extra?.lang?.pygmentsLexer
      title: _.find(file.extra?.toc, level: 1)?.title
      toc: file.extra?.toc
    }, false, 2)
    first = false

    cb null, file

  endStream = (cb) ->
    output.write fileSuffix
    if opts.verbose
      log "File tree written to #{path.basename fileName}"
    cb()

  through.obj bufferContents, endStream

Choose First h1 for File Title

Choose First h1 for File Title


{EditorView, ScrollView} = require 'atom'

module.exports =
class MinimapEditorView extends ScrollView

  @content: ->
    @div class: 'minimap-editor editor editor-colors', =>
      @div class: 'scroll-view', outlet: 'scrollView', =>
        @div class: 'lines', outlet: 'lines'

  initialize: ->
    super

  update: (@editorView) ->
    start = Date.now()

    @lines.html ''
    console.log('cleaning time:', (Date.now() - start) + 'ms')
    # FIXME: If the file is very large, the tokenizes doesn't generate
    # completely, so doesn't have the syntax highlight until a new view
    # is activated in the same pane.
    numLines = @editorView.getModel().displayBuffer.getLines().length
    lines = @editorView.buildLineElementsForScreenRows(0, numLines)

    @lines.append lines
    @lines.css fontSize: "#{@editorView.getFontSize()}px"

    console.log('Update MinimapEditorView response time:', (Date.now() - start) + 'ms')

  getClientRect: ->
    sv = @scrollView[0]
    {
      width: sv.scrollWidth,
      height: sv.scrollHeight
    }

{EditorView, ScrollView, $} = require 'atom'

module.exports =
class MinimapEditorView extends ScrollView

  @content: ->
    @div class: 'minimap-editor editor editor-colors', =>
      @div class: 'scroll-view', outlet: 'scrollView', =>
        @div class: 'lines', outlet: 'lines', =>
          @div class: 'lines-wrapper'

  initialize: ->
    super

  update: (@editorView) ->
    start = Date.now()

    @lines[0].removeChild(@lines[0].childNodes[0])
    @lines.css fontSize: "#{@editorView.getFontSize()}px"

    console.log('cleaning:', (Date.now() - start) + 'ms')
    # FIXME: If the file is very large, the tokenizes doesn't generate
    # completely, so doesn't have the syntax highlight until a new view
    # is activated in the same pane.
    numLines = @editorView.getModel().displayBuffer.getLines().length
    lines = @editorView.buildLineElementsForScreenRows(0, numLines)
    console.log(' build lines:', (Date.now() - start) + 'ms')
    wrapper = $('<div/>')
    wrapper.append lines
    @lines.append wrapper

    console.log('Update MinimapEditorView response time:', (Date.now() - start) + 'ms')

  getClientRect: ->
    sv = @scrollView[0]
    {
      width: sv.scrollWidth,
      height: sv.scrollHeight
    }

Optimize minimap update by removing a wrapper instead of all lines


Marbles.Views.PermissionsFieldsToggle = class PermissionsFieldsToggleView extends TentStatus.View
  @template_name: 'permissions_fields_toggle'
  @view_name: 'permissions_fields_toggle'

  constructor: ->
    super

    @once 'ready', =>
      setImmediate @bindEvents

    @render()

  context: (permissions = @parentView()?.post()?.get('permissions')) =>
    _.extend super,
      permissions: permissions

  permissionsFieldsView: =>
    _.last(@parentView()?.childViews('PermissionsFields') || [])

  bindEvents: =>
    permissions_fields_view = @permissionsFieldsView()
    return unless permissions_fields_view

    permissions_fields_view.on 'change:options', =>
      permissions = permissions_fields_view.buildPermissions()
      @render(@context(permissions))

    @text ?= {}
    @text.visibility_toggle = {
      show: Marbles.DOM.attr(@el, 'data-show-text')
      hide: Marbles.DOM.attr(@el, 'data-hide-text')
    }

    Marbles.DOM.on @el, 'click', (e) =>
      e.stopPropagation()
      @toggleVisibility()

  toggleVisibility: =>
    if @visible
      @hide()
    else
      @show()

  hide: =>
    @visible = false
    @permissionsFieldsView()?.hide()

  show: (should_focus = true) =>
    @visible = true
    @permissionsFieldsView()?.show()

Marbles.Views.PermissionsFieldsToggle = class PermissionsFieldsToggleView extends TentStatus.View
  @template_name: 'permissions_fields_toggle'
  @view_name: 'permissions_fields_toggle'

  constructor: ->
    super

    @once 'ready', =>
      setImmediate @bindEvents

    @render()

  context: (permissions) =>
    permissions ?= @parentView()?.post()?.get('permissions')
    permissions ?= { public: true }
    _.extend super,
      permissions: permissions

  permissionsFieldsView: =>
    _.last(@parentView()?.childViews('PermissionsFields') || [])

  bindEvents: =>
    permissions_fields_view = @permissionsFieldsView()
    return unless permissions_fields_view

    permissions_fields_view.on 'change:options', =>
      permissions = permissions_fields_view.buildPermissions()
      @render(@context(permissions))

    @text ?= {}
    @text.visibility_toggle = {
      show: Marbles.DOM.attr(@el, 'data-show-text')
      hide: Marbles.DOM.attr(@el, 'data-hide-text')
    }

    Marbles.DOM.on @el, 'click', (e) =>
      e.stopPropagation()
      @toggleVisibility()

  toggleVisibility: =>
    if @visible
      @hide()
    else
      @show()

  hide: =>
    @visible = false
    @permissionsFieldsView()?.hide()

  show: (should_focus = true) =>
    @visible = true
    @permissionsFieldsView()?.show()

Fix permissions toggle label for new posts


class Views.Application extends View
  @content: ->
    @div id: 'application', class: 'container', =>
      @div class: 'navbar navbar-fixed-top navbar-inverse', =>
        @div class: 'navbar-inner', =>
          @div class: 'container', =>
            @a "Hyperarchy", class: 'brand', href: '/'
            @ul class: 'nav pull-right', =>
              @li =>
                @button "New Question", class: 'btn btn-primary', click: 'showNewQuestionForm'
      @subview 'questionsList', new Views.RelationView(
        tag: 'div'
        attributes: { id: 'questions' }
        buildItem: (question) ->
          new Views.QuestionView(question)
      )

  initialize: ->
    Monarch.Remote.Server.fetch([Models.User, Models.Question, Models.Answer, Models.Ranking, Models.Vote, Models.QuestionComment])
      .onSuccess =>
        @questionsList.setRelation(Models.Question.table)
        @buildAndStartRouter()

  buildAndStartRouter: ->
    view = this
    Davis ->
      @configure ->
        @generateRequestOnPageLoad = true
      @get '/:questionId', ({params}) ->
        view.showQuestion(params.questionId)

  showQuestion: (id) ->
    questionView = @questionsList.find(".question[data-question-id=#{id}]")
    $.scrollTo(questionView, offset: -60) if questionView.length

  showNewQuestionForm: ->
    new Views.ModalForm(
      headingText: "Ask an open-ended question:"
      buttonText: "Ask Question"
      onSubmit: (body) =>
        Models.Question.create({body})
    )

class Views.Application extends View
  @content: ->
    @div id: 'application', =>
      @div class: 'navbar navbar-fixed-top navbar-inverse', =>
        @div class: 'navbar-inner', =>
          @div class: 'container', =>
            @a "Hyperarchy", class: 'brand', href: '/'
            @ul class: 'nav pull-right', =>
              @li =>
                @button "New Question", class: 'btn btn-primary', click: 'showNewQuestionForm'
      @subview 'questionsList', new Views.RelationView(
        tag: 'div'
        attributes: { id: 'questions', class: 'container' }
        buildItem: (question) ->
          new Views.QuestionView(question)
        )

  initialize: ->
    Monarch.Remote.Server.fetch([Models.User, Models.Question, Models.Answer, Models.Ranking, Models.Vote, Models.QuestionComment])
      .onSuccess =>
        @questionsList.setRelation(Models.Question.table)
        @buildAndStartRouter()

  buildAndStartRouter: ->
    view = this
    Davis ->
      @configure ->
        @generateRequestOnPageLoad = true
      @get '/:questionId', ({params}) ->
        view.showQuestion(params.questionId)

  showQuestion: (id) ->
    questionView = @questionsList.find(".question[data-question-id=#{id}]")
    $.scrollTo(questionView, offset: -60) if questionView.length

  showNewQuestionForm: ->
    new Views.ModalForm(
      headingText: "Ask an open-ended question:"
      buttonText: "Ask Question"
      onSubmit: (body) =>
        Models.Question.create({body})
    )

Fix title bar appearance at smaller screen widths


H2O.StackTraceOutput = (_, _stackTrace) ->
  _activeNode = signal null

  createThread = (thread) ->
    lines = split thread, '\n'

    title: head lines
    stackTrace: join (tail lines), '\n'

  createNode = (node) ->
    display = -> _activeNode self

    self =
      name: node._node
      timestamp: new Date node._time
      threads: (createThread thread for thread in node._traces)
      display: display

  _nodes = for node in _stackTrace.traces
    createNode node

  _activeNode head _nodes

  nodes: _nodes
  activeNode: _activeNode
  template: 'flow-stacktrace-output'

H2O.StackTraceOutput = (_, _stackTrace) ->
  _activeNode = signal null

  createThread = (thread) ->
    lines = split thread, '\n'

    title: head lines
    stackTrace: join (tail lines), '\n'

  createNode = (node) ->
    display = -> _activeNode self

    self =
      name: node.node
      timestamp: new Date node.time
      threads: (createThread thread for thread in node.thread_traces)
      display: display

  _nodes = for node in _stackTrace.traces
    createNode node

  _activeNode head _nodes

  nodes: _nodes
  activeNode: _activeNode
  template: 'flow-stacktrace-output'

Fix stack trace processing to match refactored API PUBDEV-371


Controller = require 'lib/controller'
User = require 'models/user'
FirstUserView = require 'views/install/firstuser'

mediator = require('chaplin').mediator

module.exports = class InstallController extends Controller

  firstuser: ->
    @adjustTitle 'Install'

    newUser = new User

    @view = new FirstUserView
      model: newUser

    newUser.on 'sync', =>
      mediator.options.needsInstall = no
      @redirectTo url: '/'

Controller = require 'lib/controller'
User = require 'models/user'
FirstUserView = require 'views/install/firstuser'

mediator = require('chaplin').mediator

module.exports = class InstallController extends Controller

  firstuser: ->
    @adjustTitle 'Install'

    newUser = new User
      roles: [{name: 'administrator'}]

    @view = new FirstUserView
      model: newUser

    newUser.on 'sync', =>
      mediator.options.needsInstall = no
      @redirectTo url: '/'

Make the first installed user an administrator by default


define [
    '../core'
    './index'
    './search'
    'tpl!templates/concept/panel.html'
], (c, index, search, templates...) ->

    templates = c._.object ['panel'], templates

    class ConceptSearch extends search.ConceptSearch
        events:
            'typeahead:autocompleted input': 'autocomplete'

        autocomplete: (event, datum) ->
            c.publish c.CONCEPT_FOCUS, datum.id

    class ConceptPanel extends c.Marionette.Layout
        className: 'concept-panel'

        template: templates.panel

        regions:
            search: '.search-region'
            index: '.index-region'

        onRender: ->
            @index.show new index.ConceptIndex
                collection: @collection
                collapsable: false

            @search.show new ConceptSearch
                collection: @collection
                handler: (query, resp) =>
                    @index.currentView.filter(query, resp)

            # Defer focus of concept search until end of event loop
            c._.defer =>
                @search.currentView.ui.input.focus()

    { ConceptPanel }

define [
    '../core'
    './index'
    './search'
    'tpl!templates/concept/panel.html'
], (c, index, search, templates...) ->

    templates = c._.object ['panel'], templates

    class ConceptSearch extends search.ConceptSearch
        events:
            'typeahead:autocompleted input': 'autocomplete'

        autocomplete: (event, datum) ->
            c.publish c.CONCEPT_FOCUS, datum.id

    # Takes a collection of c.models.ConceptModel objects
    class ConceptPanel extends c.Marionette.Layout
        className: 'concept-panel'

        template: templates.panel

        # Two primary regions for the concept panel including the search
        # and the index (listing) of concepts
        regions:
            search: '.search-region'
            index: '.index-region'

        onRender: ->
            # Pass the collection of concepts to be rendered in the index
            @index.show new index.ConceptIndex
                collection: @collection
                collapsable: false

            # When a search occurs, the index is filtered relative to the
            # response which contains a listing of IDs that the search
            # has matched.
            @search.show new ConceptSearch
                collection: @collection
                handler: (query, resp) =>
                    @index.currentView.filter(query, resp)

            # Defer focus of concept search until end of event loop
            c._.defer =>
                @search.currentView.ui.input.focus()

    { ConceptPanel }

Add comments to ConceptPanel for clarity of implementation


fs = require('fs')
instanceLookup = require('../../lib/instance-lookup')

getConfig = ->
  server: JSON.parse(fs.readFileSync(process.env.HOME + '/.tedious/test-connection.json', 'utf8')).config.server
  instanceName: JSON.parse(fs.readFileSync(process.env.HOME + '/.tedious/test-connection.json', 'utf8')).instanceName

exports.goodInstance = (test) ->
  config = getConfig()

  callback = (err, port) ->
    test.ok(!err)
    test.ok(port)

    test.done()

  instanceLookup(config.server, config.instanceName, callback)

exports.badInstance = (test) ->
  config = getConfig()

  callback = (err, port) ->
    test.ok(err)
    test.ok(!port)

    test.done()

  instanceLookup(config.server, 'badInstanceName', callback)

exports.badServer = (test) ->
  config = getConfig()

  callback = (err, port) ->
    test.ok(err)
    test.ok(!port)

    test.done()

  instanceLookup('badServer', config.instanceName, callback)

fs = require('fs')
instanceLookup = require('../../lib/instance-lookup')

getConfig = ->
  server: JSON.parse(fs.readFileSync(process.env.HOME + '/.tedious/test-connection.json', 'utf8')).config.server
  instanceName: JSON.parse(fs.readFileSync(process.env.HOME + '/.tedious/test-connection.json', 'utf8')).instanceName

exports.goodInstance = (test) ->
  config = getConfig()

  if !config.instanceName
    # Config says don't do this test (probably because SQL Server Browser is not available).
    console.log('Skipping goodInstance test')
    test.done()
    return

  callback = (err, port) ->
    test.ok(!err)
    test.ok(port)

    test.done()

  instanceLookup(config.server, config.instanceName, callback)

exports.badInstance = (test) ->
  config = getConfig()

  callback = (err, port) ->
    test.ok(err)
    test.ok(!port)

    test.done()

  instanceLookup(config.server, 'badInstanceName', callback)

exports.badServer = (test) ->
  config = getConfig()

  callback = (err, port) ->
    test.ok(err)
    test.ok(!port)

    test.done()

  instanceLookup('badServer', config.instanceName, callback)

Allow integration test looking up by instance name to be bypassed (if SQL Server Browser not available).


Promise = require 'bluebird'
fs = Promise.promisifyAll require 'fs'
_ = require 'lodash'

module.exports = () ->

        # For performance reasons, we'll do this asynchronously.
        fs.readdirAsync('./controllers/').then (controllers) ->

                #This probably isn't necessary: I wanted to parse through and grab all these controllers
                # asynchronously, so I threw them in a promise
                makeAsyncControllerParse = (file) ->
                        return new Promise (resolve, reject) ->
                                if file.match(/.+\.js/g) != null || file.match(/.+\.coffee/g) != null
                                        # When requiring the module, we don't really want to specify an extension.
                                        # Let's get rid of it.
                                        myObject = {}
                                        name = file.replace('.js', '').replace('.coffee', '')

                                        # Require the controller, feed it into the controllers
                                        myObject[name] = require "../controllers/#{name}"
                                        resolve(myObject)

                # Create a big ol' object of all the promises so that we have a handle on all the files.
                #
                # We're utilizing lodash's "chain" function simply because it gives us somewhat sane list
                # comprehension comparable to linq.
                promiseObject =
                        do
                                _.chain controllers
                                .map makeAsyncControllerParse
                                .reduce _.extend
                                .value

                # Once everything is done from above, we return back the collective promise object and
                # pipe that to whomever feels fit.
                return Promise.props promiseObject

Promise = require 'bluebird'
fs = Promise.promisifyAll require 'fs'
_ = require 'lodash'

module.exports = () ->

	# For performance reasons, we'll do this asynchronously.
	fs.readdirAsync('./controllers/').then (controllers) ->

		#This probably isn't necessary: I wanted to parse through and grab all these controllers
		# asynchronously, so I threw them in a promise
		makeAsyncControllerParse = (file) ->
			return new Promise (resolve, reject) ->
				if file.match(/.+\.js/g)? or file.match(/.+\.coffee/g)?
					# When requiring the module, we don't really want to specify an extension.
					# Let's get rid of it.
					myObject = {}
					name = file.replace('.js', '').replace('.coffee', '')

					# Require the controller, feed it into the controllers
					myObject[name] = require "../controllers/#{name}"
					resolve(myObject)

		# Create a big ol' object of all the promises so that we have a handle on all the files.
		#
		# We're utilizing lodash's "chain" function simply because it gives us somewhat sane list
		# comprehension comparable to linq.
		promiseObject =
			do
				_.chain controllers
				.map makeAsyncControllerParse
				.reduce _.extend
				.value

		# Once everything is done from above, we return back the collective promise object and
		# pipe that to whomever feels fit.
		return Promise.props promiseObject

Convert to using tabs so as to allow editor diversity.


window.LC = window.LC ? {}

slice = Array.prototype.slice

LC.util =
  last: (array, n = null) ->
    if n
      return slice.call(array, Math.max(array.length - n, 0))
    else
      return array[array.length - 1]

  sizeToContainer: (canvas, callback = ->) ->
    $canvas = $(canvas)
    $container = $canvas.parent()
    resize = =>
      canvas.style.height = "#{$container.height()}px"
      canvas.setAttribute('width', $canvas.width())
      canvas.setAttribute('height', $canvas.height())
      callback()

    $container.resize(resize)
    $(window).bind('orientationchange resize', resize)
    resize()

  combineCanvases: (a, b) ->
    c = $('<canvas>').get(0)
    c.width = Math.max(a.width, b.width)
    c.height = Math.max(a.height, b.height)
    ctx = c.getContext('2d')
    ctx.drawImage(a, 0, 0)
    ctx.drawImage(b, 0, 0)
    c

window.LC = window.LC ? {}

slice = Array.prototype.slice

LC.util =
  last: (array, n = null) ->
    if n
      return slice.call(array, Math.max(array.length - n, 0))
    else
      return array[array.length - 1]

  sizeToContainer: (canvas, callback = ->) ->
    $canvas = $(canvas)
    $container = $canvas.parent()
    resize = =>
      canvas.style.width = "#{$container.width()}px"
      canvas.style.height = "#{$container.height()}px"
      canvas.setAttribute('width', $canvas.width())
      canvas.setAttribute('height', $canvas.height())
      callback()

    $container.resize(resize)
    $(window).bind('orientationchange resize', resize)
    resize()

  combineCanvases: (a, b) ->
    c = $('<canvas>').get(0)
    c.width = Math.max(a.width, b.width)
    c.height = Math.max(a.height, b.height)
    ctx = c.getContext('2d')
    ctx.drawImage(a, 0, 0)
    ctx.drawImage(b, 0, 0)
    c

Fix sizeToContainer - actually set width


BaseTool = window.Ubret.BaseTool or require('./base_tool')

class SubjectViewer extends BaseTool
  name: 'Subject Viewer'
  template:
    """

      <% for(i = 0; i < keys.length; i++) { %>

          <%- keys[i] %>: <%- subject[keys[i]] %>

      <% } %>

    """

  start: =>
    # data = @dimensions.id.top(Infinity)
    unless @selectedElements
      subject = @data[0]
      # subject = data[0]
    else
      subject = _.find data, (record) =>
        record.id == @selectedElements[0]

    compiled = _.template @template, { subject: subject, keys: @keys }
    @el.html compiled

if typeof require is 'function' and typeof module is 'object' and typeof exports is 'object'
  module.exports = SubjectViewer
else
  window.Ubret['SubjectViewer'] = SubjectViewer

BaseTool = window.Ubret.BaseTool or require('./base_tool')

class SubjectViewer extends BaseTool

  constructor: (opts) ->
    super
    @count = 0
    @div = d3.select(@selector)
    @start()

  start: =>
    subjects = new Array
    if @selectedElements.length isnt 0
      subjects = @dimensions.uid.top(Infinity).filter (item) =>
        item.uid in @selectedElements
    else
      subjects = [@dimensions.uid.top(1)[0]]
      @selectElements subjects
    @render(subjects)

  render: (subjects) =>
    @div.selectAll('div.subject').remove()

    subject = @div.selectAll('div')
      .data(subjects).enter()
        .append('div')
        .attr('class', 'subject')

    subject.selectAll('img')
      .append('img')
        .attr('src', (d) -> d.image)

    subject.selectAll('ul')
      .append('ul')
      .data((d) => @toArray(d)).enter()
        .append('li')
        .attr('data-key', (d) -> d[0])
        .text((d) => "#{@formatKey(d[0])}: #{d[1]}")

    subject.select("[data-key=\"#{@selectedKey}\"]")
      .attr('class', 'selected')

  toArray: (data) =>
    arrayedData = new Array
    arrayedData.push [key, data[key]] for key in @keys
    arrayedData

if typeof require is 'function' and typeof module is 'object' and typeof exports is 'object'
  module.exports = SubjectViewer
else
  window.Ubret['SubjectViewer'] = SubjectViewer

Revert to multi-select version of subejct_viewer


$(document).load ->
  readyMenuToggle()
  registerJobPriority()

$(document).on 'ready page:change', ->
  readyMenuToggle()
  registerJobPriority()

readyMenuToggle = ->
  $('#menu-toggle').click (e) ->
    e.preventDefault()
    $('#wrapper').toggleClass 'toggled'

  $('#menu-close').click (e) ->
    e.preventDefault()
    $('#wrapper').toggleClass 'toggled'

registerJobPriority = ->
  $('#increase_priority').on 'click', ->
    $('#job_priority').val(parseInt($('#job_priority').val(), 10) + 1)

  $('#decrease_priority').on 'click', ->
    console.log 'decreasing'
    $('#job_priority').val(parseInt($('#job_priority').val(), 10) - 1)

$(document).load ->
  readyMenuToggle()
  registerJobPriority()

$(document).on 'ready page:change', ->
  readyMenuToggle()
  registerJobPriority()

readyMenuToggle = ->
  $('#menu-toggle').click (e) ->
    e.preventDefault()
    $('#wrapper').toggleClass 'toggled'

  $('#menu-close').click (e) ->
    e.preventDefault()
    $('#wrapper').toggleClass 'toggled'

registerJobPriority = ->
  $('#increase_priority').on 'click', ->
    $('#job_priority').val(parseInt($('#job_priority').val(), 10) + 1)

  $('#decrease_priority').on 'click', ->
    $('#job_priority').val(parseInt($('#job_priority').val(), 10) - 1)

Remove console log message from decrease job priority button.


googleTranslate = new practical.GoogleTranslate()

Tinytest.add 'Google Translate - should translate text' , (test)->
  translation = googleTranslate.translate("My name is Brandon", "es")
  expect(translation).to.be.an("Object")
  expect(translation.translatedText).to.equal("Mi Nombre Es Brandon")

googleTranslate = new practical.GoogleTranslate()

Tinytest.add 'Google Translate - should translate text' , (test)->
  translation = googleTranslate.translate("my name is Brandon", "es")
  expect(translation).to.be.an("Object")
  expect(translation.translatedText).to.equal("mi nombre es Brandon")

Tinytest.add 'Google Translate - should translate text with multiple lines' , (test)->
  translation = googleTranslate.translate("my name is Brandon\ni like apples\n", "es")
  expect(translation).to.be.an("Object")
  expect(translation.translatedText).to.equal("mi nombre es Brandon me gusta manzanas")

Add test for multiple lines translation

Add test for multiple lines translation


require 'should'

Base58 = require '..'

examples = require './examples'

describe 'Base58', ->
  describe '.encode', ->
    it 'encodes number to Base58 string', ->
      for str, num of examples
        Base58.encode(num).should.eql(str)

    describe 'when passed a string only containing numbers', ->
      it 'encodes string after first converting it to an integer', ->
        for str, num of examples
          Base58.encode(num.toString()).should.eql(str)

    describe 'when passed a float', ->
      it 'throws an error', ->
        (-> Base58.encode(3.14)).should
          .throw('Value passed is not an integer.')

    describe 'when passed a non-number value', ->
      it 'throws an error', ->
        (-> Base58.encode('hi')).should
          .throw('Value passed is not an integer.')

  describe '.decode', ->
    it 'decodes Base58 string to number', ->
      for str, num of examples
        Base58.decode(str).should.eql(num)

    describe 'when passed a non-Base58 string', ->
      it 'throws an error', ->
        (-> Base58.decode('>_<')).should
          .throw('Value passed is not a valid Base58 string.')

should = require 'should'

Base58 = require '..'

describe 'Base58', ->
  beforeEach ->
    @examples = require './examples' unless @examples?
    should.exist(@examples)

  describe '.encode', ->
    it 'encodes number to Base58 string', ->
      for str, num of @examples
        Base58.encode(num).should.eql(str)

    describe 'when passed a string only containing numbers', ->
      it 'encodes string after first converting it to an integer', ->
        for str, num of @examples
          Base58.encode(num.toString()).should.eql(str)

    describe 'when passed a float', ->
      it 'throws an error', ->
        (-> Base58.encode(3.14)).should
          .throw('Value passed is not an integer.')

    describe 'when passed a non-number value', ->
      it 'throws an error', ->
        (-> Base58.encode('hi')).should
          .throw('Value passed is not an integer.')

  describe '.decode', ->
    it 'decodes Base58 string to number', ->
      for str, num of @examples
        Base58.decode(str).should.eql(num)

    describe 'when passed a non-Base58 string', ->
      it 'throws an error', ->
        (-> Base58.decode('>_<')).should
          .throw('Value passed is not a valid Base58 string.')

Update test with slightly cleaner and safer code


Q = require('q')
async = require('async')

Theme = require('../../models/theme').model
HeadlineService = require('../services/headline')

module.exports = class ThemePresenter
  constructor: (@theme) ->

  @populateIndicatorRecencyStats: (themes) ->
    for theme in themes
      theme.outOfDateIndicatorCount = 0
      for indicator in theme.indicators
        indicator.isUpToDate = HeadlineService.narrativeRecencyTextIsUpToDate(
          indicator.narrativeRecency
        )
        unless indicator.isUpToDate
          theme.outOfDateIndicatorCount++

  filterIndicatorsWithData: ->
    deferred = Q.defer()

    indicatorsWithData = []

    indicatorHasData = (indicator, callback) ->
      indicator.hasData().then( (hasData) ->
        if hasData
          indicatorsWithData.push(indicator)

        callback(null)
      ).fail(callback)

    if @theme.indicators?
      async.each @theme.indicators, indicatorHasData, (err) =>
        if err?
          deferred.reject(err)
        else
          @theme.indicators = indicatorsWithData
          deferred.resolve()
    else
      deferred.reject(new Error('filterIndicatorsWithData called on a theme without an indicator attribute'))

    deferred.promise

  @populateIndicators: (themes, filter) ->
    Q.nfcall(
      async.each, themes, (theme, callback) ->
        Q.nfcall(
          Theme.getIndicatorsByTheme, theme.id, filter
        ).then( (indicators) ->
          theme.indicators = indicators
          callback()
        ).fail(callback)
    )

Q = require('q')
async = require('async')

Theme = require('../../models/theme').model
HeadlineService = require('../services/headline')

module.exports = class ThemePresenter
  constructor: (@theme) ->

  @populateIndicatorRecencyStats: (themes) ->
    for theme in themes
      theme.outOfDateIndicatorCount = 0
      for indicator in theme.indicators
        indicator.isUpToDate = HeadlineService.narrativeRecencyTextIsUpToDate(
          indicator.narrativeRecency
        )
        unless indicator.isUpToDate
          theme.outOfDateIndicatorCount++

  filterIndicatorsWithData: ->
    deferred = Q.defer()

    indicatorsWithData = []

    indicatorHasData = (indicator, callback) ->
      indicator.hasData().then( (hasData) ->
        if hasData
          indicatorsWithData.push(indicator)

        callback(null)
      ).catch(callback)

    if @theme.indicators?
      async.each @theme.indicators, indicatorHasData, (err) =>
        if err?
          deferred.reject(err)
        else
          @theme.indicators = indicatorsWithData
          deferred.resolve()
    else
      deferred.reject(new Error('filterIndicatorsWithData called on a theme without an indicator attribute'))

    deferred.promise

  @populateIndicators: (themes, filter) ->
    Q.nfcall(
      async.each, themes, (theme, callback) ->
        Q.nfcall(
          Theme.getIndicatorsByTheme, theme.id, filter
        ).then( (indicators) ->
          theme.indicators = indicators
          callback()
        ).catch(callback)
    )

Use catch rather than fail, as bluebird only supports catch


#= require partystreusel/base
#= require partystreusel/scroll_to
#= require jquery.cycle2
#= require jquery.cycle2.swipe

class Slider extends Partystreusel.Base
  @className = 'Slider'

  constructor: (el) ->
    super
    @initializeCycle()

  initializeCycle: ->
    # see for documenation and options:
    # https://github.com/malsup/cycle2
    @$el.cycle
      slides: '.slider__item'
      fx: 'scrollHorz'
      speed: 300
      timeout: 0
      next: '.slider__control-next'
      prev: '.slider__control-prev'
      pager: '.slider__nav'
      pagerActiveClass: 'slider__nav-item--active'
      pagerTemplate: ""
      swipe: true

Partystreusel.Slider = Slider

#= require partystreusel/base
#= require partystreusel/scroll_to
#= require jquery.cycle2
#= require jquery.cycle2.swipe

class Slider extends Partystreusel.Base
  @className = 'Slider'

  constructor: (el) ->
    super
    @slidelist = @$el.find('.slider__list')
    @initializeCycle()

  initializeCycle: ->
    # see for documenation and options:
    # https://github.com/malsup/cycle2
    @slidelist.cycle
      slides: '.slider__item'
      fx: 'scrollHorz'
      speed: 300
      timeout: 0
      next: '.slider__control-next'
      prev: '.slider__control-prev'
      pager: '.slider__nav'
      pagerActiveClass: 'slider__nav-item--active'
      pagerTemplate: ""
      swipe: true

Partystreusel.Slider = Slider

Initialize slider on top element of slider


angular.module("app").filter "formatVotes", () ->
    (number) ->  # TODO  use real precision, not available in web wallet yet
        return number / 100000

angular.module("app").filter "formatVotes", ($filter) ->
    (number) ->  # TODO  use real precision, not available in web wallet yet
        return $filter('number')(number / 100000,0)+' BTS'

Make votes format a bit prettier: Add number formatting and BTS unit


{Serenade} = require './serenade'
{Cache} = require './cache'
{Associations} = require './associations'
{extend} = require './helpers'

class Serenade.Model
  extend(@prototype, Serenade.Properties)
  extend(@prototype, Associations)

  @property: -> @prototype.property(arguments...)
  @collection: -> @prototype.collection(arguments...)
  @belongsTo: -> @prototype.belongsTo(arguments...)
  @hasMany: -> @prototype.hasMany(arguments...)

  @find: (id) -> Cache.get(this, id) or new this(id: id)

  @property 'id', serialize: true

  @extend: (name, ctor) ->
    class New extends this
      @modelName: name
      constructor: ->
        super
        ctor.apply(this, arguments) if ctor

  constructor: (attributes, bypassCache=false) ->
    unless bypassCache
      if attributes?.id
        fromCache = Cache.get(@constructor, attributes.id)
        if fromCache
          fromCache.set(attributes)
          return fromCache
        else
          Cache.set(@constructor, attributes.id, this)
    if @constructor.localStorage is 'save'
      @bind('saved', => Cache.store(@constructor, @get('id'), this))
    else if @constructor.localStorage
      @bind('change', => Cache.store(@constructor, @get('id'), this))
    @set(attributes)

  save: ->
    @trigger('saved')

{Serenade} = require './serenade'
{Cache} = require './cache'
{Associations} = require './associations'
{extend} = require './helpers'

class Serenade.Model
  extend(@prototype, Serenade.Properties)
  extend(@prototype, Associations)

  @property: -> @prototype.property(arguments...)
  @collection: -> @prototype.collection(arguments...)
  @belongsTo: -> @prototype.belongsTo(arguments...)
  @hasMany: -> @prototype.hasMany(arguments...)

  @find: (id) -> Cache.get(this, id) or new this(id: id)

  @property 'id', serialize: true

  @extend: (name, ctor) ->
    class New extends this
      @modelName: name
      constructor: ->
        super
        ctor.apply(this, arguments) if ctor

  constructor: (attributes, bypassCache=false) ->
    unless bypassCache
      if attributes?.id
        fromCache = Cache.get(@constructor, attributes.id)
        if fromCache
          fromCache.set(attributes)
          # temporary workaround until CS bug is fixed
          # otherwise, we neither return the cached object
          # nor set attributes on the new one
          @set(attributes)
          return fromCache
        else
          Cache.set(@constructor, attributes.id, this)
    if @constructor.localStorage is 'save'
      @bind('saved', => Cache.store(@constructor, @get('id'), this))
    else if @constructor.localStorage
      @bind('change', => Cache.store(@constructor, @get('id'), this))
    @set(attributes)

  save: ->
    @trigger('saved')

Work around CS identity map bug

Work around CS identity map bug


config =
  data_file_location: 'http://www.chimpandsee.org/identified-chimps/identified-species.json'
  is_scientist: 'no' # This doesn't do anything yet.
  speciesToTrack: ['chimpanzee', 'other-primate']

pairs = location.search.slice(1).split(',')
for pair in pairs
  for key, value of pair
    continue unless config.hasOwnProperty(key)
    config[key] = value

module.exports = config

config =
  data_file_location: 'https://www.chimpandsee.org/identified-chimps/identified-species.json'
  is_scientist: 'no' # This doesn't do anything yet.
  speciesToTrack: ['chimpanzee', 'other-primate']

pairs = location.search.slice(1).split(',')
for pair in pairs
  for key, value of pair
    continue unless config.hasOwnProperty(key)
    config[key] = value

module.exports = config

Update data file location to use https

Update data file location to use https


"*":
  core:
    disabledPackages: [
      "background-tips"
      "exception-reporting"
      "metrics"
      "styleguide"
      "timecop"
      "welcome"
    ]
    telemetryConsent: "no"
  editor:
    invisibles: {}
    showIndentGuide: true
    showInvisibles: true
  "file-icons":
    forceShow: true
    onChanges: true
  "line-ending-selector":
    defaultLineEnding: "LF"
  linter:
    lintOnChange: false
  "markdown-preview":
    useGitHubStyle: true
  "omni-ruler":
    columns: [
      "80"
      "100"
      "120"
      "200"
    ]
  pigments:
    markerType: "native-dot"
    mergeColorDuplicates: true
  "spell-check":
    locales: [
      "en-US"
    ]

Set Atom spell-check locales to en-US

Set Atom spell-check locales to en-US

A workaround to fix the "Cannot load the system dictionary..." error
message when opening Atom.


angular.module("admin.utils").directive "datepicker", ($window, $timeout) ->
  require: "ngModel"
  link: (scope, element, attrs, ngModel) ->
    $timeout ->
      flatpickr(element,  Object.assign(
                            {},
                            $window.FLATPICKR_DATE_DEFAULT, {
                            onOpen: (selectedDates, dateStr, instance) ->
                              instance.setDate(ngModel.$modelValue)
                            }
                          ));

angular.module("admin.utils").directive "datepicker", ($window, $timeout) ->
  require: "ngModel"
  link: (scope, element, attrs, ngModel) ->
    $timeout ->
      flapickrInstance = flatpickr(element,  Object.assign(
                            {},
                            $window.FLATPICKR_DATE_DEFAULT, {
                            onOpen: (selectedDates, dateStr, instance) ->
                              instance.setDate(ngModel.$modelValue)
                            }
                          ));
      ngModel.$render = () ->
        newValue = ngModel.$viewValue;
        flapickrInstance?.setDate(newValue)

Update flatpickr input value if ng-model change


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

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

    propTypes:
        unlabled:  React.PropTypes.bool

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

    renderEdit: (label) ->
        colProps = _.omit(@props, 'name')
        <BS.Col {...colProps} >
            <BS.Input
                ref="input"
                className={_.classnames('value', changeset: @state.changeset)}
                type='text'
                label={label}
                value={@props.model[@props.name]}
                onChange={@handleChange}
                {...@props}
            />
        </BS.Col>

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

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

    propTypes:
        unlabled:  React.PropTypes.bool

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

    renderEdit: (label) ->
        colProps = _.omit(@props, 'name')
        value = @props.model[@props.name] or ''
        <BS.Col {...colProps} >
            <BS.Input
                ref="input"
                className={_.classnames('value', changeset: @state.changeset)}
                type='text'
                label={label}
                value={value}
                onChange={@handleChange}
                {...@props}
            />
        </BS.Col>

Set to empty string instead of undefined


class visualization.Simple

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

  # Build layer as wanted
  buildLayerGroup: (widget, globalStyle = {}) ->
    group = []
    for zone in @data
      zoneLayer = new L.GeoJSON(zone.shape, globalStyle)
      widget._bindPopup(zoneLayer, zone)
      group.push(zoneLayer)
    group

  # Build HTML legend for given categories computed layer
  buildLegend: () ->
    html  = "
"
    # html += "
#{@layer.label}
"
    html += "
"
    html += ""
    html += ""
    html += ""
    html += " #{@layer.label}"
    html += ""
    html += ""
    html += "
"
    html += "
"
    return html

  # Check if categories are valid
  valid: () ->
    true

visualization.registerLayerType "simple", visualization.Simple

class visualization.Simple

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

  # Build layer as wanted
  buildLayerGroup: (widget, globalStyle = {}) ->
    group = []
    for zone in @data
      zoneLayer = new L.GeoJSON(zone.shape, globalStyle)
      zoneLayer.bindLabel(zone.name, globalStyle)
      widget._bindPopup(zoneLayer, zone)
      group.push(zoneLayer)
    group

  # Build HTML legend for given categories computed layer
  buildLegend: () ->
    html  = "
"
    # html += "
#{@layer.label}
"
    html += "
"
    html += ""
    html += ""
    html += ""
    html += " #{@layer.label}"
    html += ""
    html += ""
    html += "
"
    html += "
"
    return html

  # Check if categories are valid
  valid: () ->
    true

visualization.registerLayerType "simple", visualization.Simple

Add static label in simple visualisation map.