checkOuterPages = (url) =>
  outerPages = ["docs", "about", "privacy", "pricing"]
  for page in outerPages
    if (url.match "^/#{page}.*")
      return "/"
  return url

CI.github =
  # we encore each parammeter separately (one of them twice!) to get the right format
  authUrl: (scope=["user", "repo"]) =>
    destination = window.location.pathname
    destination = checkOuterPages(destination)
    destination = encodeURIComponent(destination)

    path = "https://github.com/login/oauth/authorize"
    client_id = window.renderContext.githubClientId
    scope = scope.join ","
    scope = encodeURIComponent(scope)

    redirect = "#{window.location.origin}/auth/github?return-to=#{destination}"
    redirect = encodeURIComponent(redirect)
    "#{path}?client_id=#{client_id}&redirect_uri=#{redirect}&scope=#{scope}"

checkOuterPages = (url) =>
  outerPages = ["docs", "about", "privacy", "pricing"]
  for page in outerPages
    if (url.match "^/#{page}.*")
      return "/"
  return url

CI.github =
  # we encore each parammeter separately (one of them twice!) to get the right format
  authUrl: (scope=["user", "repo"]) =>
    destination = window.location.pathname
    destination = checkOuterPages(destination)
    destination = encodeURIComponent(destination)

    path = "https://github.com/login/oauth/authorize"
    client_id = window.renderContext.githubClientId
    scope = scope.join ","
    scope = encodeURIComponent(scope)

    redirect = "#{window.location.href}/auth/github?return-to=#{destination}"
    redirect = encodeURIComponent(redirect)
    "#{path}?client_id=#{client_id}&redirect_uri=#{redirect}&scope=#{scope}"

Fix login problems on firefox

Fix login problems on firefox


LocalBranch = require './local-branch'

{git} = require '../../git'

module.exports =
class CurrentBranch extends LocalBranch
  initialize: ->
    @reload()

  reload: ->
    git.branch (head) =>
      @set head

    git.gitNoChange "log @{u}..", (output) =>
      @set unpushed: (output != "")

  head: ->
    "HEAD"

  delete: -> null

  checkout: -> null

LocalBranch = require './local-branch'

{git} = require '../../git'

module.exports =
class CurrentBranch extends LocalBranch
  initialize: ->
    @reload()

  reload: ->
    git.branch (head) =>
      @set head

    # git.gitNoChange "log @{u}..", (output) =>
    #   @set unpushed: (output != "")

  head: ->
    "HEAD"

  delete: -> null

  checkout: -> null

Remove pushed/unpushed status for now.

Remove pushed/unpushed status for now.

# Compose your commit message. Press `cmd-alt-c` to commit. Close to cancel.


express = require 'express'
passport = require 'passport'

router = express.Router()

router.post '/login', passport.authenticate 'local',
  successRedirect: '/app'
  failureRedirect: '/'
  failureFlash: 'Invalid username or password!'

module.exports = router

express = require 'express'
passport = require 'passport'

router = express.Router()

router.post '/login', passport.authenticate 'local',
  successRedirect: '/admin'
  failureRedirect: '/'
  failureFlash: 'Invalid username or password!'

module.exports = router

Fix wrong redirect after logging in

Fix wrong redirect after logging in


React = require 'react'
Nav = React.createFactory require 'antwar-default-theme/Nav'
Paths = require('antwar-core/PathsMixin')
require 'antwar-default-theme/scss/main.scss'

require 'react-ghfork/gh-fork-ribbon.ie.css' # ie support
require 'react-ghfork/gh-fork-ribbon.css'
Fork = React.createFactory(require 'react-ghfork')

{ div, main, script, link } = require 'react-coffee-elements'

config = require 'config'
if config.theme.customStyles?
  require 'customStyles/' + config.theme.customStyles

module.exports = React.createClass

    displayName: 'Body'

    mixins: [
        Paths
    ]

    render: ->
        sectionName = @getSectionName()

        itemTitle = @getItem().title;

        div { },
            if sectionName and sectionName != '/'
                Nav()
                Fork { className: 'right ribbon', project: "survivejs/webpack_react/issues/new?title=#{itemTitle} - ", text: 'Submit feedback', style: {backgroundColor: 'black'}}
            main { role: 'main' }, @props.children

React = require 'react'
Nav = React.createFactory require 'antwar-default-theme/Nav'
Paths = require('antwar-core/PathsMixin')
require 'antwar-default-theme/scss/main.scss'

require 'react-ghfork/gh-fork-ribbon.ie.css' # ie support
require 'react-ghfork/gh-fork-ribbon.css'
Fork = React.createFactory(require 'react-ghfork')

{ div, main, script, link } = require 'react-coffee-elements'

config = require 'config'
if config.theme.customStyles?
  require 'customStyles/' + config.theme.customStyles

module.exports = React.createClass

    displayName: 'Body'

    mixins: [
        Paths
    ]

    render: ->
        sectionName = @getSectionName()

        itemTitle = @getItem().title;

        div { },
            if sectionName and sectionName != '/'
                Nav()
                Fork { className: 'right ribbon', project: "survivejs/webpack_react/issues/new?title=#{itemTitle} - ", text: 'Submit feedback', style: {backgroundColor: 'black'}, target: '_blank'}
            main { role: 'main' }, @props.children

Set `target: _blank` on submit feedback

Set `target: _blank` on submit feedback

Better ux.


Template.loginLayout.rendered = ->
	$('html').addClass("scroll").removeClass "noscroll"
	window.pJSDom = []
	particlesJS.load 'particles-js', '/scripts/particles.json', ->

Template.loginLayout.rendered = ->
	$('html').addClass("scroll").removeClass "noscroll"
	if not Meteor.isCordova
		window.pJSDom = []
		particlesJS.load 'particles-js', '/scripts/particles.json', ->

Disable particles in mobile login

Disable particles in mobile login


#= require cmsimple/panels/images/panel
class CMSimple.Panels.ImageLibrary.List extends Spine.Controller
  events:
    'click .media-actions > .info' : 'toggleInfo'
    'click .media-info > .close' : 'toggleInfo'
    'click [data-full-url]' : 'triggerImage'
    'click .delete' : 'deleteImage'

  constructor: (el)->
    super el: $(el)

    CMSimple.Image.bind 'refresh change', => @render()
    CMSimple.Image.fetch()

  render: ->
    @html('')
    @addImage image for image in CMSimple.Image.all()

  addImage: (image)->
    @append JST['cmsimple/views/image_library_item'](image)

  toggleInfo: (e) ->
    e.preventDefault()
    info = $(e.target).parents('li').first().find('.media-info')[0]
    $(info).toggleClass('active')

  triggerImage: (e)->
    img = $(e.target)
    @trigger 'image:selected', src: img.data('full-url'), 'image-id': img.data('id')

  deleteImage: (e)->
    e.preventDefault()
    link = $(e.target)
    if confirm 'Are you sure you would like to delete this image?'
      id = link.parents('[data-id]').data('id')
      image = CMSimple.Image.find(id)
      image.destroy()

#= require cmsimple/panels/images/panel
class CMSimple.Panels.ImageLibrary.List extends Spine.Controller
  events:
    'click .media-actions > .info' : 'toggleInfo'
    'click .media-info > .close' : 'toggleInfo'
    'click [data-full-url]' : 'triggerImage'
    'click .delete' : 'deleteImage'

  constructor: (el)->
    super el: $(el)

    CMSimple.Image.bind 'refresh change', => @render()
    CMSimple.Image.fetch()

  render: ->
    @html('')
    @addImage image for image in CMSimple.Image.all()

  addImage: (image)->
    @append JST['cmsimple/views/image_library_item'](image)

  toggleInfo: (e) ->
    e.preventDefault()
    info = $(e.target).parents('li').first().find('.media-info')[0]
    $(info).toggleClass('active')

  triggerImage: (e)->
    img = $(e.target)
    image = CMSimple.Image.find(img.data('id'))
    @trigger 'image:selected',
        src: img.data('full-url'),
        alt: image.title,
        width: image.width,
        height: image.height,
        'image-id': image.id

  deleteImage: (e)->
    e.preventDefault()
    link = $(e.target)
    if confirm 'Are you sure you would like to delete this image?'
      id = link.parents('[data-id]').data('id')
      image = CMSimple.Image.find(id)
      image.destroy()

Set image properties when inserting an image.


# Import common modules.
module.exports = require '../../../../common/api/lib/exports/electron'

v8Util = process.atomBinding 'v8_util'
v8Util.setHiddenValue module.exports, 'electronModule', true

Object.defineProperties module.exports,
  # Browser side modules, please sort with alphabet order.
  app:
    enumerable: true
    get: -> require '../app'
  autoUpdater:
    enumerable: true
    get: -> require '../auto-updater'
  BrowserWindow:
    enumerable: true
    get: -> require '../browser-window'
  contentTracing:
    enumerable: true
    get: -> require '../content-tracing'
  dialog:
    enumerable: true
    get: -> require '../dialog'
  ipcMain:
    enumerable: true
    get: -> require '../ipc-main'
  globalShortcut:
    enumerable: true
    get: -> require '../global-shortcut'
  Menu:
    enumerable: true
    get: -> require '../menu'
  MenuItem:
    enumerable: true
    get: -> require '../menu-item'
  powerMonitor:
    enumerable: true
    get: -> require '../power-monitor'
  powerSaveBlocker:
    enumerable: true
    get: -> require '../power-save-blocker'
  protocol:
    enumerable: true
    get: -> require '../protocol'
  screen:
    enumerable: true
    get: -> require '../screen'
  tray:
    enumerable: true
    get: -> require '../tray'
  # The internal modules, invisible unless you know their names.
  NavigationController:
    get: -> require '../navigation-controller'
  webContents:
    get: -> require '../web-contents'

# Import common modules.
module.exports = require '../../../../common/api/lib/exports/electron'

v8Util = process.atomBinding 'v8_util'
v8Util.setHiddenValue module.exports, 'electronModule', true

Object.defineProperties module.exports,
  # Browser side modules, please sort with alphabet order.
  app:
    enumerable: true
    get: -> require '../app'
  autoUpdater:
    enumerable: true
    get: -> require '../auto-updater'
  BrowserWindow:
    enumerable: true
    get: -> require '../browser-window'
  contentTracing:
    enumerable: true
    get: -> require '../content-tracing'
  dialog:
    enumerable: true
    get: -> require '../dialog'
  ipcMain:
    enumerable: true
    get: -> require '../ipc-main'
  globalShortcut:
    enumerable: true
    get: -> require '../global-shortcut'
  Menu:
    enumerable: true
    get: -> require '../menu'
  MenuItem:
    enumerable: true
    get: -> require '../menu-item'
  powerMonitor:
    enumerable: true
    get: -> require '../power-monitor'
  powerSaveBlocker:
    enumerable: true
    get: -> require '../power-save-blocker'
  protocol:
    enumerable: true
    get: -> require '../protocol'
  screen:
    enumerable: true
    get: -> require '../screen'
  Tray:
    enumerable: true
    get: -> require '../tray'
  # The internal modules, invisible unless you know their names.
  NavigationController:
    get: -> require '../navigation-controller'
  webContents:
    get: -> require '../web-contents'

Fix typo, tray => Tray

Fix typo, tray => Tray


React = require 'react'

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

  getInitialState: ->
    subject_sets: []

  componentWillMount: ->
    @props.workflow?.get 'subject_sets', page_size: 40
      .then (subject_sets) =>
        @setState {subject_sets}

  render: ->

Choose a report to work on

        {
{subject_set.display_name}
{subject_set.metadata.BOROUGH}
{subject_set.metadata.Date}
 for subject_set in @state.subject_sets}

  update: (e) ->
    subject_set_id = e.currentTarget.href.split('/').pop()
    @props.onChange subject_set_id

React = require 'react'

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

  getInitialState: ->
    subject_sets: []

  componentWillMount: ->
    @props.workflow?.get 'subject_sets', page_size: 40
      .then (subject_sets) =>
        subject_sets.sort (a, b) ->
          return 1 if a.metadata.BOROUGH > b.metadata.BOROUGH
          return -1 if a.metadata.BOROUGH  b.metadata['File prefix']
          return -1 if a.metadata['File prefix']

