Refactor AJAX module

Refactor AJAX module

--- source/quo.ajax.coffee
+++ source/quo.ajax.coffee
@@ -44,11 +44,11 @@
     settings = $$.mix($$.ajaxSettings, options)

     if settings.type is DEFAULT.TYPE
-      settings.url += $$.serializeParameters(settings.data, "?")
+      settings.url += $$.serialize(settings.data, "?")
     else
-      settings.data = $$.serializeParameters(settings.data)
-
-    return $$.jsonp(settings) if _isJsonP(settings.url)
+      settings.data = $$.serialize(settings.data)
+
+    return _jsonp(settings) if _isJsonP(settings.url)

     xhr = settings.xhr()
     xhr.onreadystatechange = ->
@@ -67,9 +67,7 @@
     catch error
       xhr = error
       _xhrError "Resource not found", xhr, settings
-
-    (if (settings.async) then xhr else _parseResponse(xhr, settings))
-
+    xhr

   ###
@@ -168,7 +166,7 @@
         $$(script).remove()
         delete window[callbackName]

-        _xhrSuccess response, xhr, settings
+        _xhrSuccess response, settings

       script.src = settings.url.replace(RegExp("=\\?"), "=" + callbackName)
       $$("head").append script
@@ -182,14 +180,14 @@
   _xhrStatus = (xhr, settings) ->
     if (xhr.status >= 200 and xhr.status < 300) or xhr.status is 0
       if settings.async
-        _xhrSuccess _parseResponse(xhr, settings), xhr, settings
+        _xhrSuccess xhr, settings
         return
     else
       _xhrError "QuoJS.ajax: Unsuccesful request", xhr, settings
       return

-  _xhrSuccess = (response, xhr, settings) ->
-    settings.success.call settings.context, response, xhr
+  _xhrSuccess = (xhr, settings) ->
+    settings.success.call settings.context, xhr
     return

   _xhrError = (type, xhr, settings) ->
@@ -211,24 +209,12 @@

   _xhrForm = (method, url, data, success, dataType) ->
     $$.ajax
-      type: method
-      url: url
-      data: data
-      success: success
-      dataType: dataType
-      contentType: "application/x-www-form-urlencoded"
-
-  _parseResponse = (xhr, settings) ->
-    response = xhr.responseText
-    if response
-      if settings.dataType is DEFAULT.MIME
-          try
-            response = JSON.parse(response)
-          catch error
-            response = error
-            _xhrError "QuoJS.ajax: Parse Error", xhr, settings
-      else response = xhr.responseXML    if settings.dataType is "xml"
-    response
+      type        : method
+      url         : url
+      data        : data
+      success     : success
+      dataType    : dataType
+      contentType : "application/x-www-form-urlencoded"

   _isJsonP = (url) ->
     RegExp("=\\?").test url


Remixer dropdown cleaner

Remixer dropdown cleaner

--- coffee/src/views/remixer_view.coffee
+++ coffee/src/views/remixer_view.coffee
@@ -67,18 +67,22 @@

   initializeDropdownView: =>

+    moduleObject = (Shell) ->
+      {id:Shell.id, name:Shell.title, icon:Shell.icon}
+
     # get only the Link-based Modules
     modules = [
-      {id:LinkShell.id, name:'Link (iframe)', icon: LinkShell.icon}
-      {id:AcornLinkShell.id, name:'Acorn Link', icon: AcornLinkShell.icon}
-      {id:ImageLinkShell.id, name:'Image Link', icon: ImageLinkShell.icon}
-      {id:PDFLinkShell.id, name:'PDF Link', icon: PDFLinkShell.icon}
-      {id:YouTubeShell.id, name:'YouTube', icon: YouTubeShell.icon}
-      {id:VimeoShell.id, name:'Vimeo', icon: VimeoShell.icon}
+      moduleObject(LinkShell)
+      moduleObject(AcornLinkShell)
+      moduleObject(ImageLinkShell)
+      moduleObject(PDFLinkShell)
+      moduleObject(YouTubeShell)
+      moduleObject(VimeoShell)
       # '---' divisors TODO
-      {id:TextShell.id, name:'Text', icon: TextShell.icon}
+      moduleObject(TextShell)
+      moduleObject(DocShell)
       # '---' divisors TODO
-      {id:EmptyShell.id, name:'Empty', icon: EmptyShell.icon}
+      moduleObject(EmptyShell)
     ]

     selected = @model.module.id


Updated banner.

Updated banner.


Fixed bio length

Fixed bio length