Choose a report to work on

        {
{subject_set.display_name}
{subject_set.metadata.BOROUGH}
{subject_set.metadata.Date}
 for subject_set in @state.subject_sets}

  update: (e) ->
    subject_set_id = e.currentTarget.href.split('/').pop()
    @props.onChange subject_set_id

Sort subject sets by borough and file id


describe 'PodsList', ->
  subject = null
  beforeEach (done) ->
    subject = new SeedsStore('test')
    expect(subject.clear()).eventually.notify(done)
  it 'counts 0', (done) ->
    expect(subject.countForAll()).eventually.equal(0).notify(done)
  it 'counts n', (done) ->
    subject.update([{name: 1},{name: 2},{name: 3}])
    expect(subject.countForAll()).eventually.equal(3).notify(done)
  it 'readPod', (done) ->
    subject.update([{name: 1}, {name: 2}])
    expect(subject.readPod(1)).eventually.eql([{name: 1}]).notify(done)
  describe 'readsFromAll', ->
    beforeEach (done) ->
      list = [{name: 1}, {name: 2}, {name: 3}, {name: 4}]
      expect(subject.update(list))
        .eventually.notify(done)
    it 'readsFromAll asc', (done) ->
      expect(subject.readFromAll('name', true, 1, 2)).eventually
        .eql([{name: 2}, {name: 3}]).notify(done)
    it 'readsFromAll desc', (done) ->
      expect(subject.readFromAll('name', false, 1, 2)).eventually
        .eql([{name: 3}, {name: 2}]).notify(done)

describe 'PodsList', ->
  subject = null
  beforeEach (done) ->
    subject = new SeedsStore('test')
    expect(subject.clear()).eventually.notify(done)
  it 'counts 0', (done) ->
    expect(subject.countForAll()).eventually.equal(0).notify(done)
  it 'counts n', (done) ->
    subject.update([{name: 1},{name: 2},{name: 3}])
    expect(subject.countForAll()).eventually.equal(3).notify(done)
  it 'readPod', (done) ->
    subject.update([{name: 1}, {name: 2}])
    expect(subject.readPod(1)).eventually.eql([{name: 1}]).notify(done)
  describe 'readsFromAll', ->
    beforeEach (done) ->
      list = [{name: 1}, {name: 2}, {name: 3}, {name: 4}]
      expect(subject.update(list))
        .eventually.notify(done)
    it 'readsFromAll name,asc from the beginning', (done) ->
      expect(subject.readFromAll('name', true, 0, 1)).eventually
        .eql([{name: 1}]).notify(done)
    it 'readsFromAll name,asc in the middle', (done) ->
      expect(subject.readFromAll('name', true, 1, 2)).eventually
        .eql([{name: 2}, {name: 3}]).notify(done)
    it 'readsFromAll name,asc out of scope', (done) ->
      expect(subject.readFromAll('name', true, 3, 2)).eventually
        .eql([{name: 4}]).notify(done)

Add specs for normal scope.

Add specs for normal scope.


#
Tether = require 'tether/tether'
assign = require 'object-assign'
React = require 'react'
$ = React.createElement

class Attachment extends React.Component
  componentDidMount: =>
    @root = document.createElement 'DIV'
    document.body.appendChild @root

    document.addEventListener 'mousedown', @handleEvent
    document.addEventListener 'focus', @handleEvent, true

    @tether = new Tether
      element: @root
      target: @props.target
      attachment: @props.attachment || 'top left'
      constraints: @props.constraints
      targetAttachment: @props.targetAttachment || 'bottom left'

    @componentDidUpdate()

  componentDidUpdate: =>
    React.render @renderAttachment(), @root, => @tether?.position()

  componentWillUnmount: =>
    React.unmountComponentAtNode @root

    @tether.destroy()
    document.body.removeChild @root
    document.removeEventListener 'mousedown', @handleEvent
    document.removeEventListener 'focus', @handleEvent

  handleEvent: (e) =>
    node = e.target

    while node != null
      return true if node == @root || node == @props.target
      node = node.parentNode

    @props.onCloseRequest?()
    true

  render: =>
    null

  renderAttachment: =>
    props = assign {}, @props

    delete props.target
    delete props.attachment
    delete props.constraints
    delete props.onCloseRequest
    delete props.targetAttachment

    $ 'div', props

module.exports = Attachment

#
Tether = require 'tether/tether'
assign = require 'object-assign'
React = require 'react'
$ = React.createElement

class Attachment extends React.Component
  componentDidMount: =>
    @root = document.createElement 'DIV'
    document.body.appendChild @root

    document.addEventListener 'mousedown', @handleEvent
    document.addEventListener 'focus', @handleEvent, true

    @tether = new Tether
      element: @root
      target: @props.target
      attachment: @props.attachment || 'top left'
      constraints: @props.constraints
      targetAttachment: @props.targetAttachment || 'bottom left'

    @componentDidUpdate()

  componentDidUpdate: =>
    React.render @renderAttachment(), @root, => @tether?.position()

  componentWillUnmount: =>
    React.unmountComponentAtNode @root

    @tether.destroy()
    document.body.removeChild @root
    document.removeEventListener 'mousedown', @handleEvent
    document.removeEventListener 'focus', @handleEvent, true

  handleEvent: (e) =>
    node = e.target

    while node != null
      return true if node == @root || node == @props.target
      node = node.parentNode

    @props.onCloseRequest?()
    true

  render: =>
    null

  renderAttachment: =>
    props = assign {}, @props

    delete props.target
    delete props.attachment
    delete props.constraints
    delete props.onCloseRequest
    delete props.targetAttachment

    $ 'div', props

module.exports = Attachment

Fix Attachment not correctly cleaning up listener


StatusBarView = require './status-bar-view'
FileInfoView = require './file-info-view'
CursorPositionView = require './cursor-position-view'
GrammarView = require './grammar-view'
GitView = require './git-view'

module.exports =
  activate: ->
    @statusBar = new StatusBarView()
    @statusBar.attach()

    @fileInfo = new FileInfoView(@statusBar)
    @statusBar.appendLeft(@fileInfo)

    @cursorPosition = new CursorPositionView(@statusBar)
    @statusBar.appendLeft(@cursorPosition)

    @git = new GitView(@statusBar)
    @statusBar.appendRight(@git)

StatusBarView = require './status-bar-view'
FileInfoView = require './file-info-view'
CursorPositionView = require './cursor-position-view'
GitView = require './git-view'

module.exports =
  activate: ->
    @statusBar = new StatusBarView()
    @statusBar.attach()

    @fileInfo = new FileInfoView(@statusBar)
    @statusBar.appendLeft(@fileInfo)

    @cursorPosition = new CursorPositionView(@statusBar)
    @statusBar.appendLeft(@cursorPosition)

    @git = new GitView(@statusBar)
    @statusBar.appendRight(@git)

Remove ref to status bar

Remove ref to status bar


class Backbone.PushableCollection extends Backbone.Collection
  initialize: () ->
    window.FayeClient.subscribe "/sync/#{@channel()}", _.bind(@receive, @)

  receive: (message) ->
    @[message.event] message.object

  create: (attributes) ->
    model = new @model attributes
    model.fetch()
    @add model

  update: (attributes) ->
    model = @get attributes.id
    model.set attributes

  destroy: (attributes) ->
    @remove @get(attributes.id)

class Backbone.PushableCollection extends Backbone.Collection
  initialize: () ->
    window.FayeClient.subscribe "/sync/#{@channel()}", _.bind(@receive, @)

  receive: (message) ->
    @[message.event] message.object

  create: (attributes) ->
    model = new @model attributes
    @add model

  update: (attributes) ->
    model = @get attributes.id
    model.set attributes

  destroy: (attributes) ->
    @remove @get(attributes.id)

Remove Fetch from PushableCollection Create Event


###*
# @overview Registers the custom button tag.
#
# @module stout-ui/button
###
defaults   = require 'lodash/defaults'
Button     = require './Button'
ButtonView = require './ButtonView'
parser     = require 'stout-client/parser'

# Read the button custom HTML tag.
TAG_NAME = vars.readPrefixed 'button/button-tag'

# Register the button tag.
parser.register TAG_NAME, ButtonView, Button, {contentsMember: 'label'}

module.exports = (init) ->
  defaults init, {context: new Button}
  (new ButtonView init).context

###*
# @overview Registers the custom button tag.
#
# @module stout-ui/button
###
defaults   = require 'lodash/defaults'
Button     = require './Button'
ButtonView = require './ButtonView'
parser     = require 'stout-client/parser'

# Read the button custom HTML tag.
TAG_NAME = vars.readPrefixed 'button/button-tag'

# Register the button tag.
parser.register TAG_NAME, ButtonView, Button, {contentsMember: 'label'}

module.exports = (init) ->
  defaults init, {context: new Button}

  view = new ButtonView init

  # Configure event proxying.
  init.context.proxyEvents view, 'blur focus active hover click leave'

  view.context

Add button interactive event proxying.

Add button interactive event proxying.


module.exports =
  treeView: null

  activate: (@state={}) ->
    @createView() if @state.attached
    rootView.command 'tree-view:toggle', => @createView().toggle()
    rootView.command 'tree-view:reveal-active-file', => @createView().revealActiveFile()

  deactivate: ->
    @treeView?.deactivate()
    @treeView = null

  serialize: ->
    if @treeView?
      @treeView.serialize()
    else
      @state

  createView: ->
    unless @treeView?
      TreeView = require 'tree-view/lib/tree-view'
      @treeView = new TreeView(@state)
    @treeView

module.exports =
  treeView: null

  activate: (@state) ->
    @createView() if @state.attached
    rootView.command 'tree-view:toggle', => @createView().toggle()
    rootView.command 'tree-view:reveal-active-file', => @createView().revealActiveFile()

  deactivate: ->
    @treeView?.deactivate()
    @treeView = null

  serialize: ->
    if @treeView?
      @treeView.serialize()
    else
      @state

  createView: ->
    unless @treeView?
      TreeView = require 'tree-view/lib/tree-view'
      @treeView = new TreeView(@state)
    @treeView

Remove unneeded param defaults from activate methods


#     NoFlo - Flow-Based Programming for JavaScript
#     (c) 2014-2015 TheGrid (Rituwall Inc.)
#     NoFlo may be freely distributed under the MIT license
#
# Platform detection method
exports.isBrowser = ->
  if typeof process isnt 'undefined' and process.execPath and process.execPath.match /node|iojs/
    return false
  true

exports.warnDeprecated = (message) ->
  if exports.isBrowser()
    throw new Error message if window.NOFLO_FATAL_DEPRECATED
    console.warn message
    return
  if process.env.NOFLO_FATAL_DEPRECATED
    throw new Error message
  console.warn message

Add method for optionally-fatal deprecation warnings


define [
    'jquery'
    'underscore'
    'backbone'
    'marionette'
    '../base'
    '../charts'
    '../charts/utils'
    'tpl!templates/field/stats.html'
], ($, _, Backbone, Marionette, base, charts, utils, templates...) ->

    templates = _.object ['layout'], templates

    class FieldStatValue extends Marionette.ItemView
        tagName: 'li'

        template: (data) ->
            "#{ data.label }#{ data.value }"

    class FieldStatsValues extends Marionette.CollectionView
        tagName: 'ul'

        itemView: FieldStatValue

    class FieldStatsChart extends charts.FieldChart
        className: 'sparkline'

        chartOptions: Backbone.Sparkline::chartOptions

        getChartOptions: (resp) ->
            options =
                series: [utils.getSeries(resp.data)]

            $.extend true, options, @chartOptions
            options.chart.renderTo = @ui.chart[0]
            return options

    class FieldStats extends Marionette.Layout
        className: 'field-stats'

        template: templates.layout

        regions:
            values: '.stats-values'
            chart: '.stats-chart'

        onRender: ->
            if @model.stats?
                @values.show new FieldStatsValues
                    collection: @model.stats
                if not @model.stats.length
                    @model.stats.fetch(reset: true)

    { FieldStats }