--- app/assets/javascripts/controllers/user_index_controller.js.coffee
+++ app/assets/javascripts/controllers/user_index_controller.js.coffee
@@ -16,7 +16,7 @@
   bioCharCounter: (->
     newString = @get('user.miniBio')
     newLength = newString.length
-    remLength = 161 - newLength
+    remLength = 160 - newLength
     if remLength <= 0
       @set('user.miniBio', newString[0...160])
       remLength = 0


add allowTransparency="true" to <iframe> for ie8

--- app/assets/javascripts/uploadcare/widget/tabs/remote-tab.js.coffee
+++ app/assets/javascripts/uploadcare/widget/tabs/remote-tab.js.coffee
@@ -36,6 +36,7 @@
               marginheight: 0
               marginwidth: 0
               frameborder: 0
+              allowTransparency: "true"
             .css
               width: '100%'
               height: '100%'


I should kill myself

I should kill myself

--- modules/danbooru.coffee
+++ modules/danbooru.coffee
@@ -82,7 +82,7 @@

     @registerCommand 'setwaifu', { allowDM: true }, (msg, args, d)=>
       return if not d.data.allowWaifus
-      waifu = (args.match(/\w+/) or [''])[0]
+      waifu = (args.match(/\S+/) or [''])[0]
       return msg.reply "Usage: ```#{@prefix}setWaifu <safebooru_tag>```" if not waifu
       # Do a dummy search
       qs = {


update code to reflect comment

update code to reflect comment

--- common/lib/xmodule/xmodule/js/src/peergrading/track_changes.coffee
+++ common/lib/xmodule/xmodule/js/src/peergrading/track_changes.coffee
@@ -54,7 +54,7 @@
     keyOfLatestChange = 0
     @tracked_changes = @$(@tracked_changes_sel)
     @tracked_changes.each ->
-      key = parseInt($(@).attr('data-cid'))
+      key = $(@).data('cid')
       if key > keyOfLatestChange
         keyOfLatestChange = key
     @tracker.rejectChange('[data-cid="'+ keyOfLatestChange + '"]')


Cancel timers on destruction of scope

Cancel timers on destruction of scope

--- community/browser/app/scripts/controllers/SysinfoController.coffee
+++ community/browser/app/scripts/controllers/SysinfoController.coffee
@@ -115,6 +115,8 @@
           (Settings.refreshInterval * 1000)
         )

+    $scope.$on '$destroy', () => $timeout.cancel(timer)
+
     $scope.isMaster = (member) ->
       return member.haRole is 'master'


[skip] Deleted unused code (1m)

[skip] Deleted unused code (1m)

--- spec/javascripts/queueing_discipline_spec.coffee
+++ spec/javascripts/queueing_discipline_spec.coffee
@@ -1,17 +0,0 @@
-#= require_tree ../../app/assets/javascripts/houston-scheduler/models/queuing_disciplines
-
-# !nb: it'll take a little more work to load Backbone
-# c.f. http://chaijs.com/api/assert/
-#      http://visionmedia.github.com/mocha/
-#      https://github.com/jfirebaugh/konacha
-#      http://www.solitr.com/blog/2012/04/konacha-tutorial-javascript-testing-with-rails/
-
-describe 'Queuing Disciplines', ->
-
-  describe 'Maxamize ROI', ->
-
-    before ->
-      @qd = new Scheduler.QueuingDiscipline.MaximizeRoi()
-
-    it 'should be able to report its own name', ->
-      assert.equal(@qd.name, 'Maximize ROI')


refactor a little

refactor a little

--- client/code/router/main.coffee
+++ client/code/router/main.coffee
@@ -85,9 +85,7 @@

   dataset: (box) ->
     doNotNavigate = false
-    render = =>
-      views.findByToolName 'datatables-view-tool', (dataTablesView) =>
-        alert 'NULL DT' unless dataTablesView
+    render = (dataTablesView) =>
         subnavView = new Cu.View.DatasetNav {model: model, view: dataTablesView}
         @subnavView.showView subnavView
         contentView = new Cu.View.PluginContent {model: dataTablesView}
@@ -103,16 +101,20 @@
       views = model.get 'views'
       subnavView = new Cu.View.DatasetNav {model: model}
       @subnavView.showView subnavView
-      if dataTablesView?
-        render()
-      else
-        views.once 'update:tool', =>
-          doNotNavigate = true
-          render()
-        setTimeout ->
-          unless doNotNavigate
-            app.navigate "/dataset/#{model.id}/settings", trigger: true
-        , 200
+
+      views.findByToolName 'datatables-view-tool', (dataTablesView) =>
+        if dataTablesView?
+          render dataTablesView
+        else
+          views.once 'update:tool', =>
+            console.log 'UPDATE TOOL'
+            doNotNavigate = true
+            render dataTablesView
+          setTimeout ->
+            console.log "navigating"
+            unless doNotNavigate
+              app.navigate "/dataset/#{model.id}/settings", trigger: true
+          , 1000

   datasetSettings: (box) ->
     mod = Cu.Model.Dataset.findOrCreate box: box


fix logic

fix logic

Former-commit-id: 1b9d781b0ae3610ac0f45f4152099dda6070b887 [formerly e9c2de3a9b1ebfc50b6642641a04625d648afd1a] [formerly 6612b5886316ef751f7fa12dc60bd692d66bac91 [formerly 58af516cc2eb6eef7adeac4957a088442012c7bc]] [formerly 2951b371f35253c41c342d3274f985e67b915af4 [formerly e4a743178e70c6a24e40acc92c3547ab3082ec45] [formerly 3ba025f174905545c775913126c6b0bc07e51452 [formerly 3ba025f174905545c775913126c6b0bc07e51452 [formerly 26e118c6a14b90bb2e86f067f487dea774c26e58]]]]
Former-commit-id: 7e1fb3c458f2cf28017e90008cd0bc88deab69c0 [formerly 04abb318d30175ccf885b478a62f334334c3f262] [formerly b116d196d9d2837b0bf55f9ef21e8802b59d071b [formerly 4bf76329fa85ca81af469c5baa929cc957b6c692]]
Former-commit-id: a9b833990342b3461e6236600b484543dd629743 [formerly 30fefd0e5e6e854ee17ec04debbc72ed208b7d92]
Former-commit-id: 58730fb67ff343548636ac83bed7ec93fc781459
Former-commit-id: abcf9aef5ffdcc9c5a666f698f39becd1d5c5ac3

--- @client/franklin.coffee
+++ @client/franklin.coffee
@@ -1420,7 +1420,7 @@
           curr_column = Math.floor(i / s.rows)
           side_offset = curr_column * s.col_gap + i * s.dx
           top_offset = (i % s.rows) * s.dy
-          left_right = if @data().is_pro && !@props.rendered_as == 'under_review' then 'left' else 'right'
+          left_right = if @data().is_pro && @props.rendered_as != 'under_review' then 'left' else 'right'
           style =
             top: top_offset
             position: 'absolute'


simplifying and  mostly merging TagHomepage and SimpleHomepage

--- @client/homepage.coffee
+++ @client/homepage.coffee
@@ -78,8 +78,9 @@
 window.Homepage = ReactiveComponent
   displayName: 'Homepage'
   render: ->
-    doc = fetch('document')
-    subdomain = fetch('/subdomain')
+    doc = fetch 'document'
+    subdomain = fetch '/subdomain'
+    homepage_tabs = fetch 'homepage_tabs'

     return SPAN null if !subdomain.name

@@ -92,7 +93,35 @@
     DIV
       key: "homepage_#{subdomain.name}"

-      SimpleHomepage()
+      DIV
+        id: 'homepagetab'
+        role: if customization('homepage_tabs') then "tabpanel"
+        style:
+          margin: '45px auto'
+          width: HOMEPAGE_WIDTH()
+          position: 'relative'
+
+        if customization('auth_callout')
+          AuthCallout()
+
+        if !fetch('/proposals').proposals
+          ProposalsLoading()
+        else
+          if customization('homepage_tab_views')?[homepage_tabs.filter]
+            view = customization('homepage_tab_views')[homepage_tabs.filter]()
+            if typeof(view) == 'function'
+              view = view()
+            view
+          else
+            SimpleHomepage()
+
+  typeset : ->
+    subdomain = fetch('/subdomain')
+    if subdomain.name == 'RANDOM2015' && $('.MathJax').length == 0
+      MathJax.Hub.Queue(["Typeset", MathJax.Hub, ".proposal_homepage_name"])
+
+  componentDidMount : -> @typeset()
+  componentDidUpdate : -> @typeset()

 window.proposal_editor = (proposal) ->
@@ -118,185 +147,43 @@

   render: ->
     current_user = fetch('/current_user')
-
-    show_all = fetch('show_all_proposals')
-
-    users = fetch '/users'
-    proposals = fetch '/proposals'
-    proposals = proposals.proposals
-
-    if !proposals || !users.users
-      return ProposalsLoading()
-
-    clusters = get_all_lists()
-
-    hues = getNiceRandomHues clusters.length
-    colors = {}
-    for cluster, idx in clusters
-      colors[cluster] = hues[idx]
-
-    proposals = sorted_proposals(proposals, @local.key, true)
+    proposals = sorted_proposals(fetch('/proposals').proposals, @local.key, true)

     homepage_tabs = fetch 'homepage_tabs'
-
-    dummy_cluster = homepage_tabs.filter
-
-    collapsed = fetch 'collapsed_clusters'
-    if !collapsed["list/#{dummy_cluster}"]?
-      collapsed["list/#{dummy_cluster}"] = customization('list_is_archived', "list/#{dummy_cluster}")
-      save collapsed
-
-
-
-    DIV
-      id: 'homepagetab'
-      role: if customization('homepage_tabs') then "tabpanel"
-      style:
-        margin: '45px auto'
-        width: HOMEPAGE_WIDTH()
-        position: 'relative'
-
-      if customization('auth_callout')
-        AuthCallout()
-
-      ManualProposalResort sort_key: @local.key
-
-      ListHeader
-        list:
-          key: "list/#{dummy_cluster}"
-          name: dummy_cluster
-          proposals: []
-          list_is_archived: customization('list_is_archived', "list/#{dummy_cluster}")
-        allow_editing: false
-        proposals_count: proposals.length
-
-
-
-
-      UL null,
-
-        for proposal,idx in proposals
-          continue if idx > 20 && !show_all.show_all
-          cluster = proposal.cluster or 'Proposals'
-
-          CollapsedProposal
-            key: "collapsed#{proposal.key}"
-            proposal: proposal
-            show_category: true
-            category_color: hsv2rgb(colors[cluster], .7, .8)
-
-        if (show_all.show_all || proposals.length <= 20) && customization('list_show_new_button', "list/#{dummy_cluster}")
-          LI
-            key: "newlist/#{dummy_cluster}"
-            style:
-              margin: 0
-              padding: 0
-              listStyle: 'none'
-              display: 'inline-block'
-              marginBottom: 20
-              marginTop: 6
-
-
-            NewProposal
-              cluster_name: dummy_cluster
-              local: @local.key
-              label_style: {}
-
-      if !show_all.show_all && proposals.length > 20
-        BUTTON
-          style:
-            backgroundColor: '#f9f9f9'
-            width: HOMEPAGE_WIDTH()
-            #position: 'absolute'
-            #bottom: 0
-            textDecoration: 'underline'
-            cursor: 'pointer'
-            paddingTop: 10
-            paddingBottom: 10
-            fontWeight: 600
-            textAlign: 'center'
-            marginTop: 40
-            border: 'none'
-            fontSize: 22
-
-          onMouseDown: =>
-            show_all.show_all = true
-            save(show_all)
-
-          translator "engage.show_hidden_proposals", 'Show all proposals'
+    aggregate_list_key = homepage_tabs.filter
+
+    List
+      key: aggregate_list_key
+      aggregates: get_all_lists()
+      list:
+        key: "list/#{aggregate_list_key}"
+        name: aggregate_list_key
+        proposals: proposals

 #############
 # SimpleHomepage
 #
 # Two column layout, with proposal name and mini histogram.
-# Divided into clusters.
+# Divided into lists.

 window.SimpleHomepage = ReactiveComponent
   displayName: 'SimpleHomepage'

   render : ->
-    subdomain = fetch('/subdomain')
-
+    current_user = fetch('/current_user')
+    lists = clustered_proposals_with_tabs()
     homepage_tabs = fetch 'homepage_tabs'

-    if customization('homepage_tab_views')?[homepage_tabs.filter]
-      view = customization('homepage_tab_views')[homepage_tabs.filter]()
-      if typeof(view) == 'function'
-        view = view()
-      return view
-
-    proposals = fetch '/proposals'
-    current_user = fetch('/current_user')
-
-    if !proposals.proposals
-      return ProposalsLoading()
-
-    clusters = clustered_proposals_with_tabs()
-
-    collapsed = fetch 'collapsed_clusters'
-    for cluster in clusters
-      if !collapsed[cluster.key]?
-        collapsed[cluster.key] = customization('list_is_archived', cluster.key)
-        save collapsed
-
-    DIV
-      id: 'homepagetab'
-      role: if customization('homepage_tabs') then "tabpanel"
-      style:
-        margin: '45px auto'
-        width: HOMEPAGE_WIDTH()
-        position: 'relative'
-
-      if customization('homepage_tabs') && customization('homepage_tab_headers')?[homepage_tabs.filter]
-        customization('homepage_tab_headers')[homepage_tabs.filter]()
-
-      if customization('auth_callout') && homepage_tabs.filter not in ['About', 'FAQ']
-        AuthCallout()
-
-
-
-      DIV null,
-        # List all clusters
-        for cluster, index in clusters or []
-          List
-            key: "list/#{cluster.name}"
-            list: cluster
-            index: index
-
-        if current_user.is_admin && homepage_tabs.filter not in ['About', 'FAQ']
-
-          NewList()
+    DIV null,
+      for list, index in lists or []
+        List
+          key: "list/#{list.name}"
+          list: list
+
+      if current_user.is_admin && homepage_tabs.filter not in ['About', 'FAQ']
+        NewList()

-
-  typeset : ->
-    subdomain = fetch('/subdomain')
-    if subdomain.name == 'RANDOM2015' && $('.MathJax').length == 0
-      MathJax.Hub.Queue(["Typeset", MathJax.Hub, ".proposal_homepage_name"])
-
-  componentDidMount : -> @typeset()
-  componentDidUpdate : -> @typeset()
-

 window.HomepageTabTransition = ReactiveComponent


removed logic and points tabs from popovers

--- components/default-components.coffee
+++ components/default-components.coffee
@@ -30,8 +30,6 @@

Properties

Validations

-
Logic

-
Points

@@ -46,20 +44,6 @@

-

-

-

-                                <select class="form-control custom-m-b" ng-model="formObject.logic.action" ng-options="action for action in actions"></select>
 this element if

-                                <component-selector></component-selector>
-
-                                <select class="form-control custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-

@@ -110,8 +94,6 @@

Properties

Validations

-
Logic

-
Points

@@ -177,52 +159,6 @@

-

-

-                                <select class="form-control custom-m-b" ng-model="formObject.logic.action" ng-options="action for action in actions"></select>
 this element if

-                                <component-selector></component-selector>
-
-                                <select class="form-control custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-

-
-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}
-

-

-

-

-                                Add
-                                <input type="text" class="form-control" ng-model="newRule.points">
-                                points
-

-

-
-

-

-                              if this field
-                              <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-
-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value">
-
-                              <button ng-click="addRule()" class="btn btn-primary" type="button">+</button>
-
-

-
{{rulesErrorMessage}}

-
-

-
-

@@ -281,8 +217,6 @@

Properties

Validations

-
Logic

-
Points

@@ -320,51 +254,6 @@
                                 <select ng-model="$parent.validation" class='form-control' ng-options="option.rule as option.label for option in validationOptions"></select>

-

-

-                                <select class="form-control custom-m-b" ng-model="formObject.logic.action" ng-options="action for action in actions"></select>
 this element if

-                                <component-selector></component-selector>
-
-                                <select class="form-control custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-

-
-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}
-

-

-

-

-                                Add
-                                <input type="text" class="form-control" ng-model="newRule.points">
-                                points
-

-

-
-

-

-                              if this field
-                              <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-
-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value">
-
-                              <button ng-click="addRule()" class="btn btn-primary" type="button">+</button>
-
-

-
{{rulesErrorMessage}}

-
-

-

@@ -424,8 +313,6 @@

Properties

Validations

-
Logic

-
Points

@@ -492,50 +379,6 @@
                                     <input type="text" class="form-control" ng-model="maxLength" placeholder="Max Length">

-

-

-

-                                <select class="form-control custom-m-b" ng-model="formObject.logic.action" ng-options="action for action in actions"></select>
 this element if

-                                <component-selector></component-selector>
-
-                                <select class="form-control custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-

-
-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}
-

-

-

-

-                                Add
-                                <input type="text" class="form-control" ng-model="newRule.points">
-                                points
-

-

-
-

-

-                              if this field
-                              <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-
-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value">
-
-                              <button ng-click="addRule()" class="btn btn-primary" type="button">+</button>
-
-

-
{{rulesErrorMessage}}

-

@@ -584,8 +427,6 @@

Properties

Validations

-
Logic

-
Points

@@ -621,49 +462,6 @@
                               <input type="checkbox" id="{{'required' + date + index}}" ng-model="required">
                               Required

-

-

-

-                                <select class="form-control custom-m-b" ng-model="formObject.logic.action" ng-options="action for action in actions"></select>
 this element if

-                                <component-selector></component-selector>
-                                <select class="form-control custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-

-
-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}
-

-

-

-

-                                Add
-                                <input type="text" class="form-control" ng-model="newRule.points">
-                                points
-

-

-
-

-

-                              if this field
-                              <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-
-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value">
-
-                              <button ng-click="addRule()" class="btn btn-primary" type="button">+</button>
-
-

-
{{rulesErrorMessage}}

-

@@ -718,8 +516,6 @@

Properties

Validations

-
Logic

-
Points

@@ -755,50 +551,6 @@
                               <input type="checkbox" id="{{'required' + date + index}}" ng-model="required">
                               Required

-

-

-

-                                <select class="form-control custom-m-b" ng-model="formObject.logic.action" ng-options="action for action in actions"></select>
 this element if

-                                <component-selector></component-selector>
-
-                                <select class="form-control custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-

-
-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}
-

-

-

-

-                                Add
-                                <input type="text" class="form-control" ng-model="newRule.points">
-                                points
-

-

-
-

-

-                              if this field
-                              <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-
-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value">
-
-                              <button ng-click="addRule()" class="btn btn-primary" type="button">+</button>
-
-

-
{{rulesErrorMessage}}

-

@@ -853,8 +605,6 @@

Properties

Validations

-
Logic

-
Points

@@ -892,51 +642,6 @@
                                     Required

-

-

-

-                                <select class="form-control" ng-model="formObject.logic.action" ng-options="action for action in ['Hide', 'Show']"></select>
 this element if

-                                <component-selector></component-selector>
-
-                                <select class="form-control  custom-m-b" ng-model="formObject.logic.comparator" ng-options="comparator for comparator in comparatorChoices">
-                                </select>
-                                <input type="text" ng-model="formObject.logic.value" class="form-control" placeholder="Value">
-                                <button type="button" ng-click="resetLogic()" class="btn btn-default pull-right">Reset</button>
-

-

-

-
-

-
-
 0">
-                            Active Rules
-

-                              Add {{rule.points}} points if this field {{rule.predicate | predicate}} {{rule.value}}
-

-

-

-

-                                Add
-                                <input type="text" class="form-control" ng-model="newRule.points">
-                                points
-

-

-
-

-

-                              if this field
-                              <select ng-model="newRule.predicate" ng-options="predicate.value as predicate.label for predicate in predicates" class="form-control"></select>
-

-

-
-

-                            <input ng-readonly="newRule.predicate === 'null' || newRule.predicate === 'not_null'" ng-model="newRule.value" type="text" class="form-control" placeholder="value">
-
-                              <button ng-click="addRule()" class="btn btn-primary" type="button">+</button>
-
-

-
{{rulesErrorMessage}}

-


KDTabPaneView: Hotfix, make sure there is a parent element.

--- components/tabs/KDTabPaneView.coffee
+++ components/tabs/KDTabPaneView.coffee
@@ -30,7 +30,7 @@
     KD.utils.defer =>
       document.documentElement.scrollTop = @lastScrollTops.window
       @getElement().scrollTop            = @lastScrollTops.self
-      @parent.getElement().scrollTop     = @lastScrollTops.parent
+      @parent?.getElement?().scrollTop   = @lastScrollTops.parent

   hide:->


Virtualization: forgotten callback added to virtualizationController

--- client/Main/VirtualizationController.coffee
+++ client/Main/VirtualizationController.coffee
@@ -112,6 +112,7 @@
       action   : "Destroy my VM"
       callback : =>
         @deleteVmByHostname hostnameAlias, (err) ->
+          callback err
           return if KD.showError err
           new KDNotificationView title:'Successfully destroyed!'
           appStorage = KD.getSingleton('appStorageController').storage 'Finder', '1.2'


Enable voting to anybody

Enable voting to anybody

--- client/view/vote-widget.coffee
+++ client/view/vote-widget.coffee
@@ -7,8 +7,7 @@
   catch e

 Template.voteWidget.votingEnabled = ->
-  u = User.current()
-  u and (u.admin() or u.moderator())
+  true

 Template.voteWidget.events
   'click .vote-up': ->


don't show loading bar when hiding legend

--- app/scripts/models/choropleth_map.coffee
+++ app/scripts/models/choropleth_map.coffee
@@ -152,6 +152,7 @@
     if @_getSnippetModel().data('map')
       switch property
         when 'colorScheme' then return false
+        when 'hideLegend' then return false
         else
           return true
     else if prefilledMapNames.indexOf(@_getSnippetModel().identifier) != -1


Use error.message if exists

Use error.message if exists

--- client/landing/app/MainApp/KD.extend.coffee
+++ client/landing/app/MainApp/KD.extend.coffee
@@ -100,7 +100,8 @@
     err.name or= 'KodingError'

     content    = ''
-    errMessage = message or messages[err.name]
+    errMessage = err.message or messages[err.name] or messages.KodingError
+
     if errMessage?
       if 'string' is typeof errMessage
         title = errMessage


KD.extend: #showError log the error itself

In the case of server-side validation errors, it's helpful to inspect the error object itself, because the message "Errors were encountered during validation" is generic, but if you look at the .errors property, you see the actual errors that occurred.

--- client/landing/app/MainApp/KD.extend.coffee
+++ client/landing/app/MainApp/KD.extend.coffee
@@ -122,7 +122,9 @@

     new KDNotificationView {title, content, duration}

-    warn "KodingError:", err.message  unless err.name is 'AccessDenied'
+    unless err.name is 'AccessDenied'
+      warn "KodingError:", err.message
+      error err
     err?

   getPathInfo: (fullPath)->


Directing new registrant to the correct place depending on if they are a volunteer or now.

--- client/tournaments/register/register.coffee
+++ client/tournaments/register/register.coffee
@@ -111,7 +111,7 @@
         message: 'To continue, you must agree to the terms by checking the box.'
     else
       associateUserWithTournament userId
-      if Session.get('active-team').teamName = 'Volunteer'
+      if $("#role option:selected").text() is 'Volunteer'
         createNewVolunteer _id: userId, (err) ->
           if err
             Template.userMessages.showMessage
@@ -119,5 +119,7 @@
               title: 'Uh oh! '
               message: 'There was an error creating your volunteer record.
                 Reason: ' + err.reason
-      Router.go 'preferences', tournamentSlug: slug
+        Router.go 'preferences', tournamentSlug: slug
+      else
+        Router.go 'profileEdit'
     false


only owners can add users to private groups

--- client/views/app/chatWindowDashboard.coffee
+++ client/views/app/chatWindowDashboard.coffee
@@ -177,7 +177,7 @@

 		return '' unless roomData

-		return roomData.t is 'p' or (roomData.t is 'c' and roomData.uid is Meteor.userId())
+		return roomData.t in ['p', 'c'] and roomData.uid is Meteor.userId()

 	canEditName: ->
 		roomData = Session.get('roomData' + this._id)


guard against undefined concat

guard against undefined concat

--- coffee/PrimeNumberStore.coffee
+++ coffee/PrimeNumberStore.coffee
@@ -130,7 +130,7 @@
     debug('chunk index:%d', chunkIndex)

     # primeSumTbl[chunkIndex] = [ chunkPrimeTbl.primes.length ,  chunkPrimeTbl.sum ]
-    primeTbl[chunkIndex] = _.uniq(_.concat(primeTbl[chunkIndex], chunkPrimeTbl.primes))
+    primeTbl[chunkIndex] = _.uniq(_.concat(primeTbl[chunkIndex] or [], chunkPrimeTbl.primes or []))

     # store the primes
     self.store.qSet(PRIME_TBL, chunkIndex, chunkPrimeTbl.primes)