define [
    'jquery'
    'underscore'
    'backbone'
    'marionette'
    '../base'
    '../charts'
    '../charts/utils'
    'tpl!templates/field/stats.html'
], ($, _, Backbone, Marionette, base, charts, utils, templates...) ->

    templates = _.object ['layout'], templates

    class FieldStatValue extends Marionette.ItemView
        tagName: 'li'

        # This is a map of data labels to display labels. For example, when
        # displaying data with a label of 'Distinct count', it will be
        # rendered as 'Unique values' when this field stat value is displayed
        # in the page. If a data label is not in this map, then the data
        # label itself will be used.
        labelMap:
            'Distinct count': 'Unique values'

        template: (data) =>
            "#{ @labelMap[data.label] or data.label }#{ data.value }"

    class FieldStatsValues extends Marionette.CollectionView
        tagName: 'ul'

        itemView: FieldStatValue

    class FieldStatsChart extends charts.FieldChart
        className: 'sparkline'

        chartOptions: Backbone.Sparkline::chartOptions

        getChartOptions: (resp) ->
            options =
                series: [utils.getSeries(resp.data)]

            $.extend true, options, @chartOptions
            options.chart.renderTo = @ui.chart[0]
            return options

    class FieldStats extends Marionette.Layout
        className: 'field-stats'

        template: templates.layout

        regions:
            values: '.stats-values'
            chart: '.stats-chart'

        onRender: ->
            if @model.stats?
                @values.show new FieldStatsValues
                    collection: @model.stats
                if not @model.stats.length
                    @model.stats.fetch(reset: true)

    { FieldStats }

Add map of labels for statistical values

Currently, the only mapping is "Distinct count" --> "Unique values"


#= require jquery/dist/jquery
#= require jquery-deparam/jquery-deparam
#= require jquery.transit/jquery.transit
#= require slow-ajax
#= require bootstrap/dist/js/bootstrap
#= require highstock-release/highstock
#= require highstock-release/modules/exporting
#= require leaflet/dist/leaflet
#= require leaflet-override
#= require json2/json2
#= require underscore/underscore
#= require backbone/backbone
#= require geocens-js-api/geocens
#= require geocens-js-api/geocens-chart
#
#= require workbench

$(document).on "click", "a:not([data-bypass])", (evt) ->
  href = { prop: $(this).prop("href"), attr: $(this).attr("href") }
  root = location.protocol + "//" + location.host + Backbone.history.options.root

  if (href.prop && href.prop.slice(0, root.length) is root)
    route = href.prop.slice(root.length, href.prop.length).split("?")[0]
    evt.preventDefault()
    appRouter.navigate(route, { trigger: true })

#= require jquery/dist/jquery
#= require jquery-deparam/jquery-deparam
#= require jquery.transit/jquery.transit
#= require slow-ajax
#= require bootstrap/dist/js/bootstrap
#= require highstock-release/highstock
#= require highstock-release/modules/exporting
#= require leaflet/dist/leaflet
#= require ./leaflet-override
#= require json2/json2
#= require underscore/underscore
#= require backbone/backbone
#= require geocens-js-api/geocens
#= require geocens-js-api/geocens-chart
#
#= require workbench

$(document).on "click", "a:not([data-bypass])", (evt) ->
  href = { prop: $(this).prop("href"), attr: $(this).attr("href") }
  root = location.protocol + "//" + location.host + Backbone.history.options.root

  if (href.prop && href.prop.slice(0, root.length) is root)
    route = href.prop.slice(root.length, href.prop.length).split("?")[0]
    evt.preventDefault()
    appRouter.navigate(route, { trigger: true })

Use relative path for leaflet-override

Use relative path for leaflet-override


_ = require 'underscore'
Q = require 'q'
Backbone = require 'backbone'
{ API_URL } = require('sharify').data
Relations = require './mixins/relations/collector_profile.coffee'

module.exports = class CollectorProfile extends Backbone.Model
  _.extend @prototype, Relations

  url: "#{API_URL}/api/v1/me/collector_profile"

  validHashFields: [
    'owner'
    'institutional_affiliations'
    'confirmed_buyer_at'
    'collector_level'
  ]

  findOrCreate: (options = {}) ->
    { success, error } = options

    options = _.omit options, 'success', 'error'

    Q.promise (resolve, reject) =>
      @fetch _.extend {}, options,
        success: ->
          resolve arguments...
          success? arguments...
        error: =>
          @save {},
            success: ->
              resolve arguments...
              success? arguments...
            error: ->
              reject arguments...
              error? arguments...

_ = require 'underscore'
Q = require 'q'
Backbone = require 'backbone'
{ API_URL } = require('sharify').data
Relations = require './mixins/relations/collector_profile.coffee'

module.exports = class CollectorProfile extends Backbone.Model
  _.extend @prototype, Relations

  url: "#{API_URL}/api/v1/me/collector_profile"

  # Temporary hack around API bug surrounding valid hash fields...
  validHashFields: [
    'institutional_affiliations'
    'confirmed_buyer_at'
    'collector_level'
  ]

  # Ibid.
  setWithValidAttributes: (attributes = {}) ->
    existing = _.extend id: @id, _.pick(@attributes, @validHashFields)
    @clear()
    @set _.extend existing, _.pick(attributes, @validHashFields)

  findOrCreate: (options = {}) ->
    { success, error } = options

    options = _.omit options, 'success', 'error'

    Q.promise (resolve, reject) =>
      @fetch _.extend {}, options,
        success: ->
          resolve arguments...
          success? arguments...
        error: =>
          @save {},
            success: ->
              resolve arguments...
              success? arguments...
            error: ->
              reject arguments...
              error? arguments...

Expand on hack for valid hash fields

Expand on hack for valid hash fields


_ = require 'underscore'
{ Cities, FeaturedCities } = require 'places'
PartnerShows = require '../../../../collections/partner_shows.coffee'
RelatedShowsView = require './view.coffee'

module.exports = (type, show) ->

  city = _.findWhere(Cities, name: show.formatCity())

  el = $('.js-related-shows')

  criteria =
    sort: 'end_at'
    size: 4
    displayable: true

  relatedShows = new PartnerShows

  switch type
    when 'fair'
      data =  _.extend criteria, fair_id: show.related().fair.get('_id')
      title = "More Booths from #{show.related().fair.get('name')}"
    when 'gallery'
      data = _.extend criteria, sort: '-end_at', size: '8'
      relatedShows.url = "#{show.related().partner.url()}/shows"
      title = "Other Shows from #{show.partnerName()}"
    when 'featured'
      data = _.extend criteria, featured: true, status: 'running'
      el = $('.js-featured-shows')
      title = "Featured Shows"
    when 'city'
      data = _.extend criteria, near: city.coords.toString(), sort: '-start_at'
      title = "Current Shows in #{show.formatCity()}"

  new RelatedShowsView
    collection: relatedShows
    title: title
    el: el

  relatedShows.fetch
    data: data
    success: ->
      relatedShows.getShowsRelatedImages()

_ = require 'underscore'
{ Cities, FeaturedCities } = require 'places'
PartnerShows = require '../../../../collections/partner_shows.coffee'
RelatedShowsView = require './view.coffee'

module.exports = (type, show) ->

  city = _.findWhere(Cities, name: show.formatCity())

  el = $('.js-related-shows')

  criteria =
    sort: 'end_at'
    size: 20
    displayable: true

  relatedShows = new PartnerShows

  switch type
    when 'fair'
      data =  _.extend criteria, {
        fair_id: show.related().fair.get('_id')
      }
      title = "More Booths from #{show.related().fair.get('name')}"
    when 'gallery'
      data = _.extend criteria, {
        sort: '-start_at'
        status: "upcoming"
      }
      relatedShows.url = "#{show.related().partner.url()}/shows"
      title = "Other Shows from #{show.partnerName()}"
    when 'featured'
      data = _.extend criteria, {
        sort: 'end_at'
        featured: true
        status: 'running'
        displayable: true
      }
      el = $('.js-featured-shows')
      title = "Featured Shows"
    when 'city'
      data = _.extend criteria, {
        near: city.coords.toString()
        sort: 'end_at'
        status: 'running'
        displayable: true
      }
      title = "Current Shows in #{show.formatCity()}"

  new RelatedShowsView
    collection: relatedShows
    title: title
    el: el

  relatedShows.fetch
    data: data
    success: ->
      relatedShows.getShowsRelatedImages()

Change parameters by which shows are selected


{div} = React.DOM

module.exports = React.createClass

  displayName: 'Modal'

  watchForEscape: (e) ->
    if e.keyCode is 27
      @props.close?()

  # shadow the entire viewport behind the dialog
  getDimensions: ->
    width: $(window).width() + 'px'
    height: $(window).height() + 'px'

  getInitialState: ->
    dimensions = @getDimensions()
    initialState =
      backgroundStyle: @getBackgroundStyle dimensions
      contentStyle: @getContentStyle dimensions

  getBackgroundStyle: (dimensions) ->
    if @props.zIndex
      { zIndex: @props.zIndex, width: dimensions.width, height: dimensions.height }
    else
      dimensions

  getContentStyle: (dimensions) ->
    if @props.zIndex
      { zIndex: @props.zIndex + 1, width: dimensions.width, height: dimensions.height }
    else
      dimensions

  updateStyles: ->
    dimensions = @getDimensions()
    @setState
      backgroundStyle: @getBackgroundStyle dimensions
      contentStyle: @getContentStyle dimensions

  # use bind/unbind for clients using older versions of jQuery
  componentDidMount: ->
    $(window).bind 'keyup', @watchForEscape
    $(window).bind 'resize', @updateStyles

  componentWillUnmount: ->
    $(window).unbind 'keyup', @watchForEscape
    $(window).unbind 'resize', @updateStyles

  render: ->
    (div {className: 'modal'},
      (div {className: 'modal-background', style: @state.backgroundStyle})
      (div {className: 'modal-content', style: @state.contentStyle}, @props.children)
    )

{div} = React.DOM

module.exports = React.createClass

  displayName: 'Modal'

  watchForEscape: (e) ->
    if e.keyCode is 27
      @props.close?()

  # shadow the entire viewport behind the dialog
  getDimensions: ->
    width: '100vw'
    height: '100vh'

  getInitialState: ->
    dimensions = @getDimensions()
    initialState =
      backgroundStyle: @getBackgroundStyle dimensions
      contentStyle: @getContentStyle dimensions

  getBackgroundStyle: (dimensions) ->
    if @props.zIndex
      { zIndex: @props.zIndex, width: dimensions.width, height: dimensions.height }
    else
      dimensions

  getContentStyle: (dimensions) ->
    if @props.zIndex
      { zIndex: @props.zIndex + 1, width: dimensions.width, height: dimensions.height }
    else
      dimensions

  updateStyles: ->
    dimensions = @getDimensions()
    @setState
      backgroundStyle: @getBackgroundStyle dimensions
      contentStyle: @getContentStyle dimensions

  # use bind/unbind for clients using older versions of jQuery
  componentDidMount: ->
    $(window).bind 'keyup', @watchForEscape
    $(window).bind 'resize', @updateStyles

  componentWillUnmount: ->
    $(window).unbind 'keyup', @watchForEscape
    $(window).unbind 'resize', @updateStyles

  render: ->
    (div {className: 'modal'},
      (div {className: 'modal-background', style: @state.backgroundStyle})
      (div {className: 'modal-content', style: @state.contentStyle}, @props.children)
    )

Change height and width calculations to just use Viewport Width and Height


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

class Backbone.Views.IndicatorSelectorView extends Backbone.Diorama.NestingView
  template: Handlebars.templates['indicator_selector.hbs']
  className: 'modal indicator-selector'

  events:
    "click .close": "close"

  initialize: (options = {}) ->
    @currentIndicator  = options.currentIndicator
    @indicators = new Backbone.Collections.IndicatorCollection()
    @indicators.fetch(
      success: @render
    )

  render: =>
    $('body').addClass('stop-scrolling')

    @$el.html(@template(
      thisView: @
      currentIndicator: @currentIndicator
      indicators: @indicators.groupByType()
    ))
    @attachSubViews()

    @bindToIndicatorSelection()

    return @

  bindToIndicatorSelection: ->
    for key, subView of @subViews
      @listenTo(subView, 'indicatorSelected', @triggerIndicatorSelected)

  triggerIndicatorSelected: (indicator) =>
    @trigger('indicatorSelected', indicator)

  onClose: ->
    $('body').removeClass('stop-scrolling')

    @stopListening()
    @closeSubViews()

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