@@ -213,6 +213,7 @@

             promise.then((primeRecords)->
                 _.each(fieldArr, (value, index)->
+
                     unless primeRecords[index]? or primeRecords[index].length > 0
                         return

@@ -254,20 +255,20 @@
         chain.then(()->
             _.each([minIndex..maxIndex], (index)->

-                # debug("index:%d min:%d max:%d", index, min, max)
-                filtered = _.filter(primeTbl[index], (prime)->
+                debug("index:%d min:%d max:%d", index, min, max)
+                filtered = _.filter(primeTbl[index] or [], (prime)->

                         if prime < min  or prime > max
                             return false

-                        debug("%d", prime)
+                        # debug("%d", prime)

                         sum = sum + prime
                         return true
                 )

-                # debug("filtered: %s:%d", filtered, filtered.length)
-                if filtered.length > 0 then primes = _.concat(primes, filtered)
+                debug("filtered: %s:%d", filtered, filtered.length)
+                if _.isArray(filtered) and filtered.length > 0 then primes = _.concat(primes, filtered)
             )

             if primes.length > 0 then mean = sum / primes.length


Fix initial looks, resize component on scroll

--- framer/Components/ScrollComponent.coffee
+++ framer/Components/ScrollComponent.coffee
@@ -74,6 +74,7 @@
 		options.clip ?= true
 		options.name ?= "ScrollComponent"
 		options.mouseWheelEnabled ?= false
+		options.backgroundColor ?= null

 		super options

@@ -91,10 +92,12 @@
 		# Calculates the size of the content. By default this returns the total
 		# size of all the content layers based on width and height. You can override
 		# this for example to take scaling into account.
-		frame = @content.contentFrame()
-		frame.width = @width if frame.width < @width
-		frame.height = @height if frame.height < @height
-		return frame
+
+		contentFrame = @content.contentFrame()
+		return size =
+			width:  Math.max(@width, contentFrame.width)
+			height: Math.max(@height, contentFrame.height)
+

 	setContentLayer: (layer) ->

@@ -104,24 +107,26 @@
 		@_content.superLayer = @
 		@_content.name = "ScrollContent"
 		@_content.clip = false
-		@_content.backgroundColor = null
 		@_content.draggable.enabled = true
 		@_content.draggable.momentum = true
 		@_content.on("change:subLayers", @_updateContent)

+		# Update the content view size on resizing the ScrollComponent
+		@on("change:width", @_updateContent)
+		@on("change:height", @_updateContent)
+
 		@_updateContent()
 		@scrollPoint = {x:0, y:0}

 		return @_content

-
-	_updateContent: (info) =>
+	_updateContent: =>

 		# Update the constraints based on the content size and contentInset

 		contentFrame = @calculateContentSize()
-		contentFrame.x += @_contentInset.left
-		contentFrame.y += @_contentInset.top
+		contentFrame.x = 0 + @_contentInset.left
+		contentFrame.y = 0 + @_contentInset.top
 		@content.frame = contentFrame

 		constraintsFrame = @calculateContentSize()


nonbreakable spaces

nonbreakable spaces

--- js/app.coffee
+++ js/app.coffee
@@ -84,17 +84,17 @@
   # ctvrt
   (ts) ->
     strings = [
-      'celá a něco'
-      'za chvíli čtvrt'
+      'celá a něco'
+      'hnedle tři čtvrtě'
+      'za chvíli čtvrt'
       'čtvrt'
-      'po čtvrt'
-      'bude půl'
+      'po čtvrt'
+      'bude půl'
       'půl'
       'po půl'
-      'hnedle tři čtvrtě'
-      'tři čtvrtě'
-      'po tři čtvrtě'
-      'bude celá'
+      'tři čtvrtě'
+      'po tři čtvrtě'
+      'bude celá'
       'celá'
     ]
     size = strings.length


Fixed false positive, wrapped `yield` in a `call`


Add loader to task page

Add loader to task page

--- projects/static/coffee/project.coffee
+++ projects/static/coffee/project.coffee
@@ -8,6 +8,9 @@

 $ ->
+    NProgress.start()
+    NProgress.inc()
+
     app = window.coviolations

     class PlotData
@@ -66,6 +69,10 @@
                     el: $('.js-task-line-list')
                     collection: collection
                     showProjectName: false
+
+                view.on 'renderFinished', =>
+                    NProgress.inc()
+
                 view.render()

                 data = new PlotData
@@ -77,6 +84,8 @@
                                 data.push violation.name, pair[0], pair[1], task.get('resource_uri')

                 data.normalise()
+
+                NProgress.inc()

                 $('.js-charts-holder').empty()

@@ -96,6 +105,9 @@
                         name: name
                     view.render()
                     view.$el.appendTo $('.js-charts-holder')
+                    NProgress.inc()
+
+                NProgress.done()

     renderPage()
     window.push.on 'task', (task) =>


Changes to right bus

Changes to right bus

--- coffee/game/score_manager.coffee
+++ coffee/game/score_manager.coffee
@@ -3,8 +3,8 @@
     @displayer = $(selector)
     @currentScore = 0

-    EventBus.get('RideEngine').register PickupZoneVanishedEvent.NAME, (z) => @onMissedPickup(z)
-    EventBus.get('RideEngine').register DropZoneVanishedEvent.NAME, (z) => @onMissedDrop(z)
+    EventBus.get('Zone').register PickupZoneVanishedEvent.NAME, (z) => @onMissedPickup(z)
+    EventBus.get('Zone').register DropZoneVanishedEvent.NAME, (z) => @onMissedDrop(z)
     EventBus.get('RideEngine').register DropEvent.NAME, (z) => @onDrop(z)

   _refreshScore: () ->


Always assign scopeName

Always assign scopeName

--- lib/package-grammars-view.coffee
+++ lib/package-grammars-view.coffee
@@ -39,8 +39,10 @@
     @grammarSettings.empty()

     for grammar in @getPackageGrammars()
-      continue unless grammar.scopeName
-      scopeName = ".#{grammar.scopeName}" unless grammar.scopeName.startsWith('.')
+      {scopeName} = grammar
+      continue unless scopeName
+      scopeName = ".#{scopeName}" unless scopeName.startsWith('.')
+
       title = "#{grammar.name} Grammar"
       panel = new SettingsPanel(null, {title, scopeName, icon: 'puzzle'})
       @addGrammarHeading(grammar, panel)


upgrade the pinpoint with vanishing sel watchers

--- library/exposure/pinpoint.coffee
+++ library/exposure/pinpoint.coffee
@@ -62,6 +62,37 @@
     # Refer to `BowerSupport` class implementation for information.
     @bower "mutation-summary", "src/mutation-summary.js"

+    # Pinpoint when the specified selector vanishes (is removed or
+    # moved) and then invoke the supplied rendering function, which
+    # will receive the newly pinpointed node as its first argument.
+    # If multiple nodes with this selector vanished, then renderer
+    # will be invoked once for every disappeared node of a selector.
+    # Selectors must conform to the strict subset of CSS selectors.
+    @vanished: @transferred (selector, renderer) ->
+        noSelector = "no valid CSS selector is supplied"
+        noRenderer = "no valid rendering function given"
+        noLibrary = "mutation-summary library is missing"
+        assert _.isFunction(MutationSummary), noLibrary
+        assert _.isFunction(renderer or no), noRenderer
+        assert _.isString(selector or null), noSelector
+        assert instruct = queries: [element: selector]
+        pp = "watch vanished %s selector for a #{@service}"
+        try logger.info pp.toString(), selector.toString()
+        go = (n) => try $(n).data("owners") or new Array()
+        make = -> observer = new MutationSummary instruct
+        callback = (fn) -> instruct.callback = fn; make()
+        return callback (sum) => _.each sum, (summary) =>
+            na = "missing the element addition summary"
+            pe = "got vanish %s elements for %s service"
+            moved = new Array() # source vec for concat
+            moved = moved.concat summary.removed or []
+            moved = moved.concat summary.reparented or []
+            return unless (try moved.length or null) > 0
+            logger.info pe, moved.length, this.service
+            $(nod).data owners: go(nod) for nod in moved
+            go(nod).push this for nod in moved or Array()
+            _.each moved, (nod) -> renderer n, go(nod)
+
     # Pinpoint when the specified selector appears (or if it already
     # exists) and then invoke the supplied rendering function, which
     # will receive the newly pinpointed node as its first argument.
@@ -85,6 +116,7 @@
             na = "missing the element addition summary"
             pe = "pinpointed %s elements for %s service"
             assert _.isArray(added = summary.added), na
+            return unless (try added.length or null) > 0
             logger.info pe, added.length, this.service
             $(nod).data owners: go(nod) for nod in added
             go(nod).push this for nod in added or Array()


Unpack the arguments in ipc message

Unpack the arguments in ipc message

--- atom/browser/api/lib/web-contents.coffee
+++ atom/browser/api/lib/web-contents.coffee
@@ -48,10 +48,12 @@
     process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}"

   # Dispatch IPC messages to the ipc module.
-  webContents.on 'ipc-message', (event, channel, args...) ->
+  webContents.on 'ipc-message', (event, packed) ->
+    [channel, args...] = packed
     Object.defineProperty event, 'sender', value: webContents
     ipc.emit channel, event, args...
-  webContents.on 'ipc-message-sync', (event, channel, args...) ->
+  webContents.on 'ipc-message-sync', (event, packed) ->
+    [channel, args...] = packed
     Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
     Object.defineProperty event, 'sender', value: webContents
     ipc.emit channel, event, args...


f'real fix for that weird prompt

f'real fix for that weird prompt

--- public/javascripts/application.coffee
+++ public/javascripts/application.coffee
@@ -78,12 +78,10 @@

       # prompt if no comment
       $note = $this.find('textarea')
-      ###
-      if not $note.val()
+      if $note.length > 0 and not $note.val()
         unless confirm "Are you sure you want to vote without leaving any feedback?"
           e.stopImmediatePropagation()
           return false
-      ###

       true
     .delegate 'a.change', 'click', (e) ->


Added method to retrieve resources

Added method to retrieve resources

--- public/javascripts/game.puzzle.coffee
+++ public/javascripts/game.puzzle.coffee
@@ -40,7 +40,33 @@
     reset: ->
       console.log(@resources)
       console.log('abstract reset method')
+
   currentGame = new puzzleGame true, 4, 4, 8
+
+  reqParam = {
+    resource_id: 'cf6e12d8-bd8d-4232-9843-7fa3195cee1c',
+    limit: 10
+  };
+
+  retrieveResources = ->
+    $.ajax {
+      url: 'http://data.gov.au/api/action/datastore_search',
+      data: reqParam,
+      dataType: 'jsonp',
+      cache: true
+    }
+
+  processData = (data) ->
+    processedData = []
+    for item in data.result.records
+      if item['High resolution image']
+        processedData.push(item)
+    return processedData
+
+  $('#play').click ->
+    retrieveResources().then (res) ->
+      currentGame.init(processData(res))
+      return
     return

   $('#reset').click ->


Whitespace cleanup

Whitespace cleanup

--- core/spec/javascripts/views/tour/tour_interesting_users_view_spec.coffee
+++ core/spec/javascripts/views/tour/tour_interesting_users_view_spec.coffee
@@ -4,7 +4,6 @@
 describe 'TourInterestingUsersView', ->

   describe '8 users in total, spanning 2 pages, 2x2 grid', ->
-
     beforeEach ->
       window.currentUser = new User

@@ -30,7 +29,6 @@
         expect(@view.$('.js-scrolling-inner').width()).to.equal 40

     describe 'after going to the second page', ->
-
       beforeEach ->
         @view.showNextPage()


Removing debug info.

Removing debug info.

--- core/app/backbone/views/channel_view.coffee
+++ core/app/backbone/views/channel_view.coffee
@@ -66,13 +66,11 @@
     @stop_updating_count()

   stop_updating_count: ->
-    console.info 'stop running', @running
     if @running
       clearTimeout(@timer)
       @running = false

   start_updating_count: ->
-    console.info 'running', @running
     unless @running
       @running = true
       @timer = setTimeout((=> @fetch_activity_count(); @running=false; @start_updating_count()),10*1000)


fix(threads): Circular include blocking FocusdPerspectiveStore. Sentry #11763

--- src/flux/stores/focused-perspective-store.coffee
+++ src/flux/stores/focused-perspective-store.coffee
@@ -1,6 +1,5 @@
 _ = require 'underscore'
 NylasStore = require 'nylas-store'
-WorkspaceStore = require './workspace-store'
 AccountStore = require './account-store'
 MailboxPerspective = require '../../mailbox-perspective'
 CategoryStore = require './category-store'


pass graph events to runtime

pass graph events to runtime

--- components/ConnectRuntime.coffee
+++ components/ConnectRuntime.coffee
@@ -18,39 +18,84 @@
     @inPorts.runtime.on 'data', (@runtime) =>
       @connect @editor, @runtime

+  sendGraph: (runtime, editor) ->
+    runtime.sendGraph 'clear',
+      baseDir: 'noflo-ui-preview'
+    graph = editor.toJSON()
+    for name, definition of graph.processes
+      runtime.sendGraph 'addnode',
+        id: name
+        component: definition.component
+        metadata: definition.metadata
+    for edge in graph.connections
+      if edge.src
+        runtime.sendGraph 'addedge',
+          from:
+            node: edge.src.process
+            port: edge.src.port
+          to:
+            node: edge.tgt.process
+            port: edge.tgt.port
+        continue
+      runtime.sendGraph 'addinitial',
+        from:
+          data: edge.data
+        to:
+          node: edge.tgt.process
+          port: edge.tgt.port
+
+  convertNode: (node) ->
+    node.toJSON()
+  convertEdge: (edge) ->
+    data = edge.toJSON()
+    edgeData =
+      from:
+        node: data.src.process
+        port: data.src.port
+      to:
+        node: data.tgt.process
+        port: data.tgt.port
+  convertInitial: (iip) ->
+    data = iip.toJSON()
+    iipData =
+      from:
+        data: data.data
+      to:
+        node: data.tgt.process
+        port: data.tgt.port
+
+  subscribeEditor: (editor, runtime) ->
+    editor.addEventListener 'addnode', (node) =>
+      runtime.sendGraph 'addnode', @convertNode node.detail
+    , false
+    editor.addEventListener 'removenode', (node) =>
+      runtime.sendGraph 'removenode', @convertNode node.detail
+    , false
+    editor.addEventListener 'addedge', (edge) =>
+      runtime.sendGraph 'addedge', @convertEdge edge.detail
+    , false
+    editor.addEventListener 'removeedge', (edge) =>
+      runtime.sendGraph 'removeedge', @convertEdge edge.detail
+    , false
+    editor.addEventListener 'addinitial', (iip) =>
+      runtime.sendGraph 'addinitial', @convertInitial iip.detail
+    , false
+    editor.addEventListener 'removeinitial', (iip) =>
+      runtime.sendGraph 'removeinitial', @convertInitial iip.detail
+    , false
+    # IIP value changes need to be propagated as add+remove
+    editor.addEventListener 'iip', (iip) =>
+      runtime.sendGraph 'removeinitial', @convertInitial iip.detail
+      runtime.sendGraph 'addinitial', @convertInitial iip.detail
+    , false
+
   connect: (editor, runtime) ->
     return unless editor and runtime
-    for name, plugin of editor.plugins
-      continue unless plugin.registerRuntime
-      plugin.registerRuntime runtime
-
     runtime.on 'connected', =>
       # TODO: Read basedir from graph?
       runtime.sendComponent 'list', 'noflo-ui-preview'
-      runtime.sendGraph 'clear',
-        baseDir: 'noflo-ui-preview'
-      graph = editor.toJSON()
-      for name, definition of graph.processes
-        runtime.sendGraph 'addnode',
-          id: name
-          component: definition.component
-          metadata: definition.metadata
-      for edge in graph.connections
-        if edge.src
-          runtime.sendGraph 'addedge',
-            from:
-              node: edge.src.process
-              port: edge.src.port
-            to:
-              node: edge.tgt.process
-              port: edge.tgt.port
-          continue
-        runtime.sendGraph 'addinitial',
-          from:
-            data: edge.data
-          to:
-            node: edge.tgt.process
-            port: edge.tgt.port
+      @sendGraph runtime, editor
+      @subscribeEditor editor, runtime

     runtime.on 'component', (message) ->
       definition =


Deal with raw error objects

Deal with raw error objects

--- components/RuntimeReducer.coffee
+++ components/RuntimeReducer.coffee
@@ -126,7 +126,7 @@
         output.sendDone
           context:
             runtimeEvents: events
-        console.error data.payload.error
+        console.error data.payload
       when 'runtime:output'
         events = addRuntimeEvent data.state, data.payload.runtime, 'output', data.payload.output
         output.sendDone
@@ -140,5 +140,5 @@
           runtimeEvents: events
         output.sendDone
           context: state
-        console.error data.payload.error
+        console.error data.payload
         return


proper pluralization of point lists

proper pluralization of point lists

--- @client/franklin.coffee
+++ @client/franklin.coffee
@@ -1578,8 +1578,7 @@

     get_heading = (valence) =>
       heading = customization("point_labels.#{header_prefix}_header", @proposal)
-      singular_point = customization("point_labels.#{valence}", @proposal)
-      plural_point = customization("point_labels.#{valence.substring(0, 3)}", @proposal)
+      plural_point = customization("point_labels.#{valence}", @proposal)

       plural_point_t = translator
                         id: "point_labels.#{plural_point}"


Fack off

Fack off

--- core/app/backbone/models/fact.coffee
+++ core/app/backbone/models/fact.coffee
@@ -16,7 +16,6 @@
       indexOf = @get("containing_channel_ids").indexOf(channel.id)
       @get("containing_channel_ids").splice indexOf, 1  if indexOf
       if oldSuccess isnt `undefined`
-        console.info "hoi2"
         oldSuccess()

     $.ajax _.extend(type: "post", opts)


Call correct method

Call correct method

--- core/app/backbone/models/user.coffee
+++ core/app/backbone/models/user.coffee
@@ -58,7 +58,7 @@

   follow: ->
     user = window.currentUser.clone()
-    @followers.saveNewFollower( user )
+    @followers.addFollower( user )

   unfollow: ->
     @followers.remove(window.currentUser)


TDTabView: emit an event "TabsSorted" when the sort order changes

--- components/tabs/KDTabView.coffee
+++ components/tabs/KDTabView.coffee
@@ -112,6 +112,8 @@
     @panes.splice   newIndex, 0, splicedPane[0]

     @handles[0].setClass 'first'
+
+    @emit 'TabsSorted'

   removePane:(pane)->
     pane.emit "KDTabPaneDestroy"


Slight formatting?

Slight formatting?

--- resources/assets/coffee/react/beatmap-discussions/new-reply.coffee
+++ resources/assets/coffee/react/beatmap-discussions/new-reply.coffee
@@ -104,5 +104,6 @@
       @props.currentUser.id == @props.beatmapset.user_id ||
       @props.currentUser.id == @props.discussion.user_id

+
   validPost: ->
     @state.message.length != 0


Quote regex passed to grep

Quote regex passed to grep

--- src/app/project.coffee
+++ src/app/project.coffee
@@ -129,7 +129,7 @@

   scan: (regex, iterator) ->
     regex = new RegExp(regex.source, 'g')
-    command = "grep --null --perl-regexp --with-filename --line-number --recursive --regexp=#{regex.source} #{@getPath()}"
+    command = "grep --null --perl-regexp --with-filename --line-number --recursive --regexp=\"#{regex.source}\" #{@getPath()}"
     ChildProcess.exec command, bufferLines: true, stdout: (data) ->
       for grepLine in data.split('\n') when grepLine.length
         nullCharIndex = grepLine.indexOf('\0')


Fat arrow needed

Fat arrow needed

--- src/application.coffee
+++ src/application.coffee
@@ -59,7 +59,7 @@
     client.get "/repos/#{@repository}/deployments", params, (err, statusCode, deployments) =>
       return cb(err) if err?
       return cb(null, null) if deployments.length == 0
-      @fetchDeploymentStatuses deployments, (err, deployment) ->
+      @fetchDeploymentStatuses deployments, (err, deployment) =>
         return cb(err) if err?
         return cb(null, deployment) if deployment?
         @lastSuccessfullDeployment(env, cb, page + 1)


Only allow one update to be occurring at a time, and if another is triggered whilst one is in progress then simply schedule it for after the current one finishes.

--- src/application.coffee
+++ src/application.coffee
@@ -87,7 +87,16 @@
 	.then ->
 		start(app)

+# 0 - Idle
+# 1 - Updating
+# 2 - Update required
+currentlyUpdating = 0
 exports.update = ->
+	if currentlyUpdating isnt 0
+		# Mark an update required after the current.
+		currentlyUpdating = 2
+		return
+	currentlyUpdating = 1
 	Promise.all([
 		knex('config').select('value').where(key: 'apiKey')
 		knex('config').select('value').where(key: 'uuid')
@@ -161,3 +170,9 @@
 					knex('app').whereIn('imageId', toBeRemoved).delete()
 			)
 			Promise.all(promises)
+	.finally ->
+		if currentlyUpdating is 2
+			# If an update is required then schedule it
+			setTimeout(exports.update)
+		# Set the updating as finished
+		currentlyUpdating = 0


add reporter on receive of changeVolume message

--- client/src/app/puppet.coffee
+++ client/src/app/puppet.coffee
@@ -448,6 +448,7 @@
         reporter(null)
       when "changeVolume"
         RW.lineOut.volume = message.value
+        reporter(null)
       else
         throw new Error("Unknown type for message #{message}")
   catch error


Disable Framer 2 Compat

Disable Framer 2 Compat

--- framer/Framer.coffee
+++ framer/Framer.coffee
@@ -46,9 +46,6 @@
 Framer.DefaultContext = new Framer.Context(name:"Default")
 Framer.CurrentContext = Framer.DefaultContext

-# Compatibility for Framer 2
-require "./Compat"
-
 # Fix for mobile scrolling
 Framer.Extras.MobileScrollFix.enable() if Utils.isMobile()


And oops, also left a '\n' out.

And oops, also left a '\n' out.

--- packages/rocketchat-lib/client/MessageAction.coffee
+++ packages/rocketchat-lib/client/MessageAction.coffee
@@ -214,7 +214,7 @@
 				text += '\n'
 			text += '@' + m.u.username + ' said (' + ts + '):\n'
 			for line in message.split(/\r\n|\r|\n/)
-				text += '> ' + line
+				text += '> ' + line + '\n'
 			input.value = text
 			input.focus()
 			$(input).keyup()


ace: make sure paths are absolute

ace: make sure paths are absolute

--- client/ace/lib/ace.coffee
+++ client/ace/lib/ace.coffee
@@ -10,6 +10,8 @@
 FSHelper             = require 'app/util/fs/fshelper'
 settings             = require './settings'

+prependWithOrigin = (path) -> [location.origin, path].join '/'
+
 module.exports =

 class Ace extends KDView
@@ -25,11 +27,11 @@

   @registerStaticEmitter()

-  getscript globals.acePath, (err) ->
+  getscript prependWithOrigin(globals.acePath), (err) ->
     throw err  if err

     for k, v of globals.aceConfig
-      ace.config.set k, v
+      ace.config.set k, prependWithOrigin(v)

     ACE_READY = yes
     Ace.emit 'ScriptLoaded'
@@ -588,7 +590,8 @@
       EmmetLoadState.PENDING = yes
       emmetPath = globals.acePath.split('/').slice(0, -1)
         .concat(['_ext-emmet.js']).join('/')
-      getscript emmetPath, (err) ->
+
+      getscript prependWithOrigin(emmetPath), (err) ->
         cb err for key, cb of emmetLoadListeners when typeof cb is 'function'
         EmmetLoadState.READY = yes
         emmetLoadListeners = null


Add CI property to KONFIG object

Add CI property to KONFIG object

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

--- config/generateKonfig.coffee
+++ config/generateKonfig.coffee
@@ -270,6 +270,7 @@
     collaboration                 : { timeout: 1 * 60 * 1000 }
     client                        : { watch: yes, version: options.version, includesPath:'client' , indexMaster: 'index-master.html' , index: 'default.html' , useStaticFileServer: no , staticFilesBaseUrl: "#{options.customDomain.public}:#{options.customDomain.port}" }

+    ci  : credentials.ci
     test: credentials.test

   return KONFIG


docs(config/karma-unit.tpl): remove extra `#` from comments

Comments starting with `##` are  marked up as <h1> by *docco*, so this
change corrects that problem.

--- config/karma-unit.tpl.coffee
+++ config/karma-unit.tpl.coffee
@@ -1,9 +1,11 @@
 module.exports = (config) ->
   config.set
-    ## Where to look for files, relative to the location of this file.
+    # Where to look for files, relative to the location of this file.
     # basePath: '../'

-    ## A list of file patterns to load into the browser during testing.
+    # A list of file patterns to load into the browser during testing.
+    # **Note:** Makes assumptions about the structure of both
+    #           *`files.app.js`* and *`files.app.coffee`*.
     files: [
       <% scripts.forEach( function ( file ) { %>'<%= file %>'
       <% }); %>
@@ -39,29 +41,32 @@
         bare: true
         sourceMap: true

-    ## How to report, by default.
-    reporters: 'dots'
+    # How to report, by default.
+    reporters: [
+      'dots'
+      'coverage'
+    ]

-    ## On which port should the browser connect, on which port is the test runner
-    ## operating, and what is the URL path for the browser to use.
-    port: 9018
+    # On which port should the browser connect, on which port is the test runner
+    # operating, and what is the URL path for the browser to use.
+    port: <%= port.karma %>
     runnerPort: 9100
     urlRoot: '/'

-    ## Disable file watching by default.
+    # Disable file watching by default.
     autoWatch: false

-    ## The list of browsers to launch to test on. This includes only "Firefox" by
-    ## default, but other browser names include:
-    ## Chrome, ChromeCanary, Firefox, Opera, Safari, PhantomJS
-    ##
-    ## Note that you can also use the executable name of the browser, like "chromium"
-    ## or "firefox", but that these vary based on your operating system.
-    ##
-    ## You may also leave this blank and manually navigate your browser to
-    ## http://localhost:9018/ when you're running tests. The window/tab can be left
-    ## open and the tests will automatically occur there during the build. This has
-    ## the aesthetic advantage of not launching a browser every time you save.
+    # The list of browsers to launch to test on. This includes only "Firefox" by
+    # default, but other browser names include:
+    # Chrome, ChromeCanary, Firefox, Opera, Safari, PhantomJS
+    #
+    # Note that you can also use the executable name of the browser, like "chromium"
+    # or "firefox", but that these vary based on your operating system.
+    #
+    # You may also leave this blank and manually navigate your browser to
+    # http://localhost:9018/ when you're running tests. The window/tab can be left
+    # open and the tests will automatically occur there during the build. This has
+    # the aesthetic advantage of not launching a browser every time you save.
     browsers: [
       # 'Chrome'
       # 'Firefox'


clarified angular generator instructions

--- src/steroids/generators/resources/Angular.coffee
+++ src/steroids/generators/resources/Angular.coffee
@@ -13,10 +13,19 @@

   @usage: ()->
     """
-    Generates a stub angular resource consisting of a controller, a model, an index view and associated list/details partials.
+    Generates a stub angular resource consisting of a controller, a model, an index view and associated partials for a list and details views.
+
+    When used for the first time, the app/ folder is created with following default files
+     - app/controllers/application.js
+     - app/views/layouts/application.html

     Options:
-      - resource: name of resource to use. example: car will result in the files app/controllers/car.js, app/models/car.js and views/car/index.html (and _list.html and _details.html)
+      - resource: name of resource to use. Example: 'car' will result in the following files:
+        - app/controllers/car.js
+        - app/models/car.js
+        - app/views/car/index.html
+        - app/views/car/_list.html
+        - app/views/car/_details.html
     """

   templatePath: ->


fixed a error ref

fixed a error ref

--- src/coffee/util.coffee
+++ src/coffee/util.coffee
@@ -20,7 +20,7 @@
    * @param {function} func
    * @type boolean
   ###
-  isFunction:( fun )-> return typeof obj is "function"
+  isFunction:( func )-> return typeof func is "function"

   ###
    * @param {Object} obj


Fix typo

Fix typo

--- src/cmd/openssl.coffee
+++ src/cmd/openssl.coffee
@@ -1,5 +1,5 @@
-install = require './install
-'
+install = require './install'
+
 exports.title = 'Install OpenSSL utility'

 exports.args = install.args64


Load 3rd party modules just before running `lint()`

--- src/commandline.coffee
+++ src/commandline.coffee
@@ -247,6 +247,11 @@
         literate = CoffeeScript.helpers.isLiterate path

         fileConfig = if config then config else getFallbackConfig(path)
+
+        for ruleName, data of fileConfig
+            if data.module?
+                loadRules(data.module, ruleName)
+
         errorReport.paths[path] = coffeelint.lint(source, fileConfig, literate)
     return errorReport

@@ -254,6 +259,11 @@
 lintSource = (source, config, literate = false) ->
     errorReport = new ErrorReport()
     config or= getFallbackConfig()
+
+    for ruleName, data of config
+        if data.module?
+            loadRules(data.module, ruleName)
+
     errorReport.paths["stdin"] = coffeelint.lint(source, config, literate)
     return errorReport

@@ -360,10 +370,6 @@
         fs.existsSync(process.env.COFFEELINT_CONFIG))
             config = JSON.parse(read(process.env.COFFEELINT_CONFIG))

-    for ruleName, data of config
-        if data.module?
-            loadRules(data.module, ruleName)
-
     loadRules(options.argv.rules) if options.argv.rules

     if options.argv.s


init journal abbrev

init journal abbrev

--- content/better-bibtex.coffee
+++ content/better-bibtex.coffee
@@ -19,6 +19,7 @@
 CACHE = require('./db/cache.coffee')
 Serializer = require('./serializer.coffee')
 Citekey = require('./keymanager/get-set.coffee')
+JournalAbbrev = require('./journal-abbrev.coffee')

 ###
   MONKEY PATCHES
@@ -139,6 +140,8 @@
   yield Zotero.Schema.schemaUpdatePromise
   bench('Zotero.Schema.schemaUpdatePromise')

+  JournalAbbrev.init()
+
   flash('Zotero translators loaded', 'Better BibTeX ready for business')

   yield Translators.init()


update email text to use email variable

update email text to use email variable

--- _source/lib/emails.coffee
+++ _source/lib/emails.coffee
@@ -5,7 +5,7 @@

 Apollos.emailTemplates.resetPassword.text = (user, url) ->
   return '
-Hi, jpinkerton88@gmail.com
+Hi, ' + user.emails[0].address + '

 You told us you forgot your password. If you really did, use this link to choose a new one:


much better

much better

--- client/app/MainApp/KiteController.coffee
+++ client/app/MainApp/KiteController.coffee
@@ -130,7 +130,7 @@

     if err and response
       callback? err, response
-      warn "there were some errors parsing kite response:", err
+      warn "Command failed:", err
     else if err
       if err.code is 503
         notification = notify


conn: watch for long intervals btwn pongs, throw disconnected

--- client/app/MainApp/monitor_status.coffee
+++ client/app/MainApp/monitor_status.coffee
@@ -193,6 +193,7 @@

   brokerInterval  = null
   failureCallback = null
+  lastPong        = null

   # use broker ping to determine internet connection
   pingBrokerOnInterval = ->
@@ -200,14 +201,26 @@
       clearTimeout failureCallback
       failureCallback = null

+      brokerPong = ->
+        # account for people disconnecting at night, then reconnecting in the
+        # morning; if reconnection happens before failureCallback is trigged,
+        # we won't know that disconnection has happened.
+        if lastPong && (Date.now() - lastPong) > 50*1000
+          log "lastPong greater than 50 secs, disconnecting"
+          status = KD.singletons.status
+          status.disconnect({reason:"internetDown"})
+
+        clearTimeout failureCallback
+        failureCallback = null
+        lastPong = Date.now()
+
       failureCallback = setTimeout ->
         log 'broker ping failed, running troubleshoot', failureCallback
         KD.troubleshoot(false)
-      , 2000
-
-      KD.remote.ping ->
-        clearTimeout failureCallback
-        failureCallback = null
+      , 3000
+
+      KD.remote.ping -> brokerPong()
+
     , 5000

   KD.remote.on 'connected', ->


Do something with this data

Do something with this data

--- client/code/view/dataset/overview.coffee
+++ client/code/view/dataset/overview.coffee
@@ -14,7 +14,7 @@
       details: true
     $aboutDiv.append datasetTileView.render().el

-    $actionDiv.html '
Analyse and export this data:
'
+    $actionDiv.html '
Do something this data:
'
     viewsView = new Cu.View.DatasetViews model: @model
     $actionDiv.append viewsView.render().el
     if @model.get('views').visible().length > 0


Compact submits table (fixes #36)

Compact submits table (fixes #36)

Merge pull request #51 from DanilVolkov/submits_table

--- client/components/SubmitListTable.coffee
+++ client/components/SubmitListTable.coffee
@@ -9,6 +9,24 @@
 import outcomeToText from '../lib/outcomeToText'

 import styles from './SubmitListTable.css'
+
+LANGUAGE_ABBREVIATED =
+    "Python 3" : "Py3"
+    "Free Pascal 3" : "FreePas"
+    "PascalABC 3" : "PasABC"
+    "GNU C++" : "C++"
+    "GNU C" : "C"
+    "Borland Delphi" : "Delphi"
+    "Java JDK" : "Java"
+    "PHP": "PHP"
+    "Python 2" : "Py2"
+    "Perl" : "Perl"
+    "Mono C#" : "C#"
+    "Ruby" : "Ruby"
+    "Haskell GHC" : "Haskell"
+    "FreeBASIC" : "FreeBASIC"
+    "GNU C++ / sanitizer" : "C++/sanitizer"
+

 maxVal = (submit, field) ->
     res = -1
@@ -26,8 +44,8 @@
                     Время попытки
                     Результат
                     Язык
-                    Время
-                    Память
+                    Время
+                    Память

                     {if props.handleDiffClick
@@ -41,15 +59,19 @@
                     if submit._id == props.activeId
                         cl += " " + styles.active
                     time = maxVal(submit, "time")
-                    mem = maxVal(submit, "max_memory_used")
-

-                        {moment(submit.time).format('YYYY-MM-DD HH:mm:ss')}
+                    mem = (maxVal(submit, "max_memory_used")) / (1024*1024)
+                    mem = mem.toFixed(2)
+

+                        {moment(submit.time).format('DD.MM.YY HH:mm:ss')}
                         {message}
-                        {submit.language}
-                        {if time? then time / 1000 else ""}
-                        {mem || ""}
+
+
{LANGUAGE_ABBREVIATED[submit.language]}

+
{submit.language}

+
+                        {if time? then time / 1000 else ""}
+                        {if mem >= 0 then mem else ""}
                         {submit.comments?.length && <FontAwesome name="comment"/> || ""}
-                        Подробнее
+                        <FontAwesome name="eye"/>
                         {if props.handleDiffClick


Reduced loops, highlight moved to last

Reduced loops, highlight moved to last

--- client/highlight.coffee
+++ client/highlight.coffee
@@ -29,12 +29,6 @@
             el.innerHTML = ''
             el.appendChild code

-        # 呼叫 HightlightJS 來將剛才脫逸的 <code> 區塊全部上色。
-        hljs.initHighlighting.called = false
-        hljs.initHighlighting()
-
-        # 將 <code> 裡面的 [[]] 和 {{}} 與 !--! 標籤替換掉。
-        document.querySelectorAll('[html-code], [js-code], [css-code]').forEach (el) ->
             # 標記程式碼。 - [[segment]]
             el.innerHTML = el.innerHTML.replace /\[\[(.*?)\]\]/g, '<mark>$1</mark>'

@@ -72,4 +66,8 @@
                     when 'user3'       then 'user.png'
                     when 'embed:karen' then 'youtube.png'
                     when 'embed:vimeo' then 'vimeo.png'
+
+        # 呼叫 HightlightJS 來將剛才脫逸的 <code> 區塊全部上色。
+        hljs.initHighlighting.called = false
+        hljs.initHighlighting()
     , 1


blocks collection uses base collection

blocks collection uses base collection

--- collections/blocks.coffee
+++ collections/blocks.coffee
@@ -2,11 +2,11 @@
 # General collection for a group of Blocks
 #

-Backbone = require("backbone")
+Base = require("./base.coffee")
 sd = require("sharify").data
 Commit = require("../models/block.coffee")

-module.exports = class Blocks extends Backbone.Collection
+module.exports = class Blocks extends Base

   model: Block


Fixed legacy

Fixed legacy

--- test/knockback/collection-observable/test.coffee
+++ test/knockback/collection-observable/test.coffee
@@ -733,33 +733,37 @@
     class PersonViewModel extends kb.ViewModel
     collection_observable = kb.collectionObservable(new kb.ContactsCollection(), {view_model: PersonViewModel})

-    collection_observable.collection().push()
-    assert.equal(collection_observable.collection().length, 0)
-    assert.equal(collection_observable().length, 0)
-    collection_observable.collection().push(null)
-    assert.equal(collection_observable.collection().length, 0)
-    assert.equal(collection_observable().length, 0)
-    collection_observable.collection().push(new kb.Contact())
-    assert.equal(collection_observable.collection().length, 1)
-    assert.equal(collection_observable().length, 1)
-    collection_observable.collection().reset()
-    assert.equal(collection_observable.collection().length, 0)
-    assert.equal(collection_observable().length, 0)
-
-    collection_observable.collection().unshift()
-    assert.equal(collection_observable.collection().length, 0)
-    assert.equal(collection_observable().length, 0)
-    collection_observable.collection().unshift(null)
-    assert.equal(collection_observable.collection().length, 0)
-    assert.equal(collection_observable().length, 0)
-    collection_observable.collection().unshift(new kb.Contact())
-    assert.equal(collection_observable.collection().length, 1)
-    assert.equal(collection_observable().length, 1)
-    collection_observable.collection().reset()
-    assert.equal(collection_observable.collection().length, 0)
-    assert.equal(collection_observable().length, 0)
-
-    kb.release(collection_observable)
-
-    assert.equal(kb.statistics.registeredStatsString('all released'), 'all released', "Cleanup: stats"); kb.statistics = null
-    done()
+    # LEGACY
+    if collection_observable.collection().push
+      collection_observable.collection().push()
+      assert.equal(collection_observable.collection().length, 0)
+      assert.equal(collection_observable().length, 0)
+      collection_observable.collection().push(null)
+      assert.equal(collection_observable.collection().length, 0)
+      assert.equal(collection_observable().length, 0)
+      collection_observable.collection().push(new kb.Contact())
+      assert.equal(collection_observable.collection().length, 1)
+      assert.equal(collection_observable().length, 1)
+      collection_observable.collection().reset()
+      assert.equal(collection_observable.collection().length, 0)
+      assert.equal(collection_observable().length, 0)
+
+    # LEGACY
+    if collection_observable.collection().unshift
+      collection_observable.collection().unshift()
+      assert.equal(collection_observable.collection().length, 0)
+      assert.equal(collection_observable().length, 0)
+      collection_observable.collection().unshift(null)
+      assert.equal(collection_observable.collection().length, 0)
+      assert.equal(collection_observable().length, 0)
+      collection_observable.collection().unshift(new kb.Contact())
+      assert.equal(collection_observable.collection().length, 1)
+      assert.equal(collection_observable().length, 1)
+      collection_observable.collection().reset()
+      assert.equal(collection_observable.collection().length, 0)
+      assert.equal(collection_observable().length, 0)
+
+    kb.release(collection_observable)
+
+    assert.equal(kb.statistics.registeredStatsString('all released'), 'all released', "Cleanup: stats"); kb.statistics = null
+    done()


ENHANCE: Update labels for bullet chart

ENHANCE: Update labels for bullet chart

--- src/app/visualisations/partials/directives/alignment-bullet-chart.coffee
+++ src/app/visualisations/partials/directives/alignment-bullet-chart.coffee
@@ -119,7 +119,7 @@
                 .on('mouseover', ->
                   dispatch.elementMouseover
                     value: measurez.median
-                    label: 'Class Median'
+                    label: 'The most average student is here'
                     color: d3.select(this).style('fill')
                   return)
                 .on('mousemove', ->
@@ -565,9 +565,9 @@
       "ranges":[targetP,targetC,targetD,targetHD],  #Minimum, mean and maximum values.
       "rangeLabels":['Pass','Credit','Distinction','High Distinction'],  #Minimum, mean and maximum values.
       "measures": {},    #Value representing current measurement (the thick blue line in the example)
-      "measureLabels": ['Most of Class is in this range']
+      "measureLabels": ['Most of the class are in this area']
       "markers":[]      #Place a marker on the chart (the white triangle marker)
-      "markerLabels": ['Your Progress - Staff Suggestion', 'Your Progress - Self Reflection']
+      "markerLabels": ['Your Suggested Progress - Staff Suggestion', 'Your Current Progress - Self Reflection']
     }

     if $scope.classStats? && $scope.classStats.title?
@@ -589,4 +589,4 @@

       if $scope.api
         $scope.api.update()
-    )+    )


Update logger transport for winston 0.7

Update logger transport for winston 0.7

--- src/core/logger.coffee
+++ src/core/logger.coffee
@@ -31,7 +31,7 @@
       if level isnt 'info'
         c = if level is 'warn' then 'yellow' else 'grey'
         msg = "#{ level[c] } #{ msg }"
-      if meta
+      if Object.keys(meta).length > 0
         msg += util.format ' %j', meta
       process.stdout.write "  #{ msg }\n"


Don't watch ignored files in preview

Don't watch ignored files in preview

--- src/core/server.coffee
+++ src/core/server.coffee
@@ -6,6 +6,7 @@
 http = require 'http'
 mime = require 'mime'
 url = require 'url'
+minimatch = require 'minimatch'
 enableDestroy = require 'server-destroy'
 {Stream} = require 'stream'

@@ -114,6 +115,12 @@
       callback error

   contentWatcher = chokidar.watch env.contentsPath,
+    ignored: (path) ->
+      for pattern in env.config.ignore
+        if minimatch env.relativeContentsPath(path), pattern
+          console.log 'ignore', path
+          return true
+      return false
     ignoreInitial: true
   contentWatcher.on 'change', (path) ->
     return if not contents? or block.contentsLoad


namespace access on plugin

namespace access on plugin

--- src/core/studio.coffee
+++ src/core/studio.coffee
@@ -16,6 +16,6 @@
         onCreateDriver:(listener)-> require('./util/listeners').addOnCreateDriver(listener)
         onDestroyDriver:(listener)-> require('./util/listeners').addOnDestroyDriver(listener)
       }
-    })
+    },Studio)
 }
 module.exports=Studio


Core#send

Core#send

--- src/core_object.coffee
+++ src/core_object.coffee
@@ -155,6 +155,6 @@
         self.extend Module(I, self)

       return self
-
+
     send: (name, args...) ->
       self[name](args...)


detect winner

detect winner

--- coffee/ttp-logic.coffee
+++ coffee/ttp-logic.coffee
@@ -5,13 +5,20 @@

 brd = board boardRows, boardCols

+winningTriples = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
+
 $ ->
   turn = 0; $('#turn').text 'O'
   $ '#mainBoard'
     .append brd.map((cell) -> "

#{cell}

").join ''
     .on 'click', '.cell', ->
       if !$(@).hasClass('circle') && !$(@).hasClass('cross')
-        $(@).addClass ['circle', 'cross'][turn]
+        $(@).addClass myClass = ['circle', 'cross'][turn]
+        $s = $(@).parent().children() # siblings, including self
+        for t in winningTriples
+          if $s.eq(t[0]).hasClass(myClass) && $s.eq(t[1]).hasClass(myClass) && $s.eq(t[2]).hasClass(myClass)
+            alert 'OX'[turn] + ' wins'
+            break
         turn = 1 - turn; $('#turn').text 'OX'[turn]
       return
   return


Fix broken StateFieldPickerSpec

Fix broken StateFieldPickerSpec

--- test/spec/charts/settings/StateFieldPickerSpec.coffee
+++ test/spec/charts/settings/StateFieldPickerSpec.coffee
@@ -39,13 +39,16 @@
           Ext.merge(args,args.requester)
           args.callback([ me.allowedValue("V1"), me.allowedValue("V2") ])

+      getType = ->
+        @attributeDefinition.AttributeType.toLowerCase()
+
       # I'm not convinced this is the appropriate way to do this, but it definitely works although it also
       # requires some magic (above)
       @stub Rally.data.wsapi.Model, "getFields", ->
         [
-          { name: "c_KanbanState", displayName: "Kanban State", attributeDefinition: { AttributeType: "STRING", hidden: false, ReadOnly: false, Constrained: true }, getAllowedValueStore}
-          { name: "ScheduleState", displayName: "Schedule State", attributeDefinition: { AttributeType: "STRING", hidden: false, ReadOnly: false, Constrained: true }, getAllowedValueStore}
-          { name: "TaskEstimateTotal", displayName: "Task Estimate Total", attributeDefinition: { AttributeType: "DOUBLE", hidden: false, ReadOnly: true, Constrained: false }, getAllowedValueStore}
+          { name: "c_KanbanState", displayName: "Kanban State", attributeDefinition: { AttributeType: "STRING", hidden: false, ReadOnly: false, Constrained: true }, getAllowedValueStore, getType}
+          { name: "ScheduleState", displayName: "Schedule State", attributeDefinition: { AttributeType: "STRING", hidden: false, ReadOnly: false, Constrained: true }, getAllowedValueStore, getType}
+          { name: "TaskEstimateTotal", displayName: "Task Estimate Total", attributeDefinition: { AttributeType: "DOUBLE", hidden: false, ReadOnly: true, Constrained: false }, getAllowedValueStore, getType}
         ]


add todo for later

add todo for later

--- src/node_modules/round-contributors/round-contributors-controller.coffee
+++ src/node_modules/round-contributors/round-contributors-controller.coffee
@@ -44,6 +44,7 @@
   $scope.onUpload = (files) ->
   $scope.onSuccess = (response) ->
     debug("upload success", response)
+    # TODO display success in alerts (see group-members)
     $state.reload('layout')
   $scope.onError = (response) ->
     debug("upload error", response)


Don't emit an empty class attribute when the element name does not include any embedded class names

--- tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee
+++ tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee
@@ -56,7 +56,8 @@

     element = document.createElement elementName

-    element.className = terms.join " "
+    if terms.length
+      element.className = terms.join " "

     return element


:racehorse: Specify package name

:racehorse: Specify package name

This cuts out a potential source of delay during package activation.

--- init.coffee
+++ init.coffee
@@ -39,7 +39,7 @@
       default: '-min_confidence=0.8'

   activate: ->
-    require('atom-package-deps').install()
+    require('atom-package-deps').install('linter-golinter')

     linterName = 'linter-golinter'


Fixed bundle loading.

Fixed bundle loading.


make compiler health check available on web

--- services/web/app/coffee/router.coffee
+++ services/web/app/coffee/router.coffee
@@ -276,7 +276,7 @@
 		apiRouter.get '/health_check', HealthCheckController.check
 		apiRouter.get '/health_check/redis', HealthCheckController.checkRedis

-		apiRouter.get "/status/compiler/:Project_id", AuthorizationMiddlewear.ensureUserCanReadProject, (req, res) ->
+		webRouter.get "/status/compiler/:Project_id", AuthorizationMiddlewear.ensureUserCanReadProject, (req, res) ->
 			project_id = req.params.Project_id
 			sendRes = _.once (statusCode, message)->
 				res.status statusCode


clarify errors for subscribe/unsubscribe

--- services/real-time/app/coffee/ChannelManager.coffee
+++ services/real-time/app/coffee/ChannelManager.coffee
@@ -16,9 +16,9 @@
         existingChannelSet = ClientMap.get(rclient) || @_createNewClientEntry(rclient)
         channel = "#{baseChannel}:#{id}"
         if existingChannelSet.has(channel)
-            logger.error {channel}, "already subscribed"
+            logger.error {channel}, "already subscribed - shouldn't happen"
         else
-            rclient.subscribe channel
+            rclient.subscribe channel # completes in the background
             existingChannelSet.add(channel)
             logger.log {channel}, "subscribed to new channel"
             metrics.inc "subscribe.#{baseChannel}"
@@ -27,9 +27,9 @@
         existingChannelSet = ClientMap.get(rclient)
         channel = "#{baseChannel}:#{id}"
         if !existingChannelSet.has(channel)
-            logger.error {channel}, "not subscribed, cannot unsubscribe"
+            logger.error {channel}, "not subscribed - shouldn't happen"
         else
-            rclient.unsubscribe channel
+            rclient.unsubscribe channel # completes in the background
             existingChannelSet.delete(channel)
             logger.log {channel}, "unsubscribed from channel"
             metrics.inc "unsubscribe.#{baseChannel}"


add type to register

add type to register

--- command-register.coffee
+++ command-register.coffee
@@ -10,6 +10,7 @@
   parseOptions: =>
     commander
       .option '-s, --server <host[:port]>', 'Meshblu host'
+      .option '-t, --type <device:type>', 'Device type'
       .parse process.argv

   parseConfig: =>
@@ -23,7 +24,7 @@

     {hostname, port} = url.parse server
     port ?= 80
-    {server: hostname, port: port}
+    {server: hostname, port: port, type: commander.type}

   run: =>
     @parseOptions()
@@ -33,7 +34,7 @@
     @conn.on 'notReady', @onReady

   onReady: (credentials) =>
-    @conn.register {}, (credentials) =>
+    @conn.register {type: @config.type}, (credentials) =>
       @config.uuid = credentials.uuid
       @config.token = credentials.token
       console.log JSON.stringify(@config, null, 2)


show time since tweet

show time since tweet

--- commands/twitter.coffee
+++ commands/twitter.coffee
@@ -5,6 +5,23 @@
 ###
 Twitter search
 ###
+
+`
+function relativeTime(dat){
+	var s = ~~( (+new Date-Date.parse(dat)) / 1000 );
+	// unidade de tempo
+	var un = (s<60) ? 'second'
+		: (s /= 60)<60 ? 'minute'
+		: (s /= 60)<24 ? 'hour'
+		: (s /= 24)<30.4 ? 'day'
+		: (s /= 30.4)<365 ? 'month'
+		: 'ano';
+	s = Math.floor(s);
+	un += (s>1 || s == 0) ? 's' : '';
+
+	  return s + ' ' + un + ' ago';
+};
+`

 twitterSearch = (query, respond) ->

@@ -21,7 +38,8 @@

         if data.results
             for tweet in data.results
-                message += "#{tweet.from_user}: #{decode tweet.text}\n"
+                created = tweet.created_at
+                message += "#{tweet.from_user}: #{decode tweet.text} (#{relativeTime created})\n"
         else
             message = "I'm sorry, nothing found for '#{query}' on twitter."

@@ -36,3 +54,4 @@
         /search\stwitter(?:\sfor)?\s(.+)/i
     ]
     fn: (user, m, cb) -> twitterSearch m[1], cb
+


add

add

add comment

--- gulp/tasks/js.coffee
+++ gulp/tasks/js.coffee
@@ -16,6 +16,8 @@
 watchify     = require 'watchify'
 handleErrors = require '../util/handleErrors.js'

+
+# webpack
 gulp.task "js", ()->
   gulp.src config.js.src+'main.js'
   .pipe $.plumber
@@ -28,7 +30,7 @@
   .on "end" , browserSync.reload

-
+# browserify
 opts = {
         entries: './'+config.js.src+'/main.js'
         transform: [ 'babelify' ]


progress on token switches

progress on token switches

--- handlers/thread.iced
+++ handlers/thread.iced
@@ -10,7 +10,7 @@
 {checkers,arr_subchecker} = require 'keybase-bjson-core'
 {make_esc}                = require 'iced-error'
 {unix_time}               = require('iced-utils').util
-idcheckers            = require('keybase-messenger-core').id.checkers
+idcheckers                = require('keybase-messenger-core').id.checkers

 #=============================================================================

@@ -82,11 +82,32 @@

 class UpdateWriteTokenHandler extends Handler

+  #--------------------
+
   input_template : -> {
-    i : checkers.buffer
+    i : idcheckers.thread()
+    user_zid : checkers.intval(0)
+    old_token : idcheckers.write_token()
+    new_token : idcheckers.write_token()
+  }

+  #--------------------

-  }
+  write : (cb) ->
+    q = """UPDATE thread_keys
+           SET write_key=?
+           WHERE thread_id=?
+           AND user_zid=?
+           AND write_key=?"""
+    args = [ H(@input.new_token), H(@input.i), @input.user_zid, H(@input.old_token)]
+    await mm.db.update1 q, args, defer err
+    cb err
+
+  #--------------------
+
+  _handle : (cb) ->
+    await @write defer err
+    cb err

 #=============================================================================


Tweak _selectOneRow error messages

Tweak _selectOneRow error messages

--- src/db/database.coffee
+++ src/db/database.coffee
@@ -31,15 +31,13 @@
             onAllRows: (rows) ->
                 if rows.length == 0
                     if !allowEmpty
-                        e  = "Expected query #{query} to return 1 row, " +
-                             "but it returned 0 rows."
+                        e  = "No data returned for query #{query}. Expected 1 row"
                         return cb(e)
                     else
                         return cb(null, null)

                 if (rows.length != 1)
-                    e = "Expected query #{query} to return 1 row, " +
-                        "but it returned #{rows.length} rows."
+                    e = "Too many rows returned for query #{query}. Expected 1 row but got #{rows.length}"
                     return cb(e)

                 v = (if rowShape == 'array' then rows[0][0] else rows[0])


Extract Default Modules

Extract Default Modules

--- src/game_object.coffee
+++ src/game_object.coffee
@@ -160,7 +160,9 @@
   "Bindable"
   "Ageable"
   "Bounded"
-  "Clampable", Cooldown, Drawable, Expirable, Follow, Metered, Movable, Rotatable, TimedEvents, Tween]
+  "Clampable"
+  "Cooldown"
+  "Drawable", Expirable, Follow, Metered, Movable, Rotatable, TimedEvents, Tween]

 ###*
 Construct an object instance from the given entity data.


bugfixing issues with the Coffeescript condensed MetricPrototype factory, comparing against working versions of the app to figure out what's failing. Getting close but still not quite there.

--- app/assets/javascripts/angular/factories/MetricPrototypeFactory.js.coffee
+++ app/assets/javascripts/angular/factories/MetricPrototypeFactory.js.coffee
@@ -4,12 +4,9 @@
       @$scope = $scope
       @tiers = []
       @badges = {}
-      # @availableBadges = angular.copy($scope.courseBadges)
-      # @selectedBadge = ""
       @id = if attrs.id then attrs.id else null
       @fullCreditTier = null
       @addTiers(attrs["tiers"]) if attrs["tiers"] #add tiers if passed on init
-      # @loadMetricBadges(attrs["metric_badges"]) if attrs["metric_badges"] #add badges if passed on init
       @name = if attrs.name then attrs.name else ""
       @rubricId = if attrs.rubric_id then attrs.rubric_id else @$scope.rubricId
       if @id
@@ -23,9 +20,11 @@
       ## graderubric
       @selectedTier = null

-      if $scope.rubricGrades
-        @rubricGrade = $scope.rubricGrades[@id]
+      # look for a rubric grade by metric_id if there are rubric grades present
+      if @$scope.rubricGrades
+        @rubricGrade = @$scope.rubricGrades[@id]