class Backbone.Views.IndicatorSelectorView extends Backbone.Diorama.NestingView
  template: Handlebars.templates['indicator_selector.hbs']
  className: 'modal indicator-selector'

  events:
    "click .close": "close"

  initialize: (options = {}) ->
    @currentIndicator  = options.currentIndicator
    @indicators = new Backbone.Collections.IndicatorCollection([], withData: true)
    @indicators.fetch(
      success: @render
    )

  render: =>
    $('body').addClass('stop-scrolling')

    @$el.html(@template(
      thisView: @
      currentIndicator: @currentIndicator
      indicators: @indicators.groupByType()
    ))
    @attachSubViews()

    @bindToIndicatorSelection()

    return @

  bindToIndicatorSelection: ->
    for key, subView of @subViews
      @listenTo(subView, 'indicatorSelected', @triggerIndicatorSelected)

  triggerIndicatorSelected: (indicator) =>
    @trigger('indicatorSelected', indicator)

  onClose: ->
    $('body').removeClass('stop-scrolling')

    @stopListening()
    @closeSubViews()

Make the indicator selector only show indicators with data


{div} = React.DOM

@FeedView = React.createClass
  displayName: 'FeedView'

  componentWillMount: ->
    Screensmart.store.dispatch Screensmart.Actions.updateResponse()

  render: ->
    div
      className: 'feed'
      @props.children.map (child) ->
        div
          key: child.key
          className: 'item'
          child

{div} = React.DOM

@FeedView = React.createClass
  displayName: 'FeedView'

  render: ->
    div
      className: 'feed'
      @props.children.map (child) ->
        div
          key: child.key
          className: 'item'
          child

Fix response loading twice on fill_out start


class Lanes.Components.FieldSet extends Lanes.React.Component

    getDefaultProps: ->
        speed: 0.4

    propTypes:
        title: React.PropTypes.string.isRequired
        speed: React.PropTypes.number
        collapsed: React.PropTypes.bool

    getInitialState: ->
        state = {
            expanded: !@props.collapsed,
            icon: if @props.collapsed then 'plus' else 'minus'
        }
        state.height = 30 if @props.collapsed
        state

    getClientHeight: ->
        _.max(
            _.pluck(@refs.body.getDOMNode().children, 'clientHeight')
        ) + 45

    toggleExpanded: ->
        if @state.expanded
            if ! @state.hasExpanded
                @setState( hasExpanded: true, height: @getClientHeight() )
                _.defer @toggleExpanded
                return
            @setState expanded: false, height: 30
        else
            @setState expanded: true, height: @getClientHeight()

        _.delay( =>
            if @isMounted()
                @setState(icon: if @state.expanded then 'minus' else 'plus')
        , @props.speed * 1000)

    render: ->
        colProps = _.omit(@props, 'name')
        <BS.Col {...colProps}>
            <fieldset className={
                _.classnames("collapsible", @props.className, @state.icon
                {expanded: @state.expanded, collapsed: !@state.expanded})
            }
            style={
                maxHeight: @state.height
                transition: "max-height #{@props.speed}s ease-in-out";
            }>
                <legend onClick={@toggleExpanded}>
                    {@props.title}
                </legend>
                <div ref="body" className="fieldset-fields">
                    {@props.children}
                </div>
            </fieldset>
        </BS.Col>

class Lanes.Components.FieldSet extends Lanes.React.Component

    getDefaultProps: ->
        expanded: true

    propTypes:
        title: React.PropTypes.string.isRequired
        expanded: React.PropTypes.bool

    getInitialState: ->
        expanded: @props.expanded

    componentWillReceiveProps: (nextProps) ->
        @setState(expanded: nextProps.expanded) if nextProps.expanded?

    toggleExpanded: ->
        @setState(expanded: not @state.expanded)

    render: ->
        colProps = _.omit(@props, 'name')
        <BS.Col {...colProps}>
            <fieldset className={
                _.classnames("collapsible", @props.className, @state.icon
                    {expanded: @state.expanded, collapsed: !@state.expanded})
            }>
                <legend onClick={@toggleExpanded}>
                    {@props.title}
                </legend>
                <BS.Collapse in={@state.expanded}>
                    <div ref="body" className="fieldset-fields">
                        {@props.children}
                    </div>
                </BS.Collapse>
            </fieldset>
        </BS.Col>

Use Collapse component vs own logic

Use Collapse component vs own logic


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

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

  class FakeEditor
    constructor: (@minimap) ->

    getActiveMinimap: -> @minimap.getActiveMinimap()

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

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

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

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

    getActiveEditor: -> @fakeEditor

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

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

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

  class FakeEditor
    constructor: (@minimap) ->

    getActiveMinimap: -> @minimap.getActiveMinimap()

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

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

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

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

    getActiveEditor: -> @fakeEditor

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

:bug: Fix broken plugin since highlight-selected update

Fixes #5


_ = require 'underscore'
Backbone = require 'backbone'

router = new Backbone.Router
href = null

module.exports = ($el) ->
  $el.on 'click', 'a[href]', onClick
  # Make sure history is started to use our internal router
  Backbone.history.start(pushState: true) unless Backbone.History.started

onClick = (e) ->
  e.preventDefault()
  _.defer =>
    href = $(this).attr('href')
    return unless href?.length
    # Don't iframe if it might be an offsite link
    return if href.indexOf('http') > -1
    setIframe()
    router.route location.pathname.replace(/^\//, ''), removeIframe
    router.navigate href

setIframe = ->
  $('#iframe-popover').html "<iframe src='#{href}'>"
  $('body').addClass('body-iframe-popover')

removeIframe = ->
  $('#iframe-popover').html ''
  $('body').removeClass('body-iframe-popover')

# To keep our router state from getting out of wack we'll do a full redirect after the first page
# in the iframe. We trigger this parent event inside the main_layout/templates/head.jade to make
# sure our route changes right away.
addEventListener? 'message', (e) ->
  return unless e.data.href
  return if e.data.href is @location.href
  $('body').remove()
  @location = e.data.href

_ = require 'underscore'
Backbone = require 'backbone'

router = new Backbone.Router
href = null

module.exports = ($el) ->
  $el.on 'click', 'a[href]', onClick
  # Make sure history is started to use our internal router
  Backbone.history.start(pushState: true) unless Backbone.History.started

onClick = (e) ->
  return if e.metaKey or e.ctrlKey

  e.preventDefault()
  _.defer =>
    href = $(this).attr('href')
    return unless href?.length
    # Don't iframe if it might be an offsite link
    return if href.indexOf('http') > -1
    setIframe()
    router.route location.pathname.replace(/^\//, ''), removeIframe
    router.navigate href

setIframe = ->
  $('#iframe-popover').html "<iframe src='#{href}'>"
  $('body').addClass('body-iframe-popover')

removeIframe = ->
  $('#iframe-popover').html ''
  $('body').removeClass('body-iframe-popover')

# To keep our router state from getting out of wack we'll do a full redirect after the first page
# in the iframe. We trigger this parent event inside the main_layout/templates/head.jade to make
# sure our route changes right away.
addEventListener? 'message', (e) ->
  return unless e.data.href
  return if e.data.href is @location.href
  $('body').remove()
  @location = e.data.href

Allow cmd and ctrl clicks to open links in new tabs


{CompositeDisposable} = require 'event-kit'
[Minimap, MinimapElement] = []

module.exports =
class V4Main
  @includeInto: (base) ->
    for k,v of @prototype
      base::[k] = v

  activateV4: ->
    @editorsMinimaps = {}
    @subscriptions = new CompositeDisposable
    MinimapElement ?= require './minimap-element'

    MinimapElement.registerViewProvider()

  deactivate: ->
    minimap.destroy() for id,minimap of @editorsMinimaps
    @subscriptions.dispose()
    @editorsMinimaps = {}
    @toggled = false

  toggle: ->
    if @toggled
      @toggled = false
      @subscriptions.dispose()
    else
      @toggled = true
      @initSubscriptions()

  minimapForEditor: (editor) -> @editorsMinimaps[editor.id]

  initSubscriptions: ->
    Minimap ?= require './minimap'

    @subscriptions.add atom.workspace.observeTextEditors (textEditor) =>
      minimap = new Minimap({textEditor})
      @editorsMinimaps[textEditor.id] = minimap

      editorElement = atom.views.getView(textEditor)
      minimapElement = atom.views.getView(minimap)

      minimapElement.attach()

{CompositeDisposable} = require 'event-kit'
[Minimap, MinimapElement] = []

module.exports =
class V4Main
  @includeInto: (base) ->
    for k,v of @prototype
      base::[k] = v

  activateV4: ->
    @editorsMinimaps = {}
    @subscriptions = new CompositeDisposable
    MinimapElement ?= require './minimap-element'

    MinimapElement.registerViewProvider()

  deactivate: ->
    minimap.destroy() for id,minimap of @editorsMinimaps
    @subscriptions.dispose()
    @editorsMinimaps = {}
    @toggled = false

  toggle: ->
    if @toggled
      @toggled = false
      @subscriptions.dispose()
    else
      @toggled = true
      @initSubscriptions()

  minimapForEditor: (editor) -> @editorsMinimaps[editor.id]

  observeMinimaps: (iterator) ->
    return unless iterator?
    iterator({view: minimap}) for id,minimap of @editorsMinimaps
    createdCallback = (minimap) -> iterator(minimap)
    disposable = @onDidCreateMinimap(createdCallback)
    disposable.off = ->
      deprecate('Use Disposable::dispose instead')
      disposable.dispose()
    disposable

  initSubscriptions: ->
    Minimap ?= require './minimap'

    @subscriptions.add atom.workspace.observeTextEditors (textEditor) =>
      minimap = new Minimap({textEditor})
      @editorsMinimaps[textEditor.id] = minimap

      editorElement = atom.views.getView(textEditor)
      minimapElement = atom.views.getView(minimap)

      @emitter.emit('did-create-minimap')

      minimapElement.attach()

Implement minimap creation observer method for v4


Template.displayIcon.userIconUrl = ->
  # TODO: We should specify default URL to the image of an avatar which is generated from name initials
  "https://secure.gravatar.com/avatar/#{ Meteor.person()?.gravatarHash }?s=25"

Template._loginButtonsLoggedInDropdownActions.personSlug = ->
  Meteor.person()?.slug

# To close login buttons dialog box when clicking or focusing somewhere outside
$(document).click (e) ->
  Accounts._loginButtonsSession.closeDropdown() unless e.originalEvent.dialogBoxEvent
  return # Make sure CoffeeScript does not return anything

$(document).focus (e) ->
  Accounts._loginButtonsSession.closeDropdown() unless e.originalEvent.dialogBoxEvent
  return # Make sure CoffeeScript does not return anything

# But if clicked inside, we mark the event so that dialog box is not closed
Template._loginButtons.events
  'click #login-buttons': (e, template) ->
    e.dialogBoxEvent = true
    return # Make sure CoffeeScript does not return anything

  'focus #login-buttons': (e, template) ->
    e.dialogBoxEvent = true
    return # Make sure CoffeeScript does not return anything

Template.displayIcon.userIconUrl = ->
  # TODO: We should specify default URL to the image of an avatar which is generated from name initials
  "https://secure.gravatar.com/avatar/#{ Meteor.person()?.gravatarHash }?s=25"

Template._loginButtonsLoggedInDropdownActions.personSlug = ->
  Meteor.person()?.slug

# To close login buttons dialog box when clicking or focusing somewhere outside
$(document).click (e) ->
  Accounts._loginButtonsSession.closeDropdown() unless e.originalEvent?.dialogBoxEvent
  return # Make sure CoffeeScript does not return anything

$(document).focus (e) ->
  Accounts._loginButtonsSession.closeDropdown() unless e.originalEvent?.dialogBoxEvent
  return # Make sure CoffeeScript does not return anything

# But if clicked inside, we mark the event so that dialog box is not closed
Template._loginButtons.events
  'click #login-buttons': (e, template) ->
    e.dialogBoxEvent = true
    return # Make sure CoffeeScript does not return anything

  'focus #login-buttons': (e, template) ->
    e.dialogBoxEvent = true
    return # Make sure CoffeeScript does not return anything

Check if originalEvent is defined

Check if originalEvent is defined


_ = require 'underscore-plus'
{View} = require 'atom-space-pen-views'

module.exports =
class IncompatiblePackagesStatusView extends View
  @content: ->
    @div class: 'incompatible-packages-status inline-block text text-error', =>
      @span class: 'icon icon-bug'
      @span outlet: 'countLabel', class: 'incompatible-packages-status'

  initialize: (statusBar, incompatibleCount) ->
    @countLabel.text(incompatibleCount)
    @tooltipSubscription = atom.tooltips.add(@element, title: _.pluralize(incompatibleCount, 'incompatible package'))
    statusBar.appendRight(this)

    @on 'click', =>
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'incompatible-packages:view')
      @destroy()

  destroy: ->
    @tooltipSubscription.dispose()
    @remove()

_ = require 'underscore-plus'
{View} = require 'atom-space-pen-views'

module.exports =
class IncompatiblePackagesStatusView extends View
  @content: ->
    @div class: 'incompatible-packages-status inline-block text text-error', =>
      @span class: 'icon icon-bug'
      @span outlet: 'countLabel', class: 'incompatible-packages-status'

  initialize: (statusBar, incompatibleCount) ->
    @countLabel.text(incompatibleCount)
    @tooltipSubscription = atom.tooltips.add(@element, title: _.pluralize(incompatibleCount, 'incompatible package'))
    statusBar.addRightTile(item: this)

    @on 'click', =>
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'incompatible-packages:view')
      @destroy()

  destroy: ->
    @tooltipSubscription.dispose()
    @remove()