+      # if there are rubric grades, select the
       if @rubricGrade
         @rubricGradeTierId = @rubricGrade.tier_id
       else
@@ -38,30 +37,13 @@

       # alert(@selectedTier.id)
       # would this always have an id?
-      #@max_points = if attrs.max_points then attrs.max_points else 0
     alert: ()->
       alert("snakes!")
     addTier: (attrs={})->
       newTier = new TierPrototype(@, attrs, @$scope)
       @tiers.push newTier
       if @rubricGradeTierId and @rubricGradeTierId == newTier.id
-        # alert(self.rubricGradeTierId)
-        # alert(newTier.id)
         @selectedTier = newTier
-    #what is different here? // from GradeRubric
-      # addTier: (attrs={})->
-      #   self = this
-      #   newTier = new TierPrototype(self, attrs, $scope)
-      #   @tiers.splice(-1, 0, newTier)
-      # loadTier: (attrs={})->
-      #   self = this
-      #   newTier = new TierPrototype(self, attrs, $scope)
-      #   @tiers.push newTier
-      # addTiers: (tiers)->
-      #   self = this
-      #   angular.forEach(tiers, (tier,index)->
-      #     self.loadTier(tier)
-      #   )

     addTiers: (tiers)->
       angular.forEach(tiers, (tier,index)=>
@@ -195,4 +177,4 @@
           )
       else
         @remove(index)