Use new status bar tile API

Use new status bar tile API


# modules
Sequelize = require 'sequelize'
db = require './db'
Team = require './team'

# custom validation constraints
checkUnique = (value, next) ->
    User.find
        where: $or:
                nickname: value
                email: value
    .then (user) ->
        if user then return next 'Ce nom d\'utilisateur ou cet e-mail ont déjà été choisis.'
        return next()
    .catch (err) ->
        return next err

checkNotNull = (value, next) ->
    if value.length == 0
        throw new Error 'Valeur nulle non autorisée'
    else
        next()

notNull:
    msg: "Valeur nulle"

# def model
User = db.orm.define 'User',
    id:
        type: Sequelize.INTEGER
        primaryKey: true
        autoIncrement: true
    nickname:
        type: Sequelize.STRING 25
        unique: true
        allowNull: false
        validate:
            len: [3, 25]
            isUnique: checkUnique
            isNotNull: checkNotNull
    email:
        type: Sequelize.STRING 25
        unique: true
        allowNull: false
        validate:
            len: [3, 25]
            isUnique: checkUnique
            isNotNull: checkNotNull
    password:
        type: Sequelize.STRING
        allowNull: false
        validate:
            isNotNull: checkNotNull
            len: [6,100]

# def model assocs
User.belongsTo Team,
    foreignKey: 'teamId'
    as: 'team'

#export
module.exports = User

# modules
Sequelize = require 'sequelize'
db = require './db'
Team = require './team'

# custom validation constraints
checkUnique = (value, next) ->
    User.find
        where: $or:
                nickname: value
                email: value
    .then (user) ->
        if user then return next 'Ce nom d\'utilisateur ou cet e-mail ont déjà été choisis.'
        return next()
    .catch (err) ->
        return next err

checkNotNull = (value, next) ->
    if value.length == 0
        throw new Error 'Valeur nulle non autorisée'
    else
        next()

# def model
User = db.orm.define 'User',
    id:
        type: Sequelize.INTEGER
        primaryKey: true
        autoIncrement: true
    nickname:
        type: Sequelize.STRING 25
        unique: true
        allowNull: false
        validate:
            len: [3, 25]
            isUnique: checkUnique
            isNotNull: checkNotNull
    email:
        type: Sequelize.STRING 25
        unique: true
        allowNull: false
        validate:
            len: [3, 25]
            isUnique: checkUnique
            isNotNull: checkNotNull
    password:
        type: Sequelize.STRING
        allowNull: false
        validate:
            isNotNull: checkNotNull

# def model assocs
User.belongsTo Team,
    foreignKey: 'teamId'
    as: 'team'

#export
module.exports = User

Delete length validation for password

Delete length validation for password


label = (fontSize, options = {}) ->

  options.font = _.extend {}, options.font or {},
    fontSize: fontSize

  _.extend {}, options,
    height: Ti.UI.SIZE
    width: Ti.UI.FILL
    color: '#333'
    bottom: options.font.fontSize * 0.5 # Similar to bottom margin of 0.5em

heading = (fontSize) ->
  label fontSize,
    font:
      fontWeight: 'bold'

module.exports =

  h1: heading 20

  h2: heading 18

  h3: heading 16

  h4: heading 14

  h5: heading 12

  h6: heading 10

  p: label 14

  combined:

    view:
      height: 0
      #layout: 'vertical'

    primary:
      top: 0
      height: Ti.UI.SIZE
      width: Ti.UI.FILL
      color: '#333'
      font:
        fontSize: 15

    meta:
      bottom: 0
      height: Ti.UI.SIZE
      width: Ti.UI.FILL
      color: '#999'
      font:
        fontSize: 11

label = (fontSize, options = {}) ->

  options.font = _.extend {}, options.font or {},
    fontSize: fontSize

  _.extend {}, options,
    height: Ti.UI.SIZE
    width: Ti.UI.FILL
    color: '#333'
    bottom: options.font.fontSize * 0.5 # Similar to bottom margin of 0.5em

heading = (fontSize) ->
  label fontSize,
    font:
      fontWeight: 'bold'

module.exports =

  h1: heading 20

  h2: heading 18

  h3: heading 16

  h4: heading 14

  h5: heading 12

  h6: heading 10

  p: label 14

  combined:

    view:
      height: Ti.UI.SIZE
      layout: 'vertical'

    primary:
      top: 0
      height: Ti.UI.SIZE
      width: Ti.UI.FILL
      color: '#333'
      font:
        fontSize: 15

    meta:
      bottom: 0
      height: Ti.UI.SIZE
      width: Ti.UI.FILL
      color: '#999'
      font:
        fontSize: 11

Set label height to Ti.UI.SIZE

Set label height to Ti.UI.SIZE


# handle background tiles
backgroundTile = undefined
tileImg = new Image()
tileImg.onload = ->
  backgroundTile = cq().context.createPattern(tileImg,'repeat')
tileImg.src = '/img/tile.png'
drawBackgroundTiles = (ctx) ->
  if backgroundTile?
    ctx
    .rect(0,0, ctx.canvas.width,ctx.canvas.height)
    .fillStyle(backgroundTile)
    .fill()

reset = ->
  imageSelector =
    color : '#de683c'
    zoom  : 1
  imageSelection =
    color: '#29a4d3'

  imageMouseCoords =
    x: imageCanvas.innerWidth/2
    y: imageCanvas.innerHeight/2
  zoomedMouseCoords =
    x: 0
    y: 0

# listen for scroll events
imageCanvas.on 'mousewheel', (e) ->
  e.preventDefault()
  if e.deltaY
    imageSelector.zoom += zoomSpeed*(if e.deltaY < 1 then 1 else -1)
    if imageSelector.zoom < 0.1 then imageSelector.zoom = 0.1
    if imageSelector.zoom > 1 then imageSelector.zoom = 1

# load new image on file select
fileSelect.on 'change', (e) ->
  selectedFile = e.target.files[0]
  reader = new FileReader()
  reader.onload = (e) ->
    scope.$apply ->
      scope.imagedata = e.target.result
  reader.readAsDataURL selectedFile

# handle background tiles
backgroundTile = undefined
tileImg = new Image()
tileImg.onload = ->
  backgroundTile = cq().context.createPattern(tileImg,'repeat')
tileImg.src = './img/tile.png'
drawBackgroundTiles = (ctx) ->
  if backgroundTile?
    ctx
    .rect(0,0, ctx.canvas.width,ctx.canvas.height)
    .fillStyle(backgroundTile)
    .fill()

reset = ->
  imageSelector =
    color : '#de683c'
    zoom  : 1
  imageSelection =
    color: '#29a4d3'

  imageMouseCoords =
    x: imageCanvas.innerWidth/2
    y: imageCanvas.innerHeight/2
  zoomedMouseCoords =
    x: 0
    y: 0

# listen for scroll events
imageCanvas.on 'mousewheel', (e) ->
  e.preventDefault()
  if e.deltaY
    imageSelector.zoom += zoomSpeed*(if e.deltaY < 1 then 1 else -1)
    if imageSelector.zoom < 0.1 then imageSelector.zoom = 0.1
    if imageSelector.zoom > 1 then imageSelector.zoom = 1

# load new image on file select
fileSelect.on 'change', (e) ->
  selectedFile = e.target.files[0]
  reader = new FileReader()
  reader.onload = (e) ->
    scope.$apply ->
      scope.imagedata = e.target.result
  reader.readAsDataURL selectedFile

Make tile path work in GH

Make tile path work in GH


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

  return class LegacyModal extends BaseView
    template: template

    events:
      'submit': 'onSubmit'

    onSubmit: (e) ->
      e.preventDefault()

      if $(e.currentTarget).find('.checkbox input').is(':checked')
        document.cookie = "legacy; max-age=#{60*60*24*30*365*4}; path=/;"

      location.href = @$el.children().data('href') # HACK to pass href value to modal view

define (require) ->
  $ = require('jquery')
  BaseView = require('cs!helpers/backbone/views/base')
  template = require('hbs!./legacy-template')
  require('less!./legacy')
  require('bootstrapTransition')
  require('bootstrapModal')

  return class LegacyModal extends BaseView
    template: template

    events:
      'submit': 'onSubmit'

    onSubmit: (e) ->
      e.preventDefault()

      if $(e.currentTarget).find('.checkbox input').is(':checked')
        document.cookie = "legacy; max-age=#{60*60*24*30*365*4}; path=/;"

      location.href = @$el.children().data('href') # HACK to pass href value to modal view

Add bootstrap modal and transition dependencies


class NavigationMachineItem extends JView

  {Running, Stopped} = Machine.State

  stateClasses  = ''
  stateClasses += "#{state.toLowerCase()} " for state in Object.keys Machine.State

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

    machine            = data
    @alias             = machine.label
    path               = KD.utils.groupifyLink "/IDE/VM/#{machine.uid}"

    options.tagName    = 'a'
    options.cssClass   = "vm #{machine.status.state.toLowerCase()} #{machine.provider}"
    options.attributes =
      href             : path
      title            : "Open IDE for #{@alias}"

    super options, data

    @machine = @getData()
    @progress = new KDProgressBarView
      cssClass : 'hidden'
      # initial  : Math.floor Math.random() * 100

    { computeController } = KD.singletons

    computeController.on "public-#{@machine._id}", (event)=>

      {percentage, status} = event

      if percentage?

        if @progress.bar

          @progress.show()
          @progress.updateBar percentage

          if percentage is 100
            KD.utils.wait 1000, @progress.bound 'hide'

      else

        @progress.hide()

      if status?

        @unsetClass stateClasses
        @setClass status.toLowerCase()

  pistachio:->

    """

#{@alias}
    {{> @progress}}
    """

class NavigationMachineItem extends JView

  {Running, Stopped} = Machine.State

  stateClasses  = ''
  stateClasses += "#{state.toLowerCase()} " for state in Object.keys Machine.State

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

    machine            = data
    @alias             = machine.getName()
    path               = KD.utils.groupifyLink "/IDE/VM/#{machine.uid}"

    options.tagName    = 'a'
    options.cssClass   = "vm #{machine.status.state.toLowerCase()} #{machine.provider}"
    options.attributes =
      href             : path
      title            : "Open IDE for #{@alias}"

    super options, data

    @machine = @getData()
    @progress = new KDProgressBarView
      cssClass : 'hidden'
      # initial  : Math.floor Math.random() * 100

    { computeController } = KD.singletons

    computeController.on "public-#{@machine._id}", (event)=>

      {percentage, status} = event

      if percentage?

        if @progress.bar

          @progress.show()
          @progress.updateBar percentage

          if percentage is 100
            KD.utils.wait 1000, @progress.bound 'hide'

      else

        @progress.hide()

      if status?

        @unsetClass stateClasses
        @setClass status.toLowerCase()

  pistachio:->

    """

#{@alias}
    {{> @progress}}
    """

NavigationMachineItem: Use `machine.getName()` instead of `machine.label`


module.exports = (robot) ->
  names = ['Dana', 'Freia', 'Jhishan', 'Kyle', 'Brenton', 'Terri', 'Abhi', 'Drew']
  robot.hear /Resume queen, who is next\?/i, (res) ->
    res.send res.random names

module.exports = (robot) ->
  names = ['Dana', 'Freia', 'Jhishan', 'Kyle', 'Brenton', 'Terri', 'Abhi', 'Drew']
  names = ['@danagilliann', '@flobot', '@jhishan', '@kwhughes', '@brentdur', '@terriburns', '@abhiagarwal', '@nydrewreynolds']
  robot.hear /Resume queen, who is next\?/i, (res) ->
    res.send res.random names

Change first names to slack handles

Change first names to slack handles


class window.ArgumentVotes extends Backbone.Model
  defaults:
    believes: 0
    disbelieves: 0

  isNew: -> @_argument.isNew()

  initialize: (attributes, options) ->
    @_argument = options.argument

  url: ->
    @_argument.url() + '/opinion'

  setCurrentUserOpinion: (newOpinion) ->
    previousOpinion = @get('current_user_opinion')
    @set previousOpinion, @get(previousOpinion)-1 if previousOpinion != 'no_vote'
    @set newOpinion, @get(newOpinion)+1 if newOpinion != 'no_vote'
    @set 'current_user_opinion', newOpinion

  saveCurrentUserOpinion: (opinion_type) ->
    @previous_opinion_type = @get('current_user_opinion')

    @setCurrentUserOpinion opinion_type
    @save {},
      success: =>
        mp_track "Argument: Vote", url: @url(), opinion: opinion_type
      error: =>
        @setCurrentUserOpinion @previous_opinion_type

  relevance: -> @get('believes') - @get('disbelieves')

class window.ArgumentVotes extends Backbone.Model
  defaults:
    believes: 0
    disbelieves: 0

  isNew: -> @_argument.isNew()

  initialize: (attributes, options) ->
    @_argument = options.argument

    @_argument.on 'change:argument_votes', =>
      @set @_argument.get('argument_votes')

  url: ->
    @_argument.url() + '/opinion'

  setCurrentUserOpinion: (newOpinion) ->
    previousOpinion = @get('current_user_opinion')
    @set previousOpinion, @get(previousOpinion)-1 if previousOpinion != 'no_vote'
    @set newOpinion, @get(newOpinion)+1 if newOpinion != 'no_vote'
    @set 'current_user_opinion', newOpinion

  saveCurrentUserOpinion: (opinion_type) ->
    @previous_opinion_type = @get('current_user_opinion')

    @setCurrentUserOpinion opinion_type
    @save {},
      success: =>
        mp_track "Argument: Vote", url: @url(), opinion: opinion_type
      error: =>
        @setCurrentUserOpinion @previous_opinion_type

  relevance: -> @get('believes') - @get('disbelieves')

Update ArgumentVotes when the argument changes


Settings = require "settings-sharelatex"
logger = require "logger-sharelatex"
logger.initialize("track-changes")

HttpController = require "./app/js/HttpController"
express = require "express"
app = express()

app.use express.logger()

app.post "/doc/:doc_id/flush", HttpController.flushUpdatesWithLock

app.use (error, req, res, next) ->
	logger.error err: error, "an internal error occured"
	res.send 500

port = Settings.internal?.trackchanges?.port or 3014
host = Settings.internal?.trackchanges?.host or "localhost"
app.listen port, host, (error) ->
	if error?
		logger.error err: error, "could not start track-changes server"
	else
		logger.log "track changes api listening on http://#{host}:#{port}"

Settings = require "settings-sharelatex"
logger = require "logger-sharelatex"
logger.initialize("track-changes")

HttpController = require "./app/js/HttpController"
express = require "express"
app = express()

app.use express.logger()

app.post "/doc/:doc_id/flush", HttpController.flushUpdatesWithLock

app.get "/status", (req, res, next) ->
	res.send "track-changes is alive"

app.use (error, req, res, next) ->
	logger.error err: error, "an internal error occured"
	res.send 500

port = Settings.internal?.trackchanges?.port or 3014
host = Settings.internal?.trackchanges?.host or "localhost"
app.listen port, host, (error) ->
	if error?
		logger.error err: error, "could not start track-changes server"
	else
		logger.log "track changes api listening on http://#{host}:#{port}"

Add in /status end point

Add in /status end point


define [
  'jquery'
  'underscore'
  'backbone'
  'marionette'
  'cs!views/workspace/content/aloha-edit'
  'hbs!templates/workspace/content/content-edit'
], ($, _, Backbone, Marionette, AlohaEditView, contentEditTemplate) ->

  # Edit Content Body
  # -------
  return AlohaEditView.extend
    # **NOTE:** This template is not wrapped in an element
    template: contentEditTemplate
    modelKey: 'body'

define [
  'jquery'
  'underscore'
  'backbone'
  'marionette'
  'cs!views/workspace/content/aloha-edit'
  'hbs!templates/workspace/content/content-edit'
  'bootstrapPopover'
], ($, _, Backbone, Marionette, AlohaEditView, contentEditTemplate) ->

  # Edit Content Body
  # -------
  return AlohaEditView.extend
    # **NOTE:** This template is not wrapped in an element
    template: contentEditTemplate
    modelKey: 'body'

Enable popovers in content editor

Enable popovers in content editor


App.Followable =

  initialize: ->
    $('.followable-content a[data-toggle]').on 'click', (event) ->
      event.preventDefault()

  update: (followable_id, button) ->
    $("#" + followable_id + " .js-follow").html(button)
    initialize_modules()

App.Followable =

  initialize: ->
    $('.followable-content a[data-toggle]').on 'click', (event) ->
      event.preventDefault()

  update: (followable_id, button) ->
    $("#" + followable_id + " .js-follow").html(button)
    # Temporary line. Waiting for issue resolution: https://github.com/consul/consul/issues/1736
    initialize_modules()

Add comment to temporary bugfix.

Add comment to temporary bugfix.


isActive = (type, inverse = false) ->
  name = 'is'
  name = name + 'Not' if inverse
  name = name + _.capitalize type

  (view) ->
    unless view instanceof Spacebars.kw
      throw new Error "#{name} options must be key value pair such " +
        "as {{#{name} regex='route/path'}}. You passed: " +
        "#{JSON.stringify view}"

    pattern =
      className: Match.Optional String
      regex: String

    check view.hash, pattern

    route = Router.current().route

    return false unless route

    {className, regex} = view.hash

    className ?= if inverse then 'disabled' else 'active'

    isPath = true if type is 'path'

    test = testExp route, regex, isPath

    test = not test if inverse

    if test then className else false

testExp = (route, exp, isPath = false) ->
  if isPath
    pattern = route.path()

  else
    pattern = route.getName()

  re = new RegExp exp, 'i'

  re.test pattern

helpers =
  isActiveRoute: isActive 'route'

  isActivePath: isActive 'path'

  isNotActiveRoute: isActive 'route', true

  isNotActivePath: isActive 'path', true

Template.registerHelper name, func for own name, func of helpers

isActive = (type, inverse = false) ->
  name = 'is'
  name = name + 'Not' if inverse
  name = name + 'Active' + _.capitalize type

  (view) ->
    unless view instanceof Spacebars.kw
      throw new Error "#{name} options must be key value pair such " +
        "as {{#{name} regex='route/path'}}. You passed: " +
        "#{JSON.stringify view}"

    pattern =
      className: Match.Optional String
      regex: String

    check view.hash, pattern

    route = Router.current().route

    return false unless route

    {className, regex} = view.hash

    className ?= if inverse then 'disabled' else 'active'

    isPath = true if type is 'path'

    test = testExp route, regex, isPath

    test = not test if inverse

    if test then className else false

testExp = (route, exp, isPath = false) ->
  if isPath
    pattern = route.path()

  else
    pattern = route.getName()

  re = new RegExp exp, 'i'

  re.test pattern

helpers =
  isActiveRoute: isActive 'route'

  isActivePath: isActive 'path'

  isNotActiveRoute: isActive 'route', true

  isNotActivePath: isActive 'path', true

Template.registerHelper name, func for own name, func of helpers

Fix name of helper in error message

Fix name of helper in error message


# check for subscriptions to be ready
subsReady = (subs...) ->
  return FlowRouter.subsReady() if subs.length is 1
  subs = subs.slice(0, subs.length - 1)
  _.reduce subs, (memo, sub) ->
    memo and FlowRouter.subsReady(sub)
  , true

# return path
pathFor = (path, view) ->
  throw new Error('no path defined') unless path
  if path.hash?.route?
    view = path
    path = view.hash.route
    delete view.hash.route
  query = if view.hash.query then FlowRouter._qs.parse(view.hash.query) else {}
  FlowRouter.path(path, view.hash, query)

# return absolute url
urlFor = (path, view) ->
  relativePath = pathFor(path, view)
  Meteor.absoluteUrl(relativePath.substr(1))

# get parameter
param = (name) ->
  FlowRouter.getParam(name);

# get query parameter
queryParam = (key) ->
  FlowRouter.getQueryParam(key);

# get current route name
currentRouteName = () ->
  FlowRouter.getRouteName()

# deprecated
isSubReady = (sub) ->
  return FlowRouter.subsReady(sub) if sub
  return FlowRouter.subsReady()

helpers =
  subsReady: subsReady
  pathFor: pathFor
  urlFor: urlFor
  param: param
  queryParam: queryParam
  currentRouteName: currentRouteName
  isSubReady: isSubReady

Template.registerHelper name, func for own name, func of helpers

# check for subscriptions to be ready
subsReady = (subs...) ->
  return FlowRouter.subsReady() if subs.length is 1
  subs = subs.slice(0, subs.length - 1)
  _.reduce subs, (memo, sub) ->
    memo and FlowRouter.subsReady(sub)
  , true

# return path
pathFor = (path, view) ->
  throw new Error('no path defined') unless path
  if path.hash?.route?
    view = path
    path = view.hash.route
    delete view.hash.route
  query = if view.hash.query then FlowRouter._qs.parse(view.hash.query) else {}
  hashBang = if view.hash.hash then view.hash.hash else ''
  FlowRouter.path(path, view.hash, query) + hashBang

# return absolute url
urlFor = (path, view) ->
  relativePath = pathFor(path, view)
  Meteor.absoluteUrl(relativePath.substr(1))

# get parameter
param = (name) ->
  FlowRouter.getParam(name);

# get query parameter
queryParam = (key) ->
  FlowRouter.getQueryParam(key);

# get current route name
currentRouteName = () ->
  FlowRouter.getRouteName()

# deprecated
isSubReady = (sub) ->
  return FlowRouter.subsReady(sub) if sub
  return FlowRouter.subsReady()

helpers =
  subsReady: subsReady
  pathFor: pathFor
  urlFor: urlFor
  param: param
  queryParam: queryParam
  currentRouteName: currentRouteName
  isSubReady: isSubReady

Template.registerHelper name, func for own name, func of helpers

Add hashbang option to pathFor

Add hashbang option to pathFor


# reference "_namespace.coffee"
# reference "PartViewModel.coffee"

{ PartViewModel } = @witness.ui

@witness.ui.ScenarioViewModel = class ScenarioViewModel

	constructor: (@scenario) ->
		{ @path, @url } = @scenario.parentSpecification.parentFile
		@parts = (new PartViewModel part for part in [].concat @scenario.given, @scenario.when, @scenario.then)
		@errors = ko.observableArray []

		@scenario.on.failed.addHandler (errors) =>
			if jQuery.isArray errors
				for error in errors when not error.stack or error.fromAssertion
					error.stack = ""
				@errors errors
			else
				error = errors
				if not error.stack or error.fromAssertion
					error.stack = ""
				@errors [ error ]

	templateId: "scenario"