-]  +]


bubbles: legend improved

bubbles: legend improved

--- app/charts/bubbles.coffee
+++ app/charts/bubbles.coffee
@@ -160,7 +160,7 @@

   updateLegend = (selection, maxTotalMagnitude) ->
-    legendMargin = {top: 60, right: 2, bottom: 10, left: 2}
+    legendMargin = {top: 85, right: 2, bottom: 10, left: 2}

     maxR = rscale.range()[1]  # rscale(pow10(maxOrd))
     legend = selection.select("svg.legend")
@@ -346,6 +346,18 @@
         colors = legend.append("g")
           .attr("class", "colors")

+        legend.append("text")
+          .attr("x", "70")
+          .attr("y", "15")
+          .attr("text-anchor", "middle")
+          .text("Aid commitment amount")
+
+        legend.append("text")
+          .attr("x", "70")
+          .attr("y", "28")
+          .attr("text-anchor", "middle")
+          .text("US$ constant (2009)")
+
         legend.append("g").attr("class", "outer")

         itemEnter = colors.selectAll("g.item")
@@ -353,20 +365,21 @@
           .enter()
         .append("g")
           .attr("class", "item")
-          .attr("transform", (d,i) -> "translate(0, #{i*15})")
+          .attr("transform", (d,i) -> "translate(42, #{40 + i*15})")

         itemEnter.append("rect")