# reference "_namespace.coffee"
# reference "PartViewModel.coffee"

{ PartViewModel } = @witness.ui

@witness.ui.ScenarioViewModel = class ScenarioViewModel

	constructor: (@scenario) ->
		{ @path, @url } = @scenario.parentSpecification.parentFile
		@parts = (new PartViewModel part for part in [].concat @scenario.given, @scenario.when, @scenario.then)
		@errors = ko.observableArray []

		@scenario.on.running.addHandler =>
			@errors.removeAll()

		@scenario.on.failed.addHandler (errors) =>
			if jQuery.isArray errors
				for error in errors when not error.stack or error.fromAssertion
					error.stack = ""
				@errors errors
			else
				error = errors
				if not error.stack or error.fromAssertion
					error.stack = ""
				@errors [ error ]

	templateId: "scenario"

Clear errors when re-running a scenario.


# Keybindings require three things to be fully defined: A selector that is
# matched against the focused element, the keystroke and the command to
# execute.
#}
# Below is a basic keybinding which registers on all platforms by applying to
# the root workspace element.

# For more detailed documentation see
# https://atom.io/docs/latest/advanced/keymaps
'.editor.agda':
  'ctrl-c ctrl-l': 'agda-mode:load'
  'ctrl-c ctrl-x ctrl-q': 'agda-mode:quit'
  'ctrl-c ctrl-x ctrl-r': 'agda-mode:restart'
  'ctrl-c ctrl-f': 'agda-mode:next-goal'
  'ctrl-c ctrl-b': 'agda-mode:previous-goal'
  'ctrl-c ctrl-space': 'agda-mode:give'
  'ctrl-c ctrl-t': 'agda-mode:goal-type'
  'ctrl-c ctrl-e': 'agda-mode:context'
  'ctrl-c ctrl-,': 'agda-mode:goal-type-and-context'
  'ctrl-c ctrl-.': 'agda-mode:goal-type-and-inferred-type'
  'ctrl-c ctrl-r': 'agda-mode:refine'
  'ctrl-c ctrl-c': 'agda-mode:case'
  'ctrl-c ctrl-a': 'agda-mode:auto'
  'ctrl-c ctrl-n': 'agda-mode:normalize'
  '\\': 'agda-mode:input-symbol'

# Keybindings require three things to be fully defined: A selector that is
# matched against the focused element, the keystroke and the command to
# execute.
#}
# Below is a basic keybinding which registers on all platforms by applying to
# the root workspace element.

# For more detailed documentation see
# https://atom.io/docs/latest/advanced/keymaps
'.atom-text-editor.agda':
  'ctrl-c ctrl-l': 'agda-mode:load'
  'ctrl-c ctrl-x ctrl-q': 'agda-mode:quit'
  'ctrl-c ctrl-x ctrl-r': 'agda-mode:restart'
  'ctrl-c ctrl-f': 'agda-mode:next-goal'
  'ctrl-c ctrl-b': 'agda-mode:previous-goal'
  'ctrl-c ctrl-space': 'agda-mode:give'
  'ctrl-c ctrl-t': 'agda-mode:goal-type'
  'ctrl-c ctrl-e': 'agda-mode:context'
  'ctrl-c ctrl-,': 'agda-mode:goal-type-and-context'
  'ctrl-c ctrl-.': 'agda-mode:goal-type-and-inferred-type'
  'ctrl-c ctrl-r': 'agda-mode:refine'
  'ctrl-c ctrl-c': 'agda-mode:case'
  'ctrl-c ctrl-a': 'agda-mode:auto'
  'ctrl-c ctrl-n': 'agda-mode:normalize'
  '\\': 'agda-mode:input-symbol'

Use the atom-text-editor tag instead of the editor class.


# Description:
#   Generate code names for things
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   hubot codename - Generates a few potential codenames for you
#
# Author:
#   Scott J Roberts - @sroberts

api_url = "https://gist.github.com"
request_url = api_url + "/sroberts/6529712/raw/1e979071f6a9e8747d2c44cf5af7c4998e068d49/wordlist"

module.exports = (robot) ->
  robot.respond /codename/i, (msg) ->
    robot.http(request_url)
      .get() (err, res, body) ->
        if res.statusCode is 200
          wordlist = body.split(",")
          msg.send """Codewords:
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          """
        else
          msg.send "Error: Couldn't access #{api_url}."

# Description:
#   Generate code names for things
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   hubot codename - Generates a few potential codenames for you
#
# Author:
#   Scott J Roberts - @sroberts

api_url = "https://gist.githubusercontent.com"
request_url = api_url + "/sroberts/6529712/raw/1e979071f6a9e8747d2c44cf5af7c4998e068d49/wordlist"

module.exports = (robot) ->
  robot.respond /codename/i, (msg) ->
    robot.http(request_url)
      .get() (err, res, body) ->
        if res.statusCode is 200
          wordlist = body.split(",")
          msg.send """Codewords:
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          - #{msg.random wordlist} #{msg.random wordlist}
          """
        else
          msg.send "Error: Couldn't access #{api_url}."

Change api_url to reflect Gist raw file URI change

https://developer.github.com/changes/2014-02-21-gist-raw-file-url-change/


Template.CalendarItem.helpers
	style: ->
		user = Meteor.user()

		styles = []

		itemStatus = user?.grade?[@gradeItem._id]
		itemStatus ?= 'pending'

		switch itemStatus
			when 'done'
				styles.push 'color: lightgray'
			when 'doing'
				styles.push 'color: orange'

		return styles.join '; '

	canMarkInterrest: ->
		user = Meteor.user()

		return not user?.grade?[@gradeItem._id]?

	intereseted: ->
		user = Meteor.user()
		key = "#{@calendarItem.shift}#{@calendarItem.day}-#{@gradeItem._id}"
		return user?.calendar?[@calendar._id]?.indexOf(key) > -1

Template.CalendarItem.events
	'click button.remove-interest': (e) ->
		Meteor.call 'updateCalendarItemInterest', @calendar._id, @gradeItem._id, @calendarItem.shift, @calendarItem.day, false

	'click button.mark-interest': (e) ->
		Meteor.call 'updateCalendarItemInterest', @calendar._id, @gradeItem._id, @calendarItem.shift, @calendarItem.day, true

Template.CalendarItem.helpers
	style: ->
		user = Meteor.user()

		styles = []

		itemStatus = user?.grade?[@gradeItem._id]
		itemStatus ?= 'pending'

		switch itemStatus
			when 'done'
				styles.push 'color: lightgray'
			when 'doing'
				styles.push 'color: orange'

		return styles.join '; '

	canMarkInterrest: ->
		user = Meteor.user()

		return user?.grade?[@gradeItem._id] isnt 'done'

	intereseted: ->
		user = Meteor.user()
		key = "#{@calendarItem.shift}#{@calendarItem.day}-#{@gradeItem._id}"
		return user?.calendar?[@calendar._id]?.indexOf(key) > -1

Template.CalendarItem.events
	'click button.remove-interest': (e) ->
		Meteor.call 'updateCalendarItemInterest', @calendar._id, @gradeItem._id, @calendarItem.shift, @calendarItem.day, false

	'click button.mark-interest': (e) ->
		Meteor.call 'updateCalendarItemInterest', @calendar._id, @gradeItem._id, @calendarItem.shift, @calendarItem.day, true

Allow to mark interrest in doing subjects


unless EditableForm
  EditableForm = $.fn.editableform.Constructor
  EditableForm.prototype.saveWithUrlHook = (value) ->
    originalUrl   = @options.url
    model         = @options.model
    nestedName    = @options.nested
    nestedId      = @options.nid
    nestedLocale  = @options.locale

    @options.url = (params) =>
      if typeof originalUrl == 'function'
        originalUrl.call(@options.scope, params)
      else if originalUrl? && @options.send != 'never'
        myName = params.name
        myValue = params.value

        # if there are no values in a list, add a blank value so Rails knows all values were removed
        if Object.prototype.toString.call(params.value) == '[object Array]' && params.value.length == 0
          params.value.push("")

        obj = {}

        if nestedName
          nested          = {}
          nested[myName]  = myValue
          nested['id']    = nestedId

          if nestedLocale
            nested['locale'] = nestedLocale

          obj[nestedName + '_attributes'] = nested
        else if myName != ''
          obj[myName] = myValue

        params[model] = obj

        delete params.name
        delete params.value
        delete params.pk

        $.ajax($.extend({
          url:      originalUrl
          data:     params
          type:     'PUT'
          dataType: 'json'
        }, @options.ajaxOptions))

    @saveWithoutUrlHook(value)

  EditableForm.prototype.saveWithoutUrlHook = EditableForm.prototype.save
  EditableForm.prototype.save = EditableForm.prototype.saveWithUrlHook

unless EditableForm
  EditableForm = $.fn.editableform.Constructor
  EditableForm.prototype.saveWithUrlHook = (value) ->
    originalUrl   = @options.url
    model         = @options.model
    nestedName    = @options.nested
    nestedId      = @options.nid
    nestedLocale  = @options.locale

    @options.url = (params) =>
      if typeof originalUrl == 'function'
        originalUrl.call(@options.scope, params)
      else if originalUrl? && @options.send != 'never'
        myName = params.name
        myValue = params.value

        # if there are no values in a list, add a blank value so Rails knows all values were removed
        if Object.prototype.toString.call(params.value) == '[object Array]' && params.value.length == 0
          params.value.push("")

        obj = {}

        if nestedName
          nested          = {}
          nested[myName]  = myValue
          nested['id']    = nestedId

          if nestedLocale
            nested['locale'] = nestedLocale

          obj[nestedName + '_attributes'] = nested
        else if myName != ''
          obj[myName] = myValue
        else
          obj = myValue

        params[model] = obj

        delete params.name
        delete params.value
        delete params.pk

        $.ajax($.extend({
          url:      originalUrl
          data:     params
          type:     'PUT'
          dataType: 'json'
        }, @options.ajaxOptions))

    @saveWithoutUrlHook(value)

  EditableForm.prototype.saveWithoutUrlHook = EditableForm.prototype.save
  EditableForm.prototype.save = EditableForm.prototype.saveWithUrlHook

Use the value as parameter when the myName field does not exist


class Subjects
  queue: []
  api: null
  query:
    sort: 'queued'
    page_size: "30"

  constructor: (@api, @project, @subject_set_id)->
    @query.workflow_id = @project?.links.workflows[0]
    @query.subject_set_id = @subject_set_id

  update: (opts) ->
    @[opt] = value for opt, value of opts
    @query.workflow_id = @project?.links.workflows[0]
    @query.subject_set_id = @subject_set_id

  current: ->
    @queue[0]

  fetch: ->
    return Promise.resolve [] unless @query.workflow_id? && @query.subject_set_id?
    @api.type('subjects')
    .get @query
    .then (newSubjects) =>
      @queue.push subject for subject in newSubjects

  flush: ->
    subject = null for subject in @queue
    @queue = []

  next: ->
    subject = @queue.shift()
    @fetch() if @queue.length < 2
    subject

module.exports = Subjects

class Subjects
  queue: []
  api: null
  current: null
  query:
    sort: 'queued'
    page_size: "30"

  constructor: (@api, @project, @subject_set_id)->
    @query.workflow_id = @project?.links.workflows[0]
    @query.subject_set_id = @subject_set_id

  update: (opts) ->
    @[opt] = value for opt, value of opts
    @query.workflow_id = @project?.links.workflows[0]
    @query.subject_set_id = @subject_set_id

  fetch: ->
    return Promise.resolve [] unless @query.workflow_id? && @query.subject_set_id?
    @api.type('subjects')
    .get @query
    .then (newSubjects) =>
      @queue.push subject for subject in newSubjects

  flush: ->
    subject = null for subject in @queue
    @current = null
    @queue = []

  next: ->
    @current = @queue.shift()
    @fetch() if @queue.length < 2
    @current

module.exports = Subjects

Fix incorrect reporting of current subject


class UIDemo.Views.TransitionView extends Backbone.View

  transitionRemoveClass: (className, $el = @$el) ->
    p = @_transitionPromise($el)
    @_delay(=> $el.removeClass className).then -> p

  transitionAddClass: (className, $el = @$el) ->
    p = @_transitionPromise($el)
    @_delay(=> $el.addClass className).then -> p

  _transitionPromise: ($el) ->
    return `when`.resolve(this) if $('body').is('.no-transitions')

    defer = `when`.defer()
    transitionEvent = @_whichTransitionEvent()
    transitionEndEventHandler = =>
      $el[0].removeEventListener(
        transitionEvent
        transitionEndEventHandler
        false
      )
      defer.resolve(this)

    $el[0].addEventListener(
      transitionEvent
      transitionEndEventHandler
      false
    )
    defer.promise

  _whichTransitionEvent: ->
    el = document.createElement('fakeelement')
    transitions =
      'transition': 'transitionend'
      'OTransition': 'oTransitionEnd'
      'MozTransition': 'transitionend'
      'WebkitTransition': 'webkitTransitionEnd'
    return event for property, event of transitions when el.style[property]?

  _delay: (code, time = 0) ->
    time = 0 if $('body').is('.no-transitions')
    defer = `when`.defer()
    setTimeout(
      -> `when(code())`.then (result) => defer.resolve(result)
      time
    )
    defer.promise

class UIDemo.Views.TransitionView extends Backbone.View

  transitionRemoveClass: (className, $el = @$el) ->
    p = @_transitionPromise($el)
    @_delay(=> $el.removeClass className).then -> p

  transitionAddClass: (className, $el = @$el) ->
    p = @_transitionPromise($el)
    @_delay(=> $el.addClass className).then -> p

  _transitionPromise: ($el) ->
    return `when`.resolve(this) if $('body').is('.no-transitions')

    defer = `when`.defer()
    transitionEvent = @_whichTransitionEvent()
    transitionEndEventHandler = =>
      $el[0].removeEventListener(
        transitionEvent
        transitionEndEventHandler
        false
      )
      defer.resolve(this)

    $el[0].addEventListener(
      transitionEvent
      transitionEndEventHandler
      false
    )
    defer.promise

  _whichTransitionEvent: ->
    el = document.createElement('fakeelement')
    transitions =
      'transition': 'transitionend'
      'OTransition': 'oTransitionEnd'
      'MozTransition': 'transitionend'
      'WebkitTransition': 'webkitTransitionEnd'
    return event for property, event of transitions when el.style[property]?

  _delay: (code, time = 0) ->
    if $('body').is('.no-transitions')
      result = code()
      `when`.resolve(result)

    defer = `when`.defer()
    setTimeout(
      -> `when(code())`.then (result) => defer.resolve(result)
      time
    )
    defer.promise

Remove asynchronous working if transitions are disabled


define ['jquery'], ($) ->

  class SelectGroup

    constructor: (@parent = null, @callback = false) ->
      @selectParent = (if @parent != null then $(@parent) else $('.js-select-group'))
      @addHandlers()

    addHandlers: ->
      @selectParent.on 'focus', '.js-select', (e) =>
        @getOverlay(e.target).addClass 'dropdown__value--selected'

      @selectParent.on 'blur', '.js-select', (e) =>
        @getOverlay(e.target).removeClass 'dropdown__value--selected'

      @selectParent.on 'keyup', '.js-select', (e) =>
        $(e.target).trigger('change')

      @selectParent.on 'change', '.js-select', (e) =>
        e.preventDefault()
        t = $(e.target).find("option:selected")
        val = t.text()
        @getOverlay(e.target).text(val)
        if @callback then @callback(e.target)

    getOverlay: (target) ->
      $(target).closest(@parent).find('.js-select-overlay')

define ['jquery'], ($) ->

  class SelectGroup

    constructor: (@parent = null, @callback = false) ->
      @selectParent = (if @parent != null then $(@parent) else $('.js-select-group'))
      @selectParent.find('.js-select').each (eltIndex) =>
        @setOverlay(@selectParent[eltIndex])
      @addHandlers()

    addHandlers: ->
      @selectParent.on 'focus', '.js-select', (e) =>
        @getOverlay(e.target).addClass 'dropdown__value--selected'

      @selectParent.on 'blur', '.js-select', (e) =>
        @getOverlay(e.target).removeClass 'dropdown__value--selected'

      @selectParent.on 'keyup', '.js-select', (e) =>
        $(e.target).trigger('change')

      @selectParent.on 'change', '.js-select', (e) =>
        e.preventDefault()
        @setOverlay(e.target)
        if @callback then @callback(e.target)

    getOverlay: (target) ->
      $(target).closest(@parent).find('.js-select-overlay')

    setOverlay: (target) ->
      t = $(target).find("option:selected")
      val = t.text()
      @getOverlay(target).text(val)

Set the value of the overlay on initialition


kd           = require 'kd'
actions      = require './actiontypes'
fetchAccount = require 'app/util/fetchAccount'

dispatch = (args...) -> kd.singletons.reactor.dispatch args...

###*
 * Load account with given id.
 *
 * @param {string} id
###
loadAccount = (id) ->

  origin = generateOrigin id

  dispatch actions.LOAD_USER_BEGIN, { id, origin }

  fetchAccount origin, (err, account) ->
    if err
      dispatch actions.LOAD_USER_FAIL, { err, id, origin }
      return

    dispatch actions.LOAD_USER_SUCCESS, { id, origin, account }

###*
 * Generate an origin object for given id.
 *
 * @param {string} id - JAccount id
 * @return {object}
 * @api private
###
generateOrigin = (id) -> { id, constructorName: 'JAccount', _id: id }

module.exports = {
  loadAccount
}

kd           = require 'kd'
actions      = require './actiontypes'
fetchAccount = require 'app/util/fetchAccount'

###*
 * Load account with given id.
 *
 * @param {string} id
###
loadAccount = (id) ->

  origin = generateOrigin id

  { reactor } = kd.singletons

  reactor.dispatch actions.LOAD_USER_BEGIN, { id, origin }

  fetchAccount origin, (err, account) ->
    if err
      reactor.dispatch actions.LOAD_USER_FAIL, { err, id, origin }
      return

    reactor.dispatch actions.LOAD_USER_SUCCESS, { id, origin, account }

###*
 * Generate an origin object for given id.
 *
 * @param {string} id - JAccount id
 * @return {object}
 * @api private
###
generateOrigin = (id) -> { id, constructorName: 'JAccount', _id: id }

module.exports = {
  loadAccount
}

Use reactor directly inside of action

app: Use reactor directly inside of action


_ = require 'underscore-plus'
{EditorView, View} = require 'atom'
MarkerView = require './marker-view'

module.exports =
class FindResultsView extends View

  @content: ->
    @div class: 'search-results'

  initialize: (@findModel) ->
    @markerViews = {}
    @subscribe @findModel, 'updated', (args...) => @markersUpdated(args...)

  attach: ->
    @getEditor()?.underlayer.append(this)

  detach: ->
    super

  beforeRemove: ->
    @destroyAllViews()

  getEditor: ->
    activeView = atom.workspaceView.getActiveView()
    if activeView?.hasClass('editor') then activeView else null

  markersUpdated: (markers) ->
    editor = @getEditor()

    if not editor?
      @destroyAllViews()
    else
      markerViewsToRemoveById = _.clone(@markerViews)
      for marker in markers
        if @markerViews[marker.id]
          delete markerViewsToRemoveById[marker.id]
        else
          markerView = new MarkerView({editor, marker})
          @append(markerView.element)
          @markerViews[marker.id] = markerView

      for id, markerView of markerViewsToRemoveById
        delete @markerViews[id]
        markerView.remove()

      editor.requestDisplayUpdate()

  destroyAllViews: ->
    @empty()
    @markerViews = {}

_ = require 'underscore-plus'
{EditorView, View} = require 'atom'
MarkerView = require './marker-view'

# TODO: remove this when marker views are in core. Hopefully soon.

module.exports =
class FindResultsView extends View

  @content: ->
    @div class: 'search-results'

  initialize: (@findModel) ->
    @markerViews = {}
    debouncedUpdate = _.debounce(@markersUpdated, 20)
    @subscribe @findModel, 'updated', =>
      if @getEditor()?.hasClass('react')
        # HACK: there are some issues with some of the react editor's components
        # being not available. We shouldnt be doing this rendering anyway.
        # Marker views are coming.
        debouncedUpdate()
      else
        @markersUpdated()

  attach: ->
    editor = @getEditor()
    if editor? and editor.underlayer?
      editor.underlayer.append(this)
    else if editor?
      subscription = @subscribe editor, 'editor:attached', =>
        subscription.off()
        editor.underlayer.append(this)

  detach: ->
    super

  beforeRemove: ->
    @destroyAllViews()

  getEditor: ->
    activeView = atom.workspaceView.getActiveView()
    if activeView?.hasClass('editor') then activeView else null

  markersUpdated: =>
    editor = @getEditor()
    markers = @findModel.markers

    if not editor?
      @destroyAllViews()
    else
      markerViewsToRemoveById = _.clone(@markerViews)
      for marker in markers
        if @markerViews[marker.id]
          delete markerViewsToRemoveById[marker.id]
        else
          markerView = new MarkerView({editor, marker})
          @append(markerView.element)
          @markerViews[marker.id] = markerView

      for id, markerView of markerViewsToRemoveById
        delete @markerViews[id]
        markerView.remove()

      editor.requestDisplayUpdate()

  destroyAllViews: ->
    @empty()
    @markerViews = {}

Fix error with FindResultsView attachment and update on react editor

When you’d split-open a file, the react editor wasn’t attached or
rendered yet. So there was no under layer, and when you’d try to request
a display update, it would call functions on objects that weren’t there.

So I hack this with a delay. This is not a pretty fix. It will all go
away when there are marker views in core.

refs #232


packages: [
  "advanced-open-file"
  "atom-alignment"
  "atom-beautify"
  "atom-transpose"
  "change-case"
  "color-picker"
  "docblockr"
  "editorconfig"
  "emmet"
  "expand-region"
  "language-apache"
  "language-applescript"
  "language-awk"
  "language-babel"
  "language-diff"
  "language-env"
  "language-gitattributes"
  "language-gitignore"
  "language-har"
  "language-hosts"
  "language-ini"
  "language-javascript-jsx"
  "language-latex"
  "language-liquid"
  "language-lisp"
  "language-pegjs"
  "language-pip"
  "language-prolog"
  "language-sca"
  "language-svg"
  "language-tcl"
  "language-viml"
  "language-x86"
  "linter"
  "linter-coffeescript"
  "linter-eslint"
  "linter-flake8"
  "linter-jsonlint"
  "linter-php"
  "linter-shellcheck"
  "linter-ui-default"
  "monokai"
  "package-sync"
  "resize-indent"
  "sort-lines"
  "ssh-config"
  "svg-preview"
  "tabs-to-spaces"
  "teletype"
]

packages: [
  "advanced-open-file"
  "atom-alignment"
  "atom-beautify"
  "atom-transpose"
  "change-case"
  "color-picker"
  "docblockr"
  "editorconfig"
  "emmet"
  "expand-region"
  "git-blame"
  "language-apache"
  "language-applescript"
  "language-awk"
  "language-babel"
  "language-diff"
  "language-env"
  "language-gitattributes"
  "language-gitignore"
  "language-har"
  "language-hosts"
  "language-ini"
  "language-javascript-jsx"
  "language-latex"
  "language-liquid"
  "language-lisp"
  "language-pegjs"
  "language-pip"
  "language-prolog"
  "language-sca"
  "language-svg"
  "language-tcl"
  "language-viml"
  "language-x86"
  "linter"
  "linter-coffeescript"
  "linter-eslint"
  "linter-flake8"
  "linter-jsonlint"
  "linter-php"
  "linter-shellcheck"
  "linter-ui-default"
  "monokai"
  "package-sync"
  "resize-indent"
  "sort-lines"
  "ssh-config"
  "svg-preview"
  "tabs-to-spaces"
  "teletype"
]

Add git-blame to Atom package list

Add git-blame to Atom package list