-          .attr("x", "28")
+          .attr("x", "0")
           .attr("y", "0")
           .attr("width", "15")
           .attr("height", "11")
           .attr("fill", (d) -> d.color)

         itemEnter.append("text")
-          .attr("x", "47")
+          .attr("x", "19")
           .attr("y", "5")
           .attr("alignment-baseline", "central")
           .text((d) -> d.name)
+


Swapping `exchange` and `exchange-alt`, cleanup

They were swapped to realign them with `curve`

--- src/js/Renderer.coffee
+++ src/js/Renderer.coffee
@@ -47,7 +47,7 @@

   setupTextures: (textureFile) ->
     textureOffset = 0
-    for textureGroup, textureDescription of Renderer.SupportedTextures
+    for textureGroup, textureDescription of Renderer.TextureFileDescription
       for texture, rotationsCount of textureDescription
         console.log "loading #{textureGroup}.#{texture}" if DEBUG

@@ -80,15 +80,16 @@
   # Relative to the point of origin of the canvas
   renderingCoordinatesForBlock: (x,y,z) ->
     screenX = (x + y) * @settings.blockSizeHalf
-    screenY = @settings.canvasHeight - 3 * @settings.blockSizeQuarter - (2 * z + x - y + @map.size) * @settings.blockSizeQuarter
+    screenY = @settings.canvasHeight \
+              - 3 * @settings.blockSizeQuarter \
+              - (2 * z + x - y + @map.size) * @settings.blockSizeQuarter

     [screenX, screenY]

-  # Returns either 'top', 'south', 'east' or null depending on what side
-  # of a block (if any) is displayed at the given coordinates
+  # Returns either 'top', 'south', 'east', 'floor' or null depending on what
+  # side  of a block (if any) is displayed at the given coordinates
   sideAtScreenCoordinates: (x, y) ->
     pixel = @hittestContext.getImageData x, y, 1, 1
-
     if pixel.data[0] > 0
       return 'south'
     else if pixel.data[1] > 0
@@ -143,13 +144,13 @@

   getTexture: (group, type, rotation) ->
     unless rotation
-      return @textures[group][type][0] if Renderer.SupportedTextures[group][type]?
-
-    rotationCount = Renderer.SupportedTextures[group][type]
+      return @textures[group][type][0] if Renderer.TextureFileDescription[group][type]?
+
+    rotationCount = Renderer.TextureFileDescription[group][type]
     return null unless rotationCount?
     return @textures[group][type][rotation / 90 % rotationCount]

-  drawMap: (force) ->
+  drawMap: (force = no) ->
     return if (@isDrawing or not @map.needsRedraw) and not force
     console.time "draw" if DEBUG
     @isDrawing = yes
@@ -281,7 +282,7 @@
     for block, index in stack
       @drawBlock @draggedContext, block, 0, height - @settings.blockSize - (index) * @settings.blockSizeHalf

-  @SupportedTextures:
+  @TextureFileDescription:
     #texture group:
     #  name: number of rotations/variations
     'basic':
@@ -314,8 +315,8 @@
       'dive':            4
       'drop-middle':     4
       'drop-low':        4
+      'exchange-alt':    4
       'exchange':        4
-      'exchange-alt':    4
     'low':
       'crossing':        1
       'curve':           4
@@ -332,11 +333,11 @@
     'straight':          [0, 180]
     'dive':                 [  0]
     'drop-middle':          [  0]
-    'exchange':             [ 90]
-    'exchange-alt':         [  0]
+    'exchange':             [  0]
+    'exchange-alt':         [ 90]

   @LowHoles:
     'dive':                 [180]
     'drop-low':             [  0]
-    'exchange':             [  0]
-    'exchange-alt':         [ 90]
+    'exchange':             [ 90]
+    'exchange-alt':         [  0]


focus on canvas expansion

focus on canvas expansion

--- content/gitoe-draw.coffee
+++ content/gitoe-draw.coffee
@@ -97,7 +97,6 @@
     setTimeout( @draw.bind(@,sha1,layer,pos),0 )

   # TODO
-  # focus: (sha1)->
   # ref_on_commit: (ref)
   # ref_on_ref:    (ref1, ref2)
   add_commit: (commit)->
@@ -132,10 +131,7 @@
       @canvas_inc_height()
       scroll = true
     if scroll
-      @div.scrollTo {
-        left: group_pos.left - 200
-        top: group_pos.top - 200
-      }
+      @focus( layer, pos )
     group = new fabric.Group([], group_pos)

   draw_commit: (sha1)->
@@ -164,6 +160,12 @@
         paths.push(new fabric.Line coords, @constant.path_style)
     paths

+  focus: (layer,pos)->
+    @div.scrollTo {
+      left : -200 + @constant.padding_left + pos * @constant.outer_width
+      top  : -200 + @constant.padding_top  + layer * @constant.outer_height
+    }
+
   destroy: (sha1)->
     # TODO remove sha1's related fabric objects

@@ -181,11 +183,12 @@
     @canvas = canvas

   canvas_inc_width: ()->
-    console.log 'inc width'
-    @canvas.setWidth  @canvas_width *= 1.2
+    @canvas_width *= 1.2
+    @canvas.setWidth @canvas_width
   canvas_inc_height: ()->
-    console.log 'inc height'
-    @canvas.setHeight @canvas_height *= 1.2
+    @canvas_height *= 1.2
+    @canvas.setHeight @canvas_height
+
   freeze: (fabric_obj)->
     attrs = [
       'lockMovementX'


remove title keyup

remove title keyup

--- app/scripts/editor.coffee
+++ app/scripts/editor.coffee
@@ -199,7 +199,6 @@
 				e.preventDefault()
 				e.stopPropagation()
 	handleTitleKeyUp: (e)->
-		console.log 'title keyup'
 	handleKeyDown: (e)->
 		# debug
 		$('#debug-keydown').text e.keyCode


only change route when valid

only change route when valid

--- app/scripts/router.coffee
+++ app/scripts/router.coffee
@@ -53,13 +53,15 @@

         # go to the route page by default
         $(window).load (e) ->
-            router.go '/', @title
-            router.run.apply router
+#            router.go '/', @title
+            router.run.call router, '/'

         @context_selector.on 'click', @state_changers_selector, (e)->
+            e.preventDefault();
             console.log(e);
-            router.go @href, @title
-            router.run.apply router
+#            router.go @href, @title
+            href = $(@).attr("href")
+            router.run.call router, href, e.type

         # Create an anonymous function to call the router.run method so we can
         # pass the router as "this" variable
@@ -81,15 +83,15 @@
     rootRegister: (template, callback) ->
         @register('', template, callback)

-    run: ->
-        uri = window.location.pathname
-
+    run: (uri, event) ->
+#        uri = window.location.pathname
+        console.log(uri);
         for action in @actions
             for route in action.route
                 regex = (@pathRegExp route, {}).regexp
                 match = uri.match(regex)
-                console.log(route, uri)
                 if match?
+                    @go uri
                     match.shift()
                     return action.call(match...)