* inspect() to identify the non-loaded folder

--- src/index.coffee
+++ src/index.coffee
@@ -95,10 +95,8 @@
   #_validate: (file)-> file.hasOwnProperty('contents') and file.contents?
   inspect: ->
     name = 'File'
-    if @loaded()
-      name = 'Folder' if @isDirectory()
-    else
-      name += '?'
+    name = 'Folder' if @isDirectory()
+    name += '?' unless @loaded()
     '<'+ name + ' ' + @_inspect() + '>'

   isDirectory: ->


Stub out the frontend commands.

Stub out the frontend commands.

--- src/index.coffee
+++ src/index.coffee
@@ -1,22 +1,24 @@
 # Description:
-#   Say Hi to Hubot.
+#   Challenge
 #
 # Dependencies:
 #   None
 #
 # Configuration:
-#   None
+#   HUBOT_HAMMERSPORT_ROOMS - comma-separated list of rooms to restrict hammersport chatter to.
+#   HUBOT_HAMMERSPORT_ATTACKS - path to a file containing available attacks.
 #
 # Commands:
-#   hubot hello - "hello!"
-#   hubot orly - "yarly"
+#   hubot hammersport challenge <user> - Challenge another user to a duel
+#   hubot hammersport accept - Accept a challenge.
+#   hubot hammersport decline - Decline a challenge.
+#   hubot hammer <n> - Choose an attack during a hammersport round.
 #
 # Author:
-#   tombell
+#   smashwilson

 module.exports = (robot) ->
-  robot.respond /hello/, (msg) ->
-    msg.reply "hello!"

-  robot.hear /orly/, ->
-    msg.send "yarly"
+  robot.respond /hammersport challenge (\S+)/i, (msg) ->
+
+  robot.respond /hammer (\d)/i, (msg) ->


everywhere updates when one user updates

--- src/index.coffee
+++ src/index.coffee
@@ -104,6 +104,7 @@
           socket.emit "get:house:ack", err
         else
           socket.emit "get:house:ack", houses
+          socket.broadcast.emit "get:house:ack", houses


participants/collab: fix ordering mechanism

--- client/activity/lib/models/collaborationchannelparticipants.coffee
+++ client/activity/lib/models/collaborationchannelparticipants.coffee
@@ -1,14 +1,14 @@
 _                        = require 'lodash'
 ChannelParticipantsModel = require './channelparticipants'
+videoConstants = require 'app/videocollaboration/constants'

 module.exports = class CollaborationChannelParticipantsModel extends ChannelParticipantsModel

   defaultState:
-    videoActive           : no
-    selectedParticipant   : null
-    talkingParticipants   : []
-    videoParticipants     : []
-    connectedParticipants : []
+    videoActive         : no
+    selectedParticipant : null
+    talkingParticipants : []
+    videoParticipants   : []

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

@@ -234,7 +234,7 @@

 ###*
- * Orders given state's connected participants in a way that publishing users
+ * Orders given state's video participants in a way that publishing users
  * come first.
  *
  * @param {object} state
@@ -244,14 +244,15 @@
 ###
 getOrderedVideoParticipants = (state) ->

-  actives = state.videoParticipants
-
-  # connectedParticipants has already have the active participant ids.
-  # that's why we are diff'ing to get actives b
-  connecteds = _.difference state.connectedParticipants, state.videoParticipants
-
-  # all the diffing and other stuff is for showing video active
-  # participants first and not publishing but connected people after those.
-  filterList = actives.concat connecteds
-
-
+  participants = state.videoParticipants
+  { PARTICIPANT_STATUS_PUBLISHING } = videoConstants
+
+  # _.partition returns 2 arrays from 1. First array will be result of given
+  # predicate function, 2nd array will be the remaining elements of original
+  # array.
+  [publishings, nonpublishings] = _.partition participants, (p) ->
+    p.status is PARTICIPANT_STATUS_PUBLISHING
+
+  filterList = publishings.concat nonpublishings
+
+


removed old crap

removed old crap

--- client/landing/app/CommonViews/comments/commentlistitemview.coffee
+++ client/landing/app/CommonViews/comments/commentlistitemview.coffee
@@ -57,12 +57,8 @@

   render:->
     if @getData().getAt 'deletedAt'
-      @setClass "deleted"
-      if @deleter
-        @setTemplate "
{{> @author}}'s comment has been deleted by {{> @deleter}}.
"
-      else
-        @setTemplate "
{{> @author}}'s comment has been deleted.
"
       @emit 'CommentIsDeleted'
+    @setTemplate @pistachio()
     super

   viewAppended:->
@@ -99,8 +95,18 @@
                 type     : "mini"
                 cssClass : "error editor"
                 title     : "Error, please try again later!"
-
+        # cancel       :
+        #   style      : "modal-cancel"
+        #   callback   : => modal.destroy()
+
   pistachio:->
+    if @getData().getAt 'deletedAt'
+      @setClass "deleted"
+      if @deleter
+        "
{{> @author}}'s comment has been deleted by {{> @deleter}}.
"
+      else
+        "
{{> @author}}'s comment has been deleted.
"
+    else
       """

         {{> @avatar}}
@@ -114,45 +120,3 @@

       """
-
-  # updatePartial:->
-  #   data = @getData()
-  #   # return unless 'object' is typeof data # TODO: hack
-  #   super
-  #   @_partialUpdated = yes
-  #
-  #   title = new Date(data.meta.createdAt).format 'h:MM TT ""mmm d, yyyy""'
-  #   @$('time').twipsy title : title, placement : "right", offset : 5, delayIn : 300, html : yes, animate : yes
-  #
-  # partial:(comment, account)->
-  #   return unless "object" is typeof comment
-  #   unless account
-  #     account =
-  #       profile:
-  #         fullname: 'Loading...'
-  #         username: 'Loading...'
-  #         avatar  : ''
-  #         hash    : ''
-  #     fallbackUrl = ""
-  #     title = "Default avatar"
-  #     profile = account.profile
-  #   else
-  #     profile = account.profile
-  #     host = "http://#{location.host}/"
-  #     fallbackUrl = "url(http://www.gravatar.com/avatar/#{profile.hash}?size=30&d=#{encodeURIComponent(host + '/images/defaultavatar/default.avatar.30.png')})"
-  #     title = "#{profile.firstName} #{profile.lastName}'s avatar"
-  #
-  #   """
-  #

-  #
-  #
-  #
-  #

-  #

-  #           #{profile.firstName} #{profile.lastName}:
-  #           #{__utils.applyTextExpansions comment.body}
-  #

-  #         <time>#{$.timeago new Date(comment.meta.createdAt)}</time>
-  #

-  #

-  #   """


display dontLoad

display dontLoad

--- lib/atom-ternjs-config-view.coffee
+++ lib/atom-ternjs-config-view.coffee
@@ -19,6 +19,7 @@
     config = @getModel().config
     @content.appendChild(@buildBoolean())
     @content.appendChild(@buildStringArray(config.loadEagerly, 'loadEagerly'))
+    @content.appendChild(@buildStringArray(config.dontLoad, 'dontLoad'))
     @content.appendChild(@close)

   buildStringArray: (obj, section) ->


fix selector for galleryCollection

fix selector for galleryCollection

--- MediaAdminBundle/Resources/public/coffee/GalleryCollectionView.coffee
+++ MediaAdminBundle/Resources/public/coffee/GalleryCollectionView.coffee
@@ -44,7 +44,7 @@

   clickAdd: (event) ->
     event.preventDefault()
-    if $('#main .' + $(event.target).attr('class')).length
+    if $('#main .' + $(event.target).attr('class').split(' ').join(' .')).length
       displayLoader('div[role="container"]')
       Backbone.history.navigate(appRouter.generateUrl('addMedia',
         'folderId':  @options.folderId


enhance calendar model

enhance calendar model

--- app/assets/javascripts/bookings/calendar/models/calendars.js.coffee
+++ app/assets/javascripts/bookings/calendar/models/calendars.js.coffee
@@ -19,7 +19,7 @@
       if @get('mode') == 'week'
         "" + @month_formatted() + ' ' + @range_formatted() + ", "+ @year_formatted()
       else
-        "" + (moment @get 'date').format 'MMMM'  + ""
+        "" + (moment @get 'date').format 'MMMM, YYYY'  + ""

     date_formatted_day: ->
@@ -28,21 +28,17 @@
     day_formatted: ->
       (moment @get 'date').format 'D'

-    outOfRange: ->
-      @get 'outOfRange'
+    toJSON: ->
+      data = _.clone @attributes
+      data.models = _.map data.models, (m)->
+        m.toJSON()
+        m

-    mode: ->
-      @get 'mode'
-
-    toJSON: ->
-      data = _.clone @attributes ;
       data.date_formatted = @date_formatted()
       data.month_formatted = @month_formatted()
       data.range_formatted = @range_formatted()
       data.year_formatted = @year_formatted()
       data.date_formatted_day = @date_formatted_day()
-      data.mode =  @mode()
-      data.outOfRange =  @outOfRange()
       data

   class Models.CalendarDateList extends Backbone.Collection


corrected imported class name

corrected imported class name

--- app/assets/javascripts/admin/models/dataset/dataset_collection.coffee
+++ app/assets/javascripts/admin/models/dataset/dataset_collection.coffee
@@ -1,10 +1,10 @@
 ### define
 underscore : _
-../pagination_collection : PaginationView
+../pagination_collection : PaginationCollection
 ./dataset_model : DatasetModel
 ###

-class DatasetCollection extends PaginationView
+class DatasetCollection extends PaginationCollection

   url : "/api/datasets"
   model : DatasetModel


adjusted the positioning of the snippet toolbar

--- app/assets/javascripts/carmenta/regions/snippetable.toolbar.js.coffee
+++ app/assets/javascripts/carmenta/regions/snippetable.toolbar.js.coffee
@@ -27,7 +27,7 @@
   position: ->
     offset = @snippet.offset()

-    top = offset.top + Carmenta.displayRect.top - $(@document).scrollTop() - @height() - 5
+    top = offset.top + Carmenta.displayRect.top - $(@document).scrollTop() - @height() + 5
     left = offset.left - $(@document).scrollLeft()

     @element.css {


wrap array comprehension

wrap array comprehension

--- mechanics/003-twilight-zone/simulator.coffee
+++ mechanics/003-twilight-zone/simulator.coffee
@@ -49,10 +49,10 @@
             lat = (j) -> Math.PI / 512 * (256 - j)
             u1 = vec3.unify([x1 - x3, y1 - y3, 0])
             u2 = vec3.unify([x2 - x3, y2 - y3, 0])
-            twilight = [
+            twilight = ([
                 lum1 * vec3.inner(p.zenith(lng(i), lat(j), time), u1)
                 lum2 * vec3.inner(p.zenith(lng(i), lat(j), time), u2)
-            ] for i in [0...512] for j in [0...512]
+            ] for i in [0...512] for j in [0...512])
             self.postMessage({twlt: twilight})

         handle = setInterval(evolve, 100)


WIP midstage boss.

WIP midstage boss.

--- src/lazerscripts/stage1/ship_boss.coffee
+++ src/lazerscripts/stage1/ship_boss.coffee
@@ -72,10 +72,12 @@
     # .setSealevel(@level.visibleHeight - 10)

   execute: ->
+    # Start stage 1
     @sequence(
       @parallel(
         @placeSquad MineCannon,
           options:
+            amount: 1
             attach: 'MineCannonPlace'
         @placeSquad Cabin1Inactive,
           options:
@@ -84,180 +86,228 @@
           options:
             attach: 'Cabin2Place'
         @placeSquad TurretInActive, # Turret
-          amount: 2
+          amount: 1
           delay: 0
           options:
             attach: 'TurretPlace'

         @moveTo(x: 0.8)
       )
-      @wait(500)
-      @parallel(
-        @moveTo(x: -1.5)
-        @placeSquad ScraperFlyer,
-          amount: 4
-          delay: 200
-          options: {
-            x: 20
-            y: -20
-          }
-      # Fix sequencing
+      # If parallel has resolved, move on to the next block
       #
-      # Fix hatches
-      #
-        @sequence(
-          @wait(8000)
+      # Start stage 2
+
+      @moveTo(x: -0.1)
+      @sequence(
+        @parallel(
+          # open hatch 1
+          @action 'open1'
           @placeSquad Shooter,
-            amount: 3
-            delay: 250
+            amount: 10,
+            delay: 400
             options: {
-              x: 20
-              y: 300
+              startAt: 'ShipHatch1'
+              hatchReveal: 'ShipHatch1'
+              dx: 25
+              dy: 20
             }
-          #
-          # @placeSquad Shooter,
-          #   amount: 6
-          #   delay: 200
         )
-        @wait(8000)
-        @sequence(
-          @placeSquad Swirler,
-            amount: 4
-            delay: 200
-          @wait(6000)
-          @parallel(
-            # Open hatch 1
-            @action 'open1'
-            @placeSquad Shooter,
-              amount: 5,
-              delay: 200
-              options: {
-                startAt: 'ShipHatch1'
-                hatchReveal: 'ShipHatch1'
-                dx: 25
-                dy: 20
-              }
-            @sequence(
-              @wait(3000)
-              # close hatch 1
-              @action 'close1'
-              @moveTo(x: -2)
-            )
-            @wait(3000)
-
-          )
-          @sequence(
-            # open hatch 2
-            @action 'open2'
-
-            @parallel(
-              @placeSquad Shooter,
-                amount: 3,
-                delay: 200
-                options: {
-                  startAt: 'ShipHatch2'
-                  hatchReveal: 'ShipHatch2'
-                  dx: 25
-                  dy: 20
-                }
-              @placeSquad CrewShooters,
-                amount: 8,
-                delay: 200
-                options: {
-                  x: 115
-                  y: -900
-                }
-
-              @placeSquad Shooter,
-                amount: 3,
-                delay: 200
-                options: {
-                  startAt: 'ShipHatch2'
-                  hatchReveal: 'ShipHatch2'
-                  dx: 25
-                  dy: 20
-                }
-              @placeSquad ScraperFlyer,
-                amount: 8,
-                delay: 700
-                options: {
-                  x: 915
-                  y: 0
-                }
-            )
-            @action 'close2'
-            @parallel(
-                @moveTo(x: -.5) # Move the boat out of view
-
-                # Show some aircrafts here
-                @placeSquad Shooter,
-                  amount: 8,
-                  delay: 600
-                  options: {
-                    x: -15
-                    y: 100
-                  }
-
-                @placeSquad Swirler,
-                  amount: 6,
-                  delay: 200
-                  options: {
-                    x: -15
-                    y: 100
-                  }
-            )
-            @moveTo(x: -2) # move back!
-
-            @action 'open2'
-            @placeSquad Shooter, # 2
-              amount: 6,
-              delay: 200
-              options: {
-                startAt: 'ShipHatch2'
-                hatchReveal: 'ShipHatch2'
-                dx: 25
-                dy: 20
-              }
-            @wait(2000)
-            @action 'open1'
-            @placeSquad Shooter, # 1
-              amount: 3,
-              delay: 200
-              options: {
-                startAt: 'ShipHatch1'
-                hatchReveal: 'ShipHatch1'
-                dx: 25
-                dy: 20
-              }
-            @wait(1000)
-            @placeSquad Shooter, # 1
-              amount: 6,
-              delay: 200
-              options: {
-                startAt: 'ShipHatch1'
-                hatchReveal: 'ShipHatch1'
-                dx: 25
-                dy: 20
-              }
-              @wait(1000)
-              @action 'close1'
-              @placeSquad Shooter, # 2
-                amount: 7,
-                delay: 200
-                options: {
-                  x: 565
-                  y: Crafty.viewport.height + 100
-                }
-              @wait(1000)
-              @action 'close2'
-
-            @wait(5000)
-            @moveTo(x: -5) # move forward!
-
-
-          )
-
-        )
+
+
+        # @sequence(
+        #   @placeSquad Swirler,
+        #     amount: 4
+        #     delay: 200
+        #   @wait(3000)
+        #   @parallel(
+        #     # Open hatch 1
+        #     @action 'open1'
+        #     @placeSquad Shooter,
+        #       amount: 9,
+        #       delay: 400
+        #       options: {
+        #         startAt: 'ShipHatch1'
+        #         hatchReveal: 'ShipHatch1'
+        #         dx: 25
+        #         dy: 20
+        #       }
+        #     @sequence(
+        #       @wait(3000)
+        #       @placeSquad Shooter,
+        #         amount: 5,
+        #         delay: 200
+        #         options: {
+        #           startAt: 'ShipHatch1'
+        #           hatchReveal: 'ShipHatch1'
+        #           dx: 25
+        #           dy: 20
+        #         }
+        #       @wait(2000)
+        #       @placeSquad Shooter,
+        #         amount: 7,
+        #         delay: 600
+        #         options: {
+        #           startAt: 'ShipHatch1'
+        #           hatchReveal: 'ShipHatch1'
+        #           dx: 25
+        #           dy: 20
+        #         }
+        #       # close hatch 1
+        #       @action 'close1'
+        #       @moveTo(x: -2)
+        #     )
+        #     @wait(2000)
+        #   )
+        #   @sequence(
+        #     # open hatch 2
+        #     @action 'open2'
+        #
+        #     @parallel(
+        #       @placeSquad Shooter,
+        #         amount: 3,
+        #         delay: 200
+        #         options: {
+        #           startAt: 'ShipHatch2'
+        #           hatchReveal: 'ShipHatch2'
+        #           dx: 25
+        #           dy: 20
+        #         }
+        #       @placeSquad CrewShooters,
+        #         amount: 8,
+        #         delay: 200
+        #         options: {
+        #           x: 115
+        #           y: -900
+        #         }
+        #
+        #       @placeSquad Shooter,
+        #         amount: 3,
+        #         delay: 200
+        #         options: {
+        #           startAt: 'ShipHatch2'
+        #           hatchReveal: 'ShipHatch2'
+        #           dx: 25
+        #           dy: 20
+        #         }
+        #       @placeSquad ScraperFlyer,
+        #         amount: 8,
+        #         delay: 700
+        #         options: {
+        #           x: 915
+        #           y: 0
+        #         }
+        #     )
+        #
+        #     @action 'close2'
+        #     @sequence(
+        #       @parallel(
+        #         @moveTo(x: -1.5) # Move the boat out of view
+        #         @placeSquad CrewShooters,
+        #           amount: 12,
+        #           delay: 100
+        #           options: {
+        #             x: 515
+        #             y: 0
+        #           }
+        #       )
+        #
+        #     )
+        #
+        #     # Boat moves but somehow doesn't show enemies yet.
+        #     # TO FIX!!
+        #     @placeSquad CrewShooters,
+        #       amount: 2,
+        #       delay: 100
+        #       options: {
+        #         x: 515
+        #         y: 0
+        #       }
+        #     @placeSquad CrewShooters,
+        #       amount: 12,
+        #       delay: 600
+        #       options: {
+        #         x: 515
+        #         y: 0
+        #       }
+        #     @parallel(
+        #       @moveTo(x: -2) # move back!
+        #       # Show some aircrafts here
+        #       @placeSquad Shooter,
+        #         amount: 8,
+        #         delay: 600
+        #         options: {
+        #           x: -15
+        #           y: 100
+        #         }
+        #
+        #       @placeSquad Swirler,
+        #         amount: 6,
+        #         delay: 200
+        #         options: {
+        #           x: -15
+        #           y: 100
+        #         }
+        #     )
+        #     @action 'open2'
+        #     @placeSquad Shooter, # 2
+        #       amount: 6,
+        #       delay: 200
+        #       options: {
+        #         startAt: 'ShipHatch2'
+        #         hatchReveal: 'ShipHatch2'
+        #         dx: 25
+        #         dy: 20
+        #       }
+        #     @action 'open1'
+        #     @placeSquad Shooter, # 1
+        #       amount: 3,
+        #       delay: 200
+        #       options: {
+        #         startAt: 'ShipHatch1'
+        #         hatchReveal: 'ShipHatch1'
+        #         dx: 25
+        #         dy: 20
+        #       }
+        #     @wait(1000)
+        #       @parallel(
+        #         @placeSquad Shooter, # 1
+        #           amount: 6,
+        #           delay: 200
+        #           options: {
+        #             startAt: 'ShipHatch1'
+        #             hatchReveal: 'ShipHatch1'
+        #             dx: 25
+        #             dy: 20
+        #           }
+        #         @placeSquad Shooter, # 2
+        #           amount: 6,
+        #           delay: 200
+        #           options: {
+        #             startAt: 'ShipHatch2'
+        #             hatchReveal: 'ShipHatch2'
+        #             dx: 25
+        #             dy: 20
+        #           }
+        #       )
+        #       @wait(1000)
+        #       @action 'close1'
+        #       @placeSquad Shooter, # 2
+        #         amount: 7,
+        #         delay: 900
+        #         options: {
+        #           x: 565
+        #           y: Crafty.viewport.height + 100
+        #         }
+        #       @wait(1000)
+        #       @action 'close2'
+        #
+        #     @wait(5000)
+        #     @moveTo(x: -5) # move forward!
+        #
+        #
+        #   )
+        #
+        # )
       )
     )


removed tests for globalize parsing

removed tests for globalize parsing


bound so the function isn't called before

--- client/app/Applications/Groups.kdapplication/Views/groupsinvitationtabpaneview.coffee
+++ client/app/Applications/Groups.kdapplication/Views/groupsinvitationtabpaneview.coffee
@@ -18,8 +18,7 @@
     @addSubView @listView

     @controller.on 'UpdatePendingCount', @updatePendingCount.bind this
-    @listView.on 'invitationStatusChanged', =>
-      @parent.tabHandle.markDirty()
+    @listView.on 'invitationStatusChanged', @parent.tabHandle.bound 'markDirty'

   addListeners:->
     @on 'teasersLoaded', =>


Missed off one key line in previous commit.

--- background_scripts/settings.coffee
+++ background_scripts/settings.coffee
@@ -56,6 +56,8 @@
     previousPatterns: "prev,previous,back,<,\u2190,\xab,\u226a,<<"
     # "\bnext\b,\bmore\b,>,→,»,≫,>>"
     nextPatterns: "next,more,>,\u2192,\xbb,\u226b,>>"
+    # default/fall back search engine
+    defaultSearchUrl: "http://www.google.com/search?q="

 # Initialization code.
 # We use this parameter to coordinate any necessary schema changes.


Projects: remove projects from main app bundle

--- projects.coffee
+++ projects.coffee
@@ -149,23 +149,10 @@

 bundles           =

-  # Social          :
-  #   projects      : ['Activity', 'Members', 'Apps', 'Bugs']
-  #   style         : "website/a/css/__social.css"
-  #   script        : "website/a/js/__social.js"
-
   Koding          :
     projects      : [
                      'KDBackend'
                      'KDMainApp'
-                     'Activity'
-                     'Finder'
-                     'Environments'
-                     'Dashboard'
-                     'Pricing'
-                     'Account'
-                     'Ace'
-                     'Terminal'
                      'Login'
                      'PostOperations'
                     ]


Projects: Added Workspace, CollaborativeWorkspace, Teamwork and TeamworkBundle.

--- projects.coffee
+++ projects.coffee
@@ -111,6 +111,24 @@
     script        : "website/js/app.finder.#{KODING_VERSION}.js"
     sourceMapRoot : "Finder/"

+  Workspace       :
+    files         : "client/Workspace/includes.coffee"
+    style         : "website/css/app.workspace.#{KODING_VERSION}.css"
+    script        : "website/js/app.workspace.#{KODING_VERSION}.js"
+    sourceMapRoot : "Workspace/"
+
+  CollaborativeWorkspace:
+    files         : "client/CollaborativeWorkspace/includes.coffee"
+    style         : "website/css/app.collaborativeworkspace.#{KODING_VERSION}.css"
+    script        : "website/js/app.collaborativeworkspace.#{KODING_VERSION}.js"
+    sourceMapRoot : "CollaborativeWorkspace/"
+
+  Teamwork        :
+    files         : "client/Teamwork/includes.coffee"
+    style         : "website/css/app.teamwork.#{KODING_VERSION}.css"
+    script        : "website/js/app.teamwork.#{KODING_VERSION}.js"
+    sourceMapRoot : "Teamwork/"
+
   About           :
     files         : "client/About/includes.coffee"
     style         : "website/css/app.about.#{KODING_VERSION}.css"
@@ -133,5 +151,9 @@
     style         : "website/css/koding.#{KODING_VERSION}.css"
     script        : "website/js/koding.#{KODING_VERSION}.js"

+  TeamworkBundle  :
+    projects      : ['Workspace', 'CollaborativeWorkspace', 'Teamwork']
+    style         : "website/css/teamwork.#{KODING_VERSION}.css"
+    script        : "website/js/teamwork.#{KODING_VERSION}.js"

 module.exports  = {projects, bundles}


feature(lorax): Allow specifying tag when reading log

--- src/lorax.coffee
+++ src/lorax.coffee
@@ -155,20 +155,23 @@
 @description
 Get all commits or commits since last tag
 @param {String} grep  String regex to match
-@param {Function} log Function to output log messages
+@param {String} tag   Tag to read commits from
 @returns {Promise} Promise with an array of commits
 ###
-get = (grep, log = console.log) ->
+get = (grep, tag) ->
   deferred = Q.defer()

   getLog = (tag) ->
     msg = "Reading commits"
     msg += " since #{tag}" if tag
-    log msg
+    console.log msg

     git.getLog(grep, tag).then deferred.resolve, deferred.reject

-  git.getLastTag().then getLog, -> getLog()
+  if tag?
+    getLog tag
+  else
+    git.getLastTag().then getLog, -> getLog()

   return deferred.promise


Issue #37: add a support of hash tables to the Atom plugin

--- tools/atom-plugin/language-micro/grammars/micro.cson
+++ tools/atom-plugin/language-micro/grammars/micro.cson
@@ -47,7 +47,7 @@
 	}
 	{
 		'comment': 'Built-in functions (it should be described before functions)'
-		'match': '\\b(nil|false|true|num|type|arity|apply|_|floor|ceil|trunc|round|sin|cos|tn|arcsin|arccos|arctn|angle|pow|sqrt|exp|ln|lg|abs|random|head|tail|if|str|strb|strl|args|env|time|in|out|outln|err|errln|exit)\\b'
+		'match': '\\b(nil|false|true|num|type|arity|apply|_|floor|ceil|trunc|round|sin|cos|tn|arcsin|arccos|arctn|angle|pow|sqrt|exp|ln|lg|abs|random|head|tail|keys|if|str|strb|strl|args|env|time|in|out|outln|err|errln|exit)\\b'
 		'name': 'variable.function.micro'
 	}
 	{


disabled cyclomatic complexity in computeutils.coffee

--- workers/social/lib/social/models/computeproviders/computeutils.coffee
+++ workers/social/lib/social/models/computeproviders/computeutils.coffee
@@ -1,4 +1,4 @@
-
+# coffeelint: disable=cyclomatic_complexity
 KodingError = require '../../error'

 PROVIDERS =


Added villiany to default HTTP middleware stack

--- packages/shrub-http/index.coffee
+++ packages/shrub-http/index.coffee
@@ -93,6 +93,7 @@
 			'shrub-http-express/session'
 			'shrub-user'
 			'shrub-http-express/logger'
+			'shrub-villiany'
 			'shrub-http-express/routes'
 			'shrub-http-express/static'
 			'shrub-config'


License page updates

License page updates

Changed references to Terms of Service to License FAQ

--- src/scripts/pages/license/license.coffee
+++ src/scripts/pages/license/license.coffee
@@ -8,15 +8,15 @@

   return class LicensePage extends BaseView
     template: template
-    pageTitle: 'Terms of Service - OpenStax CNX'
+    pageTitle: 'License FAQ - OpenStax CNX'
     canonical: null
-    summary: 'OpenStax CNX Terms of Service'
-    description: 'OpenStax CNX Terms of Service'
+    summary: 'OpenStax CNX License'
+    description: 'OpenStax CNX License Frequently Asked Questions'

     regions:
       find: '.find'

     onRender: () ->
-      @parent.regions.header.show(new HeaderView({page: 'tos'}))
-      @parent.regions.footer.show(new FooterView({page: 'tos'}))
+      @parent.regions.header.show(new HeaderView({page: 'license'}))
+      @parent.regions.footer.show(new FooterView({page: 'license'}))
       @regions.find.show(new FindContentView())


Mail Confirmation: fix storage of undefined error when we open Confirmraion URLs directly

--- client/Main/AppController.coffee
+++ client/Main/AppController.coffee
@@ -3,12 +3,18 @@
   constructor:->

     super
-
+
     @registerKeyBindings()

     { name, version } = @getOptions()
-    @appStorage = \
-      KD.singletons.appStorageController.storage name, version or "1.0.1"
+    { mainController } = KD.singletons
+
+    mainController.ready =>
+      # defer should be removed
+      # this should be listening to a different event - SY
+      KD.utils.defer  =>
+        { appStorageController } = KD.singletons
+        @appStorage = appStorageController.storage name, version or "1.0.1"

   createContentDisplay:(models, callback)->
     warn "You need to override #createContentDisplay - #{@constructor.name}"
@@ -25,7 +31,7 @@
     { commands } = KD.getAppOptions @getOptions().name

     cmd = commands[command]
-
+
     if 'function' is typeof cmd
       cmd.call this, event
     else if 'string' is typeof cmd


update UI for sending gcm message

update UI for sending gcm message

--- client/marionette/url/gcm.coffee
+++ client/marionette/url/gcm.coffee
@@ -6,12 +6,8 @@
 	routes:
 		'gcm':		'gcm'

-	constructor: (opts = {}) ->
-		@gcmView = new controller.GCMView {el: 'body'}
-		super(opts)
-
 	gcm: ->
-		@gcmView.render()
+		window.app.page.show new controller.GCMView()

 module.exports =
 	Router:		Router


More sensible conversion of byte-buffer to array

--- services/web/app/coffee/Features/Project/ProjectTokenGenerator.coffee
+++ services/web/app/coffee/Features/Project/ProjectTokenGenerator.coffee
@@ -15,10 +15,9 @@
 	TOKEN_NUMERICS: '123456789'

 	_randomString: (length, alphabet) ->
-		result = ''
-		crypto.randomBytes(length).map(
-			(b) -> result += alphabet[b % alphabet.length]
-		)
+		result = crypto.randomBytes(length).toJSON().data.map(
+			(b) -> alphabet[b % alphabet.length]
+		).join('')
 		return result

 	# Generate a 12-char token with only characters from TOKEN_ALPHA,


Modified Closure class generation so the noop statement from the end of the class is no longer added.

--- src/nodes.coffee
+++ src/nodes.coffee
@@ -913,7 +913,7 @@
     @ensureConstructor name, o
     @body.expressions.unshift new Extends lname, @parent if @parent and not o.google
     @body.expressions.unshift @ctor unless @ctor instanceof Code
-    @body.expressions.push lname
+    @body.expressions.push lname unless o.google
     @addBoundFunctions o

     if o.google


Limit course name to 40 characters so it doesn't overflow the image


Re-init to fix serious problem

Re-init to fix serious problem

--- config.cson
+++ config.cson
@@ -1,40 +1,7 @@
 "*":
-  "exception-reporting":
-    userId: "7047eb46-5af7-e0dc-df8e-20e09dc197f9"
-  welcome:
-    showOnStartup: false
-  "one-light-ui": {}
-  core:
-    themes: [
-      "atom-material-ui"
-      "one-light-syntax"
-    ]
-    projectHome: "/home/aflanagan/Devel"
-    disabledPackages: [
-      "go-to-line"
-    ]
-  "linter-pep8":
-    maxLineLength: 100
-  "linter-flake8":
-    maxLineLength: 100
-  "linter-pep257": {}
-  "linter-pylint":
-    rcFile: "pylintrc"
-  "atom-beautify":
-    _analyticsUserId: "0316af50-c9cd-4f92-9b83-e492e8b8649e"
-  editor:
-    invisibles: {}
-    preferredLineLength: 100
-    scrollPastEnd: true
-    tabLength: 4
-    softWrap: true
-    softWrapAtPreferredLineLength: true
-  "project-manager": {}
-  "file-icons": {}
   minimap:
     plugins:
       "git-diff": true
       linter: true
-  "highlight-line":
-    enableUnderline: true
-    enableBackgroundColor: false
+  welcome:
+    showOnStartup: false


removed ability to change slug. create/remove membership policy and invitations tabs when group privacy changed.

--- components/tabs/KDTabView.coffee
+++ components/tabs/KDTabView.coffee
@@ -111,6 +111,11 @@
       @showPane @getPaneByIndex(newIndex) if @getPaneByIndex(newIndex)?
     @emit "PaneRemoved"

+  removePaneByName:(name)->
+    for pane in @panes
+      if pane.name is name
+        @removePane pane
+        break

   appendHandleContainer:()->
     @addSubView @tabHandleContainer


refactor

refactor

--- client/landing/app/Applications/StartTab.kdapplication/AppView.coffee
+++ client/landing/app/Applications/StartTab.kdapplication/AppView.coffee
@@ -304,10 +304,10 @@
       endTitle    : "Your session end, logging out."
       content     : "You can use Koding for 20 minutes without registering. Register now."
       callback    : =>
+        return  unless KD.isGuest()
         {defaultVmName} = KD.getSingleton "vmController"
-        if KD.isGuest()
-          KD.remote.api.JVM.removeByHostname defaultVmName, (err)->
-            KD.getSingleton("finderController").unmountVm defaultVmName
-            KD.getSingleton("vmController").emit 'VMListChanged'
-            $.cookie "clientId", erase: yes
-            $.cookie "guestForFirstTime", erase: yes+        KD.remote.api.JVM.removeByHostname defaultVmName, (err)->
+          KD.getSingleton("finderController").unmountVm defaultVmName
+          KD.getSingleton("vmController").emit 'VMListChanged'
+          $.cookie "clientId", erase: yes
+          $.cookie "guestForFirstTime", erase: yes


Add option for scrollwheel

Add option for scrollwheel

Previously you had no option to disable the scrollwheel on the Map
object.

--- vendor/assets/javascripts/gmaps-auto-complete.coffee
+++ vendor/assets/javascripts/gmaps-auto-complete.coffee
@@ -63,6 +63,7 @@
     @mapType  = google.maps.MapTypeId.ROADMAP

     zoomLevel = opts['zoomLevel']
+    scrollwheel = opts['scrollwheel']

     @inputField = opts['inputField']
     @errorField = opts['#gmaps-error']
@@ -79,6 +80,7 @@

     mapOptions =
       zoom: zoomLevel
+      scrollwheel: scrollwheel
       center: latlng
       mapTypeId: mapType


Support for new Tag::attrs model added

Support for new Tag::attrs model added

--- style.coffee
+++ style.coffee
@@ -274,7 +274,7 @@

 		if not hasStyledChild and (anchor = node.query('> a'))
 			node = anchor
-			href = node.attrs.get('href')
+			href = node.getAttr('href')
 			if typeof href is 'string'
 				unless @isLinkUriSet
 					@isLinkUriSet = true
@@ -403,10 +403,10 @@
 		return

 	isLink: ->
-		@node.name is 'a' and @node.attrs.has('href') and @node.attrs.get('href')?[0] isnt '#'
+		@node.name is 'a' and @node.getAttr('href')? and @node.getAttr('href')?[0] isnt '#'

 	getLinkUri: ->
-		uri = @node.attrs.get('href') + ''
+		uri = @node.getAttr('href') + ''
 		`//<development>`
 		unless ///^([a-z]+:|\/|\$\{)///.test uri
 			log.warn "Relative link found `#{uri}`"
@@ -422,7 +422,7 @@

 		assert.notOk @item

-		id = @node.attrs.get 'neft:style'
+		id = @node.getAttr 'neft:style'
 		assert.isString id

 		@isScope = ///^(styles|renderer)\:///.test id
@@ -442,7 +442,7 @@
 					parentId = "styles:#{file}:#{style}"
 					parent = @parent
 					loop
-						if parent and parent.node.attrs.get('neft:style') is parentId
+						if parent and parent.node.getAttr('neft:style') is parentId
 							unless parent.scope
 								# parent is not ready yet
 								return


JS: remove unused code

JS: remove unused code

--- core/htdocs_source/app/pods/components/oxifield-main/component.coffee
+++ core/htdocs_source/app/pods/components/oxifield-main/component.coffee
@@ -24,10 +24,6 @@

         'col-md-' + size

-    sKeyFieldSize: Em.computed "content.keysize", ->
-        keysize = @get("content.keysize") || "2"
-        'col-md-' + keysize
-
     hasError: Em.computed.bool "content.error"

     resetError: Em.observer "content.value", ->


Fix error type assertion

Fix error type assertion

--- services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee
+++ services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee
@@ -466,7 +466,7 @@

 				it "should return an error", ->
 					@callback
-						.calledWith(new Error("destination folder is a child folder of me"))
+						.calledWith(new Errors.InvalidNameError("destination folder is a child folder of me"))
 						.should.equal true

 	describe '_removeElementFromMongoArray ', ->


Added different in_screen_time for seperate messages

--- js-library/app/js/views/notification.coffee
+++ js-library/app/js/views/notification.coffee
@@ -53,13 +53,16 @@
   show
     message: 'Factlink posted!'
     type_classes: 'fl-message-success fl-message-icon-logo'
+    in_screen_time: 1000

 Factlink.showShouldSelectTextNotification = ->
   show
     message: 'To create a Factlink, select a statement and click the Factlink button.'
     type_classes: 'fl-message-icon-add'
+    in_screen_time: 3000

 Factlink.showLoadedNotification = ->
   show
     message: 'Factlink is loaded!'
     type_classes: 'fl-message-success fl-message-icon-time'
+    in_screen_time: 3000


Client: Activity: Feed: Updated constant links to capitilize

--- client/activity/lib/components/sidebarwidgets/socialmediawidget.coffee
+++ client/activity/lib/components/sidebarwidgets/socialmediawidget.coffee
@@ -1,21 +1,21 @@
-React    = require 'kd-react'
-Scroller = require 'app/components/scroller'
+React          = require 'kd-react'
+Scroller       = require 'app/components/scroller'
+
+TWITTER_LINK   = 'https://twitter.com/intent/follow?user_id=42704386'
+FACEBOOK_LINK  = 'https://facebook.com/koding'

 module.exports = class SocialMediaWidget extends React.Component

   render: ->

-    twitter_link  = 'https://twitter.com/intent/follow?user_id=42704386'
-    facebook_link = 'https://facebook.com/koding'
-

       Koding on Twitter
       Koding on Facebook


Ace: update button colors in save&close modal

--- client/app/Applications/Ace.kdapplication/aceapplicationtabview.coffee
+++ client/app/Applications/Ace.kdapplication/aceapplicationtabview.coffee
@@ -15,7 +15,7 @@
       overlay       : yes
       buttons       :
         "SaveClose" :
-          cssClass  : "modal-clean-gray"
+          cssClass  : "modal-clean-green"
           title     : "Save and Close"
           callback  : =>
             if file.path.indexOf("localfile:") is 0
@@ -27,7 +27,7 @@
               ace.requestSave()
               @closePaneAndModal pane, modal
         "DontSave"  :
-          cssClass  : "modal-clean-gray"
+          cssClass  : "modal-clean-red"
           title     : "Don't Save"
           callback  : =>
             @closePaneAndModal pane, modal


activity: double xhr and empty activity stream fix

--- client/app/Applications/Activity.kdapplication/AppController.coffee
+++ client/app/Applications/Activity.kdapplication/AppController.coffee
@@ -35,18 +35,19 @@
     @appStorage        = new AppStorage 'Activity', '1.0'
     @isLoading         = no
     @mainController    = @getSingleton 'mainController'
-
-    if @mainController.appIsReady then @putListeners()
-    else @mainController.on 'FrameworkIsReady', => @putListeners()
+    @lastTo            = null
+    @lastFrom          = null
+
+    # if @mainController.appIsReady then @putListeners()
+    # else @mainController.on 'FrameworkIsReady', => @putListeners()

     @status = @getSingleton "status"
     @status.on "reconnected", (conn)=>
       if conn && conn.reason is "internetDownForLongTime"
-        @refresh()
-      else
-        @fetchSomeActivities()
-
-  putListeners:->
+      then @refresh()
+      else @fetchSomeActivities()
+
+  loadView:->
     activityController = @getSingleton('activityController')

     # Do we really need this? ~ GG
@@ -54,16 +55,13 @@
     activityController.once "ActivityListControllerReady", (controller)=>
       @attachEvents controller
       frontApp = @getSingleton('appManager').getFrontApp()
-      @populateActivity() if frontApp?.name is "Activity"
-
-  loadView:->
-    @populateActivity() if @listController
+      @ready @bound "populateActivity"
+
+    @emit 'ready'

   resetAll:->
-
-    delete @lastTo
-    delete @lastFrom
-
+    @lastTo   = null
+    @lastFrom = null
     @listController.resetList()
     @listController.removeAllItems()

@@ -148,7 +146,6 @@

   # Store first & last activity timestamp.
   extractTeasersTimeStamps:(teasers)->
-
     @lastTo   = teasers.first.meta.createdAt
     @lastFrom = teasers.last.meta.createdAt
     # debugger
@@ -161,7 +158,6 @@
   # Refreshes activity feed, used when user has been disconnected
   # for so long, backend connection is long gone.
   refresh:->
-
     # prevents multiple clicks to refresh from interfering
     return  if @isLoading

@@ -185,9 +181,6 @@

   populateActivity:(options = {}, callback)->

-    # log "ever here?", @isLoading
-    # debugger
-
     return if @isLoading

     @listController.showLazyLoader()
@@ -197,8 +190,6 @@
     groupsController = @getSingleton 'groupsController'
     {isReady}        = groupsController
     currentGroup     = groupsController.getCurrentGroup()
-
-    # log isReady, ">>>>>>>>"

     fetch = (slug)=>
       unless slug is 'koding'
@@ -302,7 +293,7 @@

   continueLoadingTeasers:->

-    lastTimeStamp = (new Date @lastFrom).getTime()
+    lastTimeStamp = (new Date @lastFrom or Date.now()).getTime()
     @populateActivity {slug : "before/#{lastTimeStamp}", to: lastTimeStamp}

   teasersLoaded:->


Workspace: Early implementation of WatchMode.

--- client/landing/CollaborativeWorkspace/collaborativeworkspace.coffee
+++ client/landing/CollaborativeWorkspace/collaborativeworkspace.coffee
@@ -26,6 +26,7 @@
     @workspaceRef = @firepadRef.child @sessionKey
     @broadcastRef = @workspaceRef.child "broadcast"
     @historyRef   = @workspaceRef.child "history"
+    @watchRef     = @workspaceRef.child "watch"

   bindRemoteEvents: ->
     @workspaceRef.once "value", (snapshot) =>
@@ -48,6 +49,7 @@
       @userRef.onDisconnect().set "offline"
       record = if isOldSession then "$0 joined the session" else "$0 started the session"
       @addToHistory record
+      @watchRef.child(@nickname).set "everybody"

       if @amIHost()
         @workspaceRef.onDisconnect().remove()
@@ -101,6 +103,9 @@
       @forceDisconnect()
       events = [ "value", "child_added", "child_removed", "child_changed" ]
       @workspaceRef.off eventName for eventName in events
+
+    @watchRef.on "value", (snapshot) =>
+      @watchMap = snapshot.val() or {}

   # TODO: Be sure we don't query if we have user data
   fetchUsers: ->
@@ -310,6 +315,10 @@
       delegate  : this
     }

+  setWatchMode: (targetUsername) ->
+    username = KD.nick()
+    @watchRef.child(username).set targetUsername
+
   addToHistory: (data) ->
     target       = @historyRef.child Date.now()
     data         = message: data  if typeof data is "string"


revive: pulsing logoed subpages WIP

revive: pulsing logoed subpages WIP

--- client/landing/app/MainApp/maincontroller/mainviews/mainview.coffee
+++ client/landing/app/MainApp/maincontroller/mainviews/mainview.coffee
@@ -1,6 +1,14 @@
 class MainView extends KDView

   viewAppended:->
+
+    if el = document.getElementById 'main-loading'
+      KD.utils.wait 750, ->
+        el.childNodes[0].classList.add 'out'
+        KD.utils.wait 250, ->
+          el.classList.add 'out'
+          KD.utils.wait 750, ->
+            el.parentElement.removeChild el

     @bindTransitionEnd()
     # @addServerStack()
@@ -58,7 +66,8 @@

   createMainPanels:->

-    @addSubView @homeIntro = new HomeIntroView
+    klass = if KD.isLoggedIn() then KDCustomHTMLView else HomeIntroView
+    @addSubView @homeIntro = new klass

     @addSubView @panelWrapper = new KDView
       tagName  : "section"
@@ -89,7 +98,9 @@
       tagName : "header"
       domId   : "main-header"

-    @logo = new KDCustomHTMLView
+    @header.getElement().innerHTML = ''
+
+    @header.addSubView @logo = new KDCustomHTMLView
       tagName   : "a"
       domId     : "koding-logo"
       cssClass  : if entryPoint?.type? is 'group' then 'group' else ''
@@ -99,9 +110,9 @@
         homeRoute = if KD.isLoggedIn() then "/Activity" else "/Home"
         KD.getSingleton('router').handleRoute homeRoute, {entryPoint}

-    loginLink = new CustomLinkView
+    @header.addSubView loginLink = new CustomLinkView
       domId       : 'header-sign-in'
-      title       : 'Already a user? Sign in'
+      title       : 'Already a user? Sign in.'
       icon        :
         placement : 'right'
       cssClass    : 'login'


- More Backbone model usage - Only checking in coffee for now because something is still broken

--- VersionOne.Requestor.NET.Backbone/Scripts/v1assetEditor.coffee
+++ VersionOne.Requestor.NET.Backbone/Scripts/v1assetEditor.coffee
@@ -1,5 +1,4 @@
 define ["backbone", "underscore", "toastr", "jquery", "jquery.mobile", "jsrender"], (Backbone, _, toastr, $) ->
-
   log = (message) ->
     console.log message

@@ -91,14 +90,18 @@
       @toggleNewOrEdit "new"

     refreshFormModel: ->
-      @assetModel = Backbone.Model.extend(schema: @formFields[@fieldSetName])
+      log 'Refreshing model: '
+      @assetModel = Backbone.Model.extend({schema: @getFormFields()})
+      n = new @assetModel
+      log 's:'
+      log n.schema

     listFetchIfNotLoaded: ->
       @loadRequests() unless @_listLoaded

     configureProjectSearch: ->
-      searchTerm = undefined
-      ajaxRequest = undefined
+      searchTerm = null
+      ajaxRequest = null
       projectSearch = $("#projectSearch")
       projectSearch.pressEnter (e) =>
         target = $(e.currentTarget)
@@ -117,7 +120,7 @@
         request = @createRequest(url: url)
         projects = $("#projects")
         ajaxRequest = $.ajax(request).done((data) =>
-          ajaxRequest = `undefined`
+          ajaxRequest = null
           projects = $("#projects").empty()
           for val in data
             @projectItemAppend val
@@ -154,13 +157,13 @@

     setProject: (projectIdref) ->
       @projectIdref = projectIdref
-      @refreshFieldSet projectIdref
+      @refreshFieldSet projectIdref
       #this.configureListPage();
       @_listLoaded = false

     loadRequests: (projectIdref) ->
       @_listLoaded = true
-      if not projectIdref? or projectIdref is "undefined"
+      if not projectIdref?
         projectIdref = @projectIdref
       else
         @setProject projectIdref
@@ -182,7 +185,7 @@
       @changePage "#list"

     refreshFieldSet: (fieldSetName) ->
-      if @formFields[fieldSetName] isnt `undefined`
+      if @formFields[fieldSetName]?
         @fieldSetName = fieldSetName
       else
         @fieldSetName = "default"
@@ -270,8 +273,8 @@

     newAsset: (modelData, href) ->
       @configSelectLists().done =>
-        asset = undefined
-        if modelData
+        asset = null
+        if modelData?
           asset = new @assetModel(modelData)
         else
           asset = new @assetModel()
@@ -279,7 +282,7 @@
         form = new Backbone.Form(model: asset).render()
         @form = form
         $("#fields").html form.el
-        if modelData
+        if modelData?
           @toggleNewOrEdit "edit", href
         else
           @toggleNewOrEdit "new"
@@ -299,7 +302,10 @@
       # TODO: this should not happen on EVERY new click.
       promise = new $.Deferred()
       ajaxRequests = []
-      model = (new @assetModel()).schema
+      log @assetModel
+      model = new @assetModel().schema
+      log 'sc'
+      log model
       selectLists = []
       for key, value of model
         selectLists.push value if value.options.length < 1 if value.type is "Select"
@@ -342,27 +348,30 @@
         promise.resolve()

     editAsset: (href) ->
+      fields = @getFormFields()
+
       url = @host + href + "?" + $.param(@queryOpts)
       fieldsClause = @getFormFieldsForSelectQuery()
       url += "&" + fieldsClause
-      request = @createRequest(url: url)
-      # TODO: need better way to do this
-      $.ajax(request).done((data) =>
+
+      asset = @createFetchModel url
+
+      asset.get().done(->
         modelData = {}
-        model = (new @assetModel()).schema
-        links = data._links
+        model = (new @assetModel()).schema # TODO: this might not be needed anymore
+        links = asset._links
         for key of model
-          value = data[key]
+          value = asset[key]
           if value
-            # HARD-CODED
-            value = new Date(Date.parse(value)) if key is "Custom_RequestedETA"
-            if data[key] isnt `undefined`
+            if fields[key].type == 'Date'
+              value = new Date(Date.parse(value))
+            if data[key]?
               modelData[key] = value
             else
               @debug "Setting Key: " + key + " is undefined"
           else
             rel = links[key]
-            continue if rel is `undefined`
+            continue if not rel?
             val = links[key]
             if val? and val.length > 0
               val = val[0]
@@ -403,6 +412,18 @@
       options.headers = @headers  unless @serviceGateway
       return options

+    createFetchModel: (url) ->
+      options = {}
+      options.headers = @headers unless @serviceGateway
+      props =
+        url: url
+        get: ->
+          return @fetch(options)
+
+      fetchModel = Backbone.Model.extend(props)
+
+      return new fetchModel()
+
     createAsset: (assetName, callback) ->
       url = @getAssetUrl(assetName)
       @requestorName = $("#RequestedBy").val()


Update: disable spell-check in atom

Update: disable spell-check in atom

--- Users/USERNAME/.atom/config.cson
+++ Users/USERNAME/.atom/config.cson
@@ -2,6 +2,9 @@
   "autoclose-html":
     makeNeverCloseSelfClosing: false
   core:
+    disabledPackages: [
+      "spell-check"
+    ]
     openEmptyEditorOnStart: false
     packagesWithKeymapsDisabled: [
       "platformio-ide-terminal"


get colour from correct place

get colour from correct place

--- resources/assets/coffee/react/beatmap-discussions/user-filter.coffee
+++ resources/assets/coffee/react/beatmap-discussions/user-filter.coffee
@@ -30,7 +30,7 @@
       options.push id: user.id, colour: user.profile_colour, text: user.username

     selected = if @props.selectedUser?
-                 id: @props.selectedUser.id, colour: user.profile_colour, text: @props.selectedUser.username
+                 id: @props.selectedUser.id, colour: @props.selectedUser.profile_colour, text: @props.selectedUser.username
                else
                  id: null, text: osu.trans('beatmap_discussions.user_filter.label')


updates for gl-matrix 2

updates for gl-matrix 2

--- lib/assets/javascripts/jax/camera.js.coffee
+++ lib/assets/javascripts/jax/camera.js.coffee
@@ -3,26 +3,25 @@

 class Jax.Camera
   @include Jax.EventEmitter
-  LOCAL_VIEW  = vec3.create [0, 0,-1]
-  LOCAL_RIGHT = vec3.create [1, 0, 0]
-  LOCAL_UP    = vec3.create [0, 1, 0]
+  LOCAL_VIEW  = GLMatrix.vec3.clone [0, 0,-1]
+  LOCAL_RIGHT = GLMatrix.vec3.clone [1, 0, 0]
+  LOCAL_UP    = GLMatrix.vec3.clone [0, 1, 0]

   constructor: (options) ->
-    @rotation = quat4.identity()
-    @_position = vec3.create()
+    @rotation = GLMatrix.quat.identity GLMatrix.quat.create()
+    @_position = GLMatrix.vec3.create()
     @matrices =
-      mv:  mat4.identity()
-      imv: mat4.identity()
-      p:   mat4.identity()
-      n:   mat3.identity()
+      mv:  GLMatrix.mat4.identity GLMatrix.mat4.create()
+      imv: GLMatrix.mat4.identity GLMatrix.mat4.create()
+      p:   GLMatrix.mat4.identity GLMatrix.mat4.create()
+      n:   GLMatrix.mat3.identity GLMatrix.mat3.create()
     @reset()
     @setFixedYawAxis true, vec3.UNIT_Y

     @_isValid = false
-    @_viewVector = vec3.create()
-    @_upVector   = vec3.create()
-    @_rightVector= vec3.create()
-
+    @_viewVector = GLMatrix.vec3.create()
+    @_upVector   = GLMatrix.vec3.create()
+    @_rightVector= GLMatrix.vec3.create()
     if options
       @_position = options.position if options.position
       @direction = options.direction if options.direction
@@ -35,27 +34,27 @@
     @_frustum

-  _dirVec = vec3.create()
-  _dirRightVec = vec3.create()
-  _dirUpVec = vec3.create()
-  _dirQuat = quat4.create()
+  _dirVec = GLMatrix.vec3.create()
+  _dirRightVec = GLMatrix.vec3.create()
+  _dirUpVec = GLMatrix.vec3.create()
+  _dirQuat = GLMatrix.quat.create()
   @define 'direction',
     get: ->
       @validate() unless @isValid()
       @_viewVector
     set: (dir) ->
-      vec = vec3.set dir, _dirVec
-      vec3.normalize vec
+      vec = GLMatrix.vec3.copy _dirVec, dir
+      GLMatrix.vec3.normalize vec, vec
       if @_fixedYaw
         # FIXME why am I negating? Can't remember...
-        vec3.negate vec
-        right = vec3.normalize vec3.cross @_fixedYawAxis, vec, _dirRightVec
-        up    = vec3.normalize vec3.cross vec, right, _dirUpVec
-        quat4.fromAxes vec, right, up, @rotation
+        GLMatrix.vec3.negate vec, vec
+        right = GLMatrix.vec3.normalize _dirRightVec, GLMatrix.vec3.cross _dirRightVec, @_fixedYawAxis, vec
+        up    = GLMatrix.vec3.normalize _dirUpVec,    GLMatrix.vec3.cross _dirUpVec,    vec, right
+        GLMatrix.quat.setAxes @rotation, vec, right, up
       else
-        rotquat = vec3.rotationTo @direction, vec, _dirQuat
-        quat4.multiply rotquat, @rotation, @rotation
-      quat4.normalize @rotation
+        rotquat = GLMatrix.rotationTo _dirQuat, @direction, vec
+        GLMatrix.quat.multiply @rotation, rotquat, @rotation
+      GLMatrix.quat.normalize @rotation, @rotation
       @invalidate()
       @fireEvent 'updated'

@@ -70,7 +69,7 @@
   @define 'position',
     get: -> @_position
     set: (x) ->
-      vec3.set x, @_position
+      GLMatrix.vec3.copy @_position, x
       # no need to completely invalidate, just force matrices and
       # frustum to update, that way we skip the overhead of
       # recalculating view, right and up vectors, which won't change.
@@ -88,17 +87,17 @@
   recalculateMatrices: ->
     @validate() unless @isValid()
     @_stale = false
-    mat4.fromRotationTranslation @rotation, @position, @matrices.mv
-    mat4.inverse @matrices.mv, @matrices.imv
-    mat4.toInverseMat3 @matrices.mv, @matrices.n
-    mat3.transpose @matrices.n
+    GLMatrix.mat4.fromRotationTranslation @matrices.mv, @rotation, @position
+    GLMatrix.mat4.invert @matrices.imv, @matrices.mv
+    GLMatrix.mat3.fromMat4 @matrices.n, @matrices.imv
+    GLMatrix.mat3.transpose @matrices.n, @matrices.n
     @fireEvent 'matrixUpdated'

   validate: () ->
     @_isValid = true
-    @_viewVector  = quat4.multiplyVec3 @rotation, LOCAL_VIEW,  @_viewVector
-    @_rightVector = quat4.multiplyVec3 @rotation, LOCAL_RIGHT, @_rightVector
-    @_upVector    = quat4.multiplyVec3 @rotation, LOCAL_UP,    @_upVector
+    @_viewVector  = GLMatrix.vec3.transformQuat @_viewVector,  LOCAL_VIEW,  @rotation
+    @_rightVector = GLMatrix.vec3.transformQuat @_rightVector, LOCAL_RIGHT, @rotation
+    @_upVector    = GLMatrix.vec3.transformQuat @_upVector,    LOCAL_UP,    @rotation

   setFixedYawAxis: (useFixedYaw, axis) ->
     @_fixedYaw = useFixedYaw
@@ -264,7 +263,7 @@

     view = vec3.scale @direction, forward
     right = vec3.scale @right, strafe
-    vec3.set @position, dest
+    GLMatrix.vec3.copy dest, @position
     vec3.add view, dest, dest
     vec3.add right, dest, dest
     return dest


Scroll to anchor link id if link has anchor tag

Fixes bug that page dose not scroll to anthor id through turbolinks.
This idea is based on
document.locatio.href = document.location.href + '#hash_tag'
does not make page reloading but just pageYOffset changes().

--- lib/assets/javascripts/turbolinks.js.coffee
+++ lib/assets/javascripts/turbolinks.js.coffee
@@ -30,7 +30,10 @@
     else
       changePage extractTitleAndBody(doc)...
       reflectRedirectedUrl xhr
-      resetScrollPosition()
+      if document.location.hash
+        document.location.href = document.location.href
+      else
+        resetScrollPosition()
       triggerEvent 'page:load'

   xhr.onabort = -> console.log 'Aborted turbolink fetch!'


improving readability and performance

improving readability and performance

small refactoring by @dhh suggestion
comments by @reed

--- lib/assets/javascripts/turbolinks.js.coffee
+++ lib/assets/javascripts/turbolinks.js.coffee
@@ -1,20 +1,12 @@
-initialized    = false
+CACHE_SIZE     = 10
 currentState   = null
-referer        = document.location.href
+referer        = null
 loadedAssets   = null
 pageCache      = {}
 createDocument = null
 requestMethod  = document.cookie.match(/request_method=(\w+)/)?[1].toUpperCase() or ''
 xhr            = null

-visit = (url) ->
-  if browserSupportsPushState && browserIsntBuggy
-    cacheCurrentPage()
-    reflectNewUrl url
-    fetchReplacement url
-  else
-    document.location.href = url
-

 fetchReplacement = (url) ->
   triggerEvent 'page:fetch'
@@ -31,7 +23,8 @@
   xhr.onload = ->
     triggerEvent 'page:receive'

-    if doc = validateResponse()
+    if doc = processResponse()
+      reflectNewUrl url
       changePage extractTitleAndBody(doc)...
       reflectRedirectedUrl()
       if document.location.hash
@@ -39,6 +32,8 @@
       else
         resetScrollPosition()
       triggerEvent 'page:load'
+    else
+      document.location.href = url

   xhr.onloadend = -> xhr = null
   xhr.onabort   = -> rememberCurrentUrl()
@@ -46,21 +41,16 @@

   xhr.send()

-fetchHistory = (state) ->
+fetchHistory = (position) ->
   cacheCurrentPage()
-
-  if page = pageCache[state.position]
-    xhr?.abort()
-    changePage page.title, page.body
-    recallScrollPosition page
-    triggerEvent 'page:restore'
-  else
-    fetchReplacement document.location.href
+  page = pageCache[position]
+  xhr?.abort()
+  changePage page.title, page.body
+  recallScrollPosition page
+  triggerEvent 'page:restore'

 cacheCurrentPage = ->
-  rememberInitialPage()
-
   pageCache[currentState.position] =
     url:       document.location.href,
     body:      document.body,
@@ -68,7 +58,7 @@
     positionY: window.pageYOffset,
     positionX: window.pageXOffset

-  constrainPageCacheTo(10)
+  constrainPageCacheTo(CACHE_SIZE)

 constrainPageCacheTo = (limit) ->
   for own key, value of pageCache
@@ -101,8 +91,7 @@
   return

 reflectNewUrl = (url) ->
-  if url isnt document.location.href
-    referer = document.location.href
+  if url isnt referer
     window.history.pushState { turbolinks: true, position: currentState.position + 1 }, '', url

 reflectRedirectedUrl = ->
@@ -115,13 +104,6 @@

 rememberCurrentState = ->
   currentState = window.history.state
-
-rememberInitialPage = ->
-  unless initialized
-    rememberCurrentUrl()
-    rememberCurrentState()
-    createDocument = browserCompatibleDocumentParser()
-    initialized = true

 recallScrollPosition = (page) ->
   window.scrollTo page.positionX, page.positionY
@@ -141,13 +123,12 @@
   event.initEvent name, true, true
   document.dispatchEvent event

-
-validateResponse = ->
+processResponse = ->
   clientOrServerError = ->
     400 <= xhr.status < 600

-  invalidContent = ->
-    !xhr.getResponseHeader('Content-Type').match /^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/
+  validContent = ->
+    xhr.getResponseHeader('Content-Type').match /^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/

   extractTrackAssets = (doc) ->
     (node.src || node.href) for node in doc.head.childNodes when node.getAttribute?('data-turbolinks-track')?
@@ -161,17 +142,10 @@
     [a, b] = [b, a] if a.length > b.length
     value for value in a when value in b

-  if clientOrServerError()
-    # Workaround for WebKit bug (https://bugs.webkit.org/show_bug.cgi?id=93506)
-    url = document.location.href
-    window.history.replaceState null, '', '#'
-    window.location.replace url
-    false
-  else if invalidContent() or assetsChanged (doc = createDocument xhr.responseText)
-    window.location.reload()
-    false
-  else
-    doc
+  if not clientOrServerError() and validContent()
+    doc = createDocument xhr.responseText
+    if doc and !assetsChanged doc
+      return doc

 extractTitleAndBody = (doc) ->
   title = doc.querySelector 'title'
@@ -269,11 +243,19 @@
 ignoreClick = (event, link) ->
   crossOriginLink(link) or anchoredLink(link) or nonHtmlLink(link) or noTurbolink(link) or targetLink(link) or nonStandardClick(event)

-
 initializeTurbolinks = ->
+  rememberCurrentUrl()
+  rememberCurrentState()
+  createDocument = browserCompatibleDocumentParser()
   document.addEventListener 'click', installClickHandlerLast, true
   window.addEventListener 'popstate', (event) ->
-    fetchHistory event.state if event.state?.turbolinks
+    state = event.state
+
+    if state?.turbolinks
+      if pageCache[state.position]
+        fetchHistory state.position
+      else
+        visit event.target.location.href
   , false

 browserSupportsPushState =
@@ -285,7 +267,16 @@
 requestMethodIsSafe =
   requestMethod in ['GET','']

-initializeTurbolinks() if browserSupportsPushState and browserIsntBuggy and requestMethodIsSafe
+if browserSupportsPushState and browserIsntBuggy and requestMethodIsSafe
+  visit = (url) ->
+    referer = document.location.href
+    cacheCurrentPage()
+    fetchReplacement url
+
+  initializeTurbolinks()
+else
+  visit = (url) ->
+    document.location.href = url

 # Call Turbolinks.visit(url) from client code
 @Turbolinks = { visit }


Update turbolinks.js.coffee

Update turbolinks.js.coffee

--- lib/assets/javascripts/turbolinks.js.coffee
+++ lib/assets/javascripts/turbolinks.js.coffee
@@ -9,7 +9,7 @@

 fetchReplacement = (url) ->
-  triggerEvent 'page:fetch'
+  triggerEvent 'page:fetch', url: url

   # Remove hash from url to ensure IE 10 compatibility
   safeUrl = removeHash url
@@ -121,8 +121,9 @@
     link.href = url
   link.href.replace link.hash, ''

-triggerEvent = (name) ->
+triggerEvent = (name, data) ->
   event = document.createEvent 'Events'
+  event.data = data if data
   event.initEvent name, true, true
   document.dispatchEvent event

@@ -286,6 +287,6 @@

 # Public API
 #   Turbolinks.visit(url)
-#   Turbolinks.pagesCached()
+#   Turbolinks.pagesCached()
 #   Turbolinks.pagesCached(20)
 @Turbolinks = { visit, pagesCached }


more legible

more legible

--- lib/assets/javascripts/turbolinks.js.coffee
+++ lib/assets/javascripts/turbolinks.js.coffee
@@ -20,7 +20,7 @@
   xhr.setRequestHeader 'X-XHR-Referer', referer
   xhr.onload  = ->
     doc   = createDocument xhr.responseText
-    unless assetsChanged extractAssetsFrom doc
+    unless assetsChanged doc
       changePage extractTitleAndBody(doc)...
       reflectRedirectedUrl xhr
       resetScrollPosition()
@@ -101,7 +101,8 @@
     headAssets.push link.href if link.href
   headAssets

-assetsChanged = (headAssets)->
+assetsChanged = (doc)->
+  headAssets = extractAssetsFrom doc
   if assets.length == headAssets.length
     for asset, index in assets
       unless asset == headAssets[index]


setting draggable to false on dialog

setting draggable to false on dialog

--- app/assets/coffee/apps/config/marionette/regions/dialog.coffee
+++ app/assets/coffee/apps/config/marionette/regions/dialog.coffee
@@ -12,6 +12,7 @@
         height: dialogHeight
         width: dialogWidth
         position: at: "center top"
+        draggable:false
         resizable: false
         close: (e, ui) ->
           self.closeDialog()


Fixed local bind.

Fixed local bind.

--- app/assets/javascripts/app/models/_application_model.js.coffee
+++ app/assets/javascripts/app/models/_application_model.js.coffee
@@ -187,11 +187,11 @@
       App[ @constructor.className ]['SUBSCRIPTION_ITEM'] = {}

       # subscribe and render data after local change
-      @bind(
+      App[ @constructor.className ].bind(
         'refresh change'
-        =>
-          for key, callback of App[ @constructor.className ]['SUBSCRIPTION_ITEM'][ @id ]
-            callback(@)
+        (item) =>
+          for key, callback of App[ @constructor.className ]['SUBSCRIPTION_ITEM'][ item.id ]
+            callback(item)
       )

       # subscribe and render data after server change


make date question input readonly

make date question input readonly

--- app/assets/javascripts/components/questions/date_question.cjsx
+++ app/assets/javascripts/components/questions/date_question.cjsx
@@ -7,7 +7,7 @@
 class DateQuestion extends React.Component
   render: ->
     <DatePicker dateFormat="DD/MM/YYYY" maxDate={moment()}
-      selected={@selectedDate()} onChange={@handleChange}/>
+      readOnly={true} selected={@selectedDate()} onChange={@handleChange}/>

   handleChange: (date) =>
     QuestionnaireStore.selectAnswer(@props.data.id, date.format("DD/MM/YYYY"))


Remove event handler before destroying component

--- app/assets/javascripts/rglossa/components/cwb-multiword.coffee
+++ app/assets/javascripts/rglossa/components/cwb-multiword.coffee
@@ -21,8 +21,11 @@
   # or a search action
   _query: null

-  didInsertElement: ->
+  didInsertElement: ->
     @$().on 'focusout', '.ember-text-field', => @set('query', @_query)
+
+  willDestroyElement: ->
+    @$().off 'focusout'

   displayedQuery: (->
     @_query = @get('query')


[#70462794] check if #getCurrentUser is defined

--- app/assets/javascripts/routes/admin_authorized_route.js.coffee
+++ app/assets/javascripts/routes/admin_authorized_route.js.coffee
@@ -1,6 +1,6 @@
 ETahi.AdminAuthorizedRoute = Ember.Route.extend
   beforeModel: (transition) ->
-    @handleUnauthorizedRequest(transition) unless @getCurrentUser().get('admin')
+    @handleUnauthorizedRequest(transition) unless @getCurrentUser? and @getCurrentUser().get('admin')

   handleUnauthorizedRequest: (transition) ->
     transition.abort()


Removed ~ from getUniqueId method because of DOM cannot traverse to an element which has ~ in its name.

--- client/Framework/core/utils.coffee
+++ client/Framework/core/utils.coffee
@@ -30,7 +30,7 @@
       chain.push caller
     chain

-  getUniqueId: do -> i = 0; -> "~#{i++}"
+  getUniqueId: do -> i = 0; -> "kd-#{i++}"

   getRandomNumber :(range)->
     range = range or 1000000


fixing problem with view results disappearing at odd time

Former-commit-id: d55fd999e99ac9097065bf283c23ffeaba55c84e [formerly d7a3a0a3d0543f117f965552f4dbe72b9ec78f75] [formerly 9eed264fc009eb27569026be6900845dc8ebb2ae [formerly 94a7528dc54d1d4a5d7cf51eca940a8fe433f9e9]] [formerly 80817e936674de78ab423da0fb707317dfc4330e [formerly f5f384cdb62968f32f555b5e7ba943d4de5512b9] [formerly cdfdb8c78cea1c2ef80c3476ff7b54076c4aef9a [formerly cdfdb8c78cea1c2ef80c3476ff7b54076c4aef9a [formerly bb113e4dce7a756252e979e6a199efd59cdd563d]]]]
Former-commit-id: b31acc1ee4f33b4564778cc2e39d6c075adc0add [formerly fdcc0fb3a9ca0cf953f1b6e7f89526b16c859ad5] [formerly c1e03ba6d85e632f48743670a28d825ed7fceba3 [formerly ec2424c5d3fe48bde3bd26e29c23f8d42298bd21]]
Former-commit-id: 2ec54f08dfdcc40859388407d62cf8e0d4765e40 [formerly 8998f1781606869043370c52e9731cd17c65b60d]
Former-commit-id: 3a54866a3a9759e96847cfd656b688d24dec67ae
Former-commit-id: 50463726245dd9c2b293f6dd4fb9013ec2f9daba

--- @client/modules/franklin/proposal/reasons_view.coffee
+++ @client/modules/franklin/proposal/reasons_view.coffee
@@ -81,16 +81,12 @@

     events :
       'click .points_list_region' : 'reasonsClicked'
-      # 'click .participating_users_region' : 'reasonsClicked'
       'click .reasons_footer_region' : 'reasonsClicked'
       'mouseenter .points_list_region' : 'showViewResults'
-      'mouseleave .points_list_region' : 'hideViewResults'
+      'mouseleave .points_by_community' : 'hideViewResults'
       'mouseenter .reasons_footer_region' : 'showViewResults'
       'mouseleave .reasons_footer_region' : 'hideViewResults'
-      # 'mouseenter .participating_users_region' : 'showViewResults'
-      # 'mouseleave .participating_users_region' : 'hideViewResults'
       'mouseenter .community_point' : 'logPointView'
-

     reasonsClicked : (ev) ->
       if @state == Proposal.State.Summary && $(ev.target).closest('.decision_board_heading_region').length == 0
@@ -105,7 +101,8 @@
         visibility: 'visible'

     hideViewResults : (ev) ->
-      return if @state != Proposal.State.Summary || $(ev.target).closest('.results_prompt_from_summary_view').length > 0
+      return if @state != Proposal.State.Summary || $(ev.target).closest('.results_prompt_from_summary_view').length > 0 || ($(ev.target).is('.reasons_footer_region') && !$(ev.target).is('.points_by_community'))
+
       @hover_state = false
       _.delay =>
         if !@hover_state


Client: Activity: DesktopNotifications: Updated saveSettings method to fix update settings problem

--- client/activity/lib/flux/channelnotificationsettings/actions/channel.coffee
+++ client/activity/lib/flux/channelnotificationsettings/actions/channel.coffee
@@ -109,7 +109,6 @@

 redirectToChannel: (channelName) ->

-
   route = "/Channels/#{channelName}"

   kd.singletons.router.handleRoute route
@@ -119,24 +118,28 @@

   { channelId, channelName, channelSettings, changedFields } = options
   isEqual         = yes
-  globalSettings  = getDefaultNotificationSettings()
+  defaultSettings = getDefaultNotificationSettings()
   isNewlyCreated  = channelSettings._newlyCreated

-  for item of globalSettings
-    if globalSettings[item] != channelSettings[item]
+  for item of defaultSettings
+    if defaultSettings[item] != channelSettings[item]
       isEqual = no
       break

   route = "/Channels/#{channelName}"

-  if isEqual and isNewlyCreated
+  # if changedFields.id is exist so user has set custom settings for channel
+  # before and default settings changed by koding. If he change settings again
+  # and new settings same with default settings, there is an id in changedFields
+  # so we can update settings instead of doing nothing.
+  if isEqual and isNewlyCreated and not changedFields.id
     return kd.singletons.router.handleRoute route

   if isEqual and not isNewlyCreated
     deleteSettings channelId, channelSettings.id
       .then ->
         kd.singletons.router.handleRoute route
-  else if !isNewlyCreated
+  else if not isNewlyCreated or changedFields.id
     updateSettings channelId, changedFields
       .then ->
         kd.singletons.router.handleRoute route


[app][activity] removed extra slashes which are put for xss protection related improvement

--- client/landing/app/Applications/Activity.kdapplication/AppController.coffee
+++ client/landing/app/Applications/Activity.kdapplication/AppController.coffee
@@ -19,7 +19,7 @@
   @clearQuotes = clearQuotes = (activities)->

     return activities = for activityId, activity of activities
-      activity.snapshot = activity.snapshot?.replace /"/g, '\\\"'
+      activity.snapshot = activity.snapshot?.replace /"/g, '\"'
       activity

   constructor:(options={})->


permission error for filetree actions

permission error for filetree actions

--- client/landing/app/MainApp/filetree/controllers/findertreecontroller.coffee
+++ client/landing/app/MainApp/filetree/controllers/findertreecontroller.coffee
@@ -731,7 +731,7 @@

     notification.destroy() if notification

-    if details and not msg? and /Permission denied/.test details?.message
+    if details and not msg? and /Permission denied/i.test details?.message
       msg = "Permission denied!"

     style or= 'error' if details


fix puncutation

fix puncutation

--- client/landing/app/Applications/Account.kdapplication/account/deleteaccountview.coffee
+++ client/landing/app/Applications/Account.kdapplication/account/deleteaccountview.coffee
@@ -14,7 +14,7 @@
         times = 0
         ->
           if times is 0
-            @setTitle "Are you sure!"
+            @setTitle "Are you sure?!"
           if times is 1
             @setTitle "OK, go ahead :)"
           if times > 1


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/point.coffee
+++ src/point.coffee
@@ -626,7 +626,7 @@
     .scale(1/points.length)

   ###*
-
+  Generate a random point
   ###
   Point.random = ->


JStackTemplate: add template.details field to keep repo info about the template if there is

--- workers/social/lib/social/models/computeproviders/stacktemplate.coffee
+++ workers/social/lib/social/models/computeproviders/stacktemplate.coffee
@@ -93,17 +93,20 @@
       template        :
         content       : String
         sum           : String
+        details       : Object

       # Public keys of JCredentials
       credentials     : [ String ]

-  generateTemplateObject = (content)->
-
-    content = ''  unless typeof content is 'string'
+  generateTemplateObject = (content, details) ->
+
+    content  = ''  unless typeof content is 'string'
+    details ?= {}

     return {
       content
+      details
       sum: crypto.createHash 'sha1'
         .update content
         .digest 'hex'
@@ -113,7 +116,7 @@

   @create = permit 'create stack template',

-    success: (client, data, callback)->
+    success: (client, data, callback) ->

       { delegate } = client.connection

@@ -132,7 +135,7 @@
         extras      : data.extras      ? []
         connections : data.connections ? []
         accessLevel : data.accessLevel ? 'private'
-        template    : generateTemplateObject data.template
+        template    : generateTemplateObject data.template, data.templateDetails
         credentials : data.credentials ? []

       stackTemplate.save (err)->


added facebook support to qrcode view

added facebook support to qrcode view

--- Resources/kui/codigoqr.coffee
+++ Resources/kui/codigoqr.coffee
@@ -1,4 +1,4 @@
-childs =  [ K.jade('codigoqr.jade',{nombreSocio:'Daniel Perez', numeroSocio:'1221AA'}) ]
+childs =  [ K.jade('codigoqr.jade',{nombreSocio:Ti.App.facebookdata.name, numeroSocio:Ti.App.facebookdata.id}) ]

 exports.Class = View.extend


Convert to coffee class

Convert to coffee class

--- resources/assets/coffee/react/beatmap-discussions/beatmap-list.coffee
+++ resources/assets/coffee/react/beatmap-discussions/beatmap-list.coffee
@@ -21,23 +21,23 @@

 bn = 'beatmap-list'

-BeatmapDiscussions.BeatmapList = React.createClass
-  mixins: [React.addons.PureRenderMixin]
+class BeatmapDiscussions.BeatmapList extends React.PureComponent
+  constructor: (props) ->
+    super props
+
+    @state =
+      showingSelector: false

-  getInitialState: ->
-    showingSelector: false
-
-
-  componentDidMount: ->
+  componentDidMount: =>
     $(document).on 'click.beatmapList', @hideSelector

-  componentWillUnmount: ->
+  componentWillUnmount: =>
     $(document).off '.beatmapList'

-  render: ->
+  render: =>
     div
       className: "#{bn} #{"#{bn}--selecting" if @state.showingSelector}"
       a
@@ -51,7 +51,7 @@
         @props.beatmaps.map @beatmapListItem

-  beatmapListItem: (beatmap) ->
+  beatmapListItem: (beatmap) =>
     menuItemClasses = "#{bn}__item"
     menuItemClasses += " #{bn}__item--current" if beatmap.id == @props.currentBeatmap.id

@@ -64,14 +64,14 @@
       el BeatmapDiscussions.BeatmapListItem, beatmap: beatmap, mode: 'version'

-  hideSelector: (e) ->
+  hideSelector: (e) =>
     return unless @state.showingSelector
     return if $(e.target).closest('.js-beatmap-list-selector').length

     @setSelector false

-  setSelector: (state) ->
+  setSelector: (state) =>
     return if @state.showingSelector == state

     Blackout.toggle(state)
@@ -79,13 +79,13 @@
     @setState showingSelector: state

-  selectBeatmap: (e) ->
+  selectBeatmap: (e) =>
     e.preventDefault()

     $.publish 'beatmap:select', id: parseInt(e.currentTarget.dataset.id, 10)

-  toggleSelector: (e) ->
+  toggleSelector: (e) =>
     e.preventDefault()

     @setSelector !@state.showingSelector


And then forgot to cast it to integer

And then forgot to cast it to integer

--- resources/assets/coffee/react/beatmap-discussions/beatmap-list.coffee
+++ resources/assets/coffee/react/beatmap-discussions/beatmap-list.coffee
@@ -78,7 +78,7 @@

   selectBeatmap: (e) ->
-    $.publish 'beatmap:select', id: e.currentTarget.dataset.id
+    $.publish 'beatmap:select', id: parseInt(e.currentTarget.dataset.id, 10)

   toggleSelector: ->


Use ReviewView in appdetails

Use ReviewView in appdetails

--- client/app/Applications/Apps.kdapplication/Views/appdetailsview.coffee
+++ client/app/Applications/Apps.kdapplication/Views/appdetailsview.coffee
@@ -9,19 +9,21 @@
     @listenWindowResize()

     @slideShow = new KDCustomHTMLView
-      tagName   : "ul"
+      tagName   : "ul"
       pistachio : do ->
         slides = app.manifest.screenshots or []
-        tmpl = ''
+        tmpl = ''
         for slide in slides
           tmpl += "

"
         return tmpl
+
+    @reviewView = new ReviewView {}, app

   viewAppended:->

     @setTemplate @pistachio()
     @template.update()
-
+
     @_windowDidResize()

   _windowDidResize:=>
@@ -38,8 +40,6 @@
     else
       @parent.$('.profilearea').removeClass "cast-shadow"

-
-
   pistachio:->
     """
     About {{#(title)}}
@@ -48,4 +48,6 @@

{{> @slideShow}}

     Technical Stuff

+    Reviews
+
{{> @reviewView}}

     """


client: invitations: fixed undefined param cc/ @hakankaradis

--- client/home/lib/myteam/components/hometeamsendinvites/container.coffee
+++ client/home/lib/myteam/components/hometeamsendinvites/container.coffee
@@ -106,7 +106,7 @@
     if resendInvitations?.size
       notifyPendingInvites resendInvitations, invitations
     else
-      sendInvitations invitations, alreadyMemberInvitations
+      sendInvitations invitations

   handleResendInvitations = (invitations) ->


Updated middleSection.coffee to add setting-up environment part

--- client/landing/site.landing/coffee/teams/partials/middlesection.coffee
+++ client/landing/site.landing/coffee/teams/partials/middlesection.coffee
@@ -35,6 +35,28 @@
       tagName : 'p'
       partial : 'Bling bling fo shizzle velizzle, bow wow wow volutpizzle, fo shizzle quizzle, fo shizzle mah nizzle fo rizzle, mah home g-dizzle vel, arcu.'

+    @envSchema = new KDCustomHTMLView
+      cssClass : 'setting-up-steps'
+      partial  : ''
+
+    @envSchemaStepStart = new KDCustomHTMLView
+      tagName  : 'span'
+      partial  : 'Start with lorem ipsum'
+
+    @envSchema.addSubView @envSchemaStepStart
+
+    @envSchemaStepNext = new KDCustomHTMLView
+      tagName  : 'span'
+      partial  : 'Next: Do the lorem ipsum'
+
+    @envSchema.addSubView @envSchemaStepNext
+
+    @envSchemaStepFinal = new KDCustomHTMLView
+      tagName  : 'span'
+      partial  : 'Voila! Env is ready to rock!'
+
+    @envSchema.addSubView @envSchemaStepFinal
+
     @gitHubTitle = new KDCustomHTMLView
       tagName : 'h2'
       partial : 'GitHub Integration'
@@ -63,6 +85,7 @@

       {{> @envTitle}}
       {{> @envDesc}}
+      {{> @envSchema}}

       {{> @gitHubTitle}}
       {{> @gitHubDesc}}


[IMPAC-768] - Include the new fields for recurring to create a new transaction. Also include workaround that get the first contact id and include it for the forecast transactions

--- src/components/widgets/accounts-cash-projection/accounts-cash-projection.directive.coffee
+++ src/components/widgets/accounts-cash-projection/accounts-cash-projection.directive.coffee
@@ -115,6 +115,7 @@
     hide: -> this.display = false

   $scope.addForecastPopup.createTransaction = (trx) ->
+    console.log('trx: ', trx)
     BoltResources.create(
       w.metadata.bolt_path,
       this.resourcesType,
@@ -126,9 +127,15 @@
         transaction_date: moment().format('YYYY-MM-DD'),
         due_date: moment(trx.datePicker.date).format('YYYY-MM-DD'),
         status: 'FORECAST',
-        currency: w.metadata.currency
+        currency: w.metadata.currency,
+        recurring: trx.recurring,
+        recurring_pattern: trx.recurring_pattern,
+        recurring_end_date: if trx.recurring_end_date then moment(trx.recurring_end_date).format('YYYY-MM-DD') else null
       },
-      { company: { data: { type: 'companies', id: $scope.firstCompanyId } } }
+      {
+        company: { data: { type: 'companies', id: $scope.firstCompanyId } },
+        contact: { data: { type: 'contacts', id: $scope.firstContactId } }
+      }
     ).then(-> ImpacWidgetsSvc.show(w))

   # == Chart Events Callbacks =====================================================================
@@ -191,6 +198,17 @@
       { metadata: _.pick(w.metadata, 'organization_ids') }
     ).then((response) -> $scope.firstCompanyId = response.data.data[0].id)

+    # Fetch contacts from Bolt and save first id
+    # TODO:Remove it, its only workaround to test feature for IMPAC-771
+    BoltResources.index(
+      w.metadata.bolt_path,
+      'contacts',
+      { metadata: _.pick(w.metadata, 'organization_ids') }
+    ).then((response) ->
+      if (response.data.data[0])
+        $scope.firstContactId = response.data.data[0].id
+    )
+
   # Executed after the widget and its settings are initialised and ready
   w.format = ->
     _highChartOptions =


Add *getStats command to Core

Add *getStats command to Core

--- handlers/core.coffee
+++ handlers/core.coffee
@@ -65,6 +65,12 @@
 				callback?()
 		when 'about'
 			api.replyTo message, __("This is Tim’s Chatbot.\nIt is licensed under the terms of the GNU Affero General Public License. You can obtain a copy of the Chatbot at https://github.com/wbbaddons/Tims-Chatbot."), no, callback
+		when 'getStats'
+			db.checkPermissionByMessage message, 'core.getStats', (hasPermission) ->
+				if hasPermission
+					api.replyTo message, __("Statistics:\nUp since: #{config.upSince} (#{process.uptime()} seconds)\nMemory Usage: #{process.memoryUsage().rss / 1024} KiB"), no, callback
+				else
+					callback?()
 		else
 			callback?()


make radio cleaner

make radio cleaner

--- src/radio.coffee
+++ src/radio.coffee
@@ -18,8 +18,6 @@
         $scope.selectedItem = item unless $scope.disabled

       $scope.shownItems = $scope.items
-
-      # run

     compile: (tElement, tAttrs) ->
       tAttrs.keyAttr ||= 'id'
@@ -42,18 +40,4 @@

         attrs.$observe 'required', (value) ->
           scope.required = value
-
-        scope.$watch 'selectedItem', ->
-          childScope = scope.$new()
-          childScope.item = scope.selectedItem
-          transcludeFn childScope, (clone) ->
-            if clone.text().trim() isnt ""
-              link = element[0].querySelector('a.w-chz-active')
-              angular.element(link).empty().append(clone)
-
-        # Hide drop down list on click elsewhere
-        $window.addEventListener 'click', (e) ->
-          parent = $(e.target).parents('div.w-chz')[0]
-          if parent != element[0]
-            scope.$apply(scope.hideDropDown)
-  ]
+]


use basic auth if available

use basic auth if available

--- src/robot.coffee
+++ src/robot.coffee
@@ -24,10 +24,10 @@
     @listeners   = []
     @loadPaths   = []
     @enableSlash = false
-    @connect     = Connect()

     @logger      = new Log process.env.HUBOT_LOG_LEVEL or "info"

+    @setupConnect()
     @loadAdapter adapterPath, adapter if adapter?

   # Public: Specify a router and callback to register as Connect middleware.
@@ -143,6 +143,19 @@
     for script in scripts
       @loadFile path, script

+  # Setup the Connect server's defaults
+  #
+  # Sets up basic authentication if parameters are provided
+  #
+  # Returns: nothing.
+  setupConnect: () ->
+    user = process.env.CONNECT_USER
+    pass = process.env.CONNECT_PASSWORD
+
+    @connect = Connect()
+    if user and pass
+      @connect.use Connect.basicAuth(user, path)
+
   # Load the adapter Hubot is going to use.
   #
   # path    - A String of the path to adapter if local.


fixup! setup: Improve Error message when child fails

--- src/setup.coffee
+++ src/setup.coffee
@@ -27,11 +27,11 @@
   else
     prog = cmd.split(' ')[0]
     args = cmd.split(' ').splice(1)
-  cmd = prog + ' ' + args.join(' ')
+  execCmd = prog + ' ' + args.join(' ')

   childoptions =
     env: env
-  debug 'participant process start', cmd
+  debug 'participant process start', execCmd
   child = child_process.spawn prog, args, childoptions
   returned = false
   child.on 'error', (err) ->
@@ -56,7 +56,7 @@
     debug 'child exited', code, signal
     return if returned
     returned = true
-    return callback new Error "Child '#{cmd}' (pid=#{child.pid}) exited with #{code} #{signal}"
+    return callback new Error "Child '#{execCmd}' (pid=#{child.pid}) exited with #{code} #{signal}"
   return child

 participantCommands = (graph, library, only, ignore) ->
@@ -82,7 +82,7 @@
       return cb err if err
       return cb err, { name: name, command: cmd, child: child }

-  debug 'starting participants', commands
+  debug 'starting participants', Object.keys(commands)
   names = Object.keys commands
   async.map names, start, (err, processes) ->
     return callback err if err


:memo: Update docs for Gutter events

:memo: Update docs for Gutter events

--- src/gutter.coffee
+++ src/gutter.coffee
@@ -25,16 +25,20 @@
       @emitter.emit 'did-destroy'
       @emitter.dispose()

-  # Calls your `callback` when the {Gutter}'s' visibility changes.
+  ###
+  Section: Event Subscription
+  ###
+
+  # Public: Calls your `callback` when the gutter's visibility changes.
   #
   # * `callback` {Function}
-  #  * `gutter` The {Gutter} whose visibility changed.
+  #  * `gutter` The gutter whose visibility changed.
   #
   # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
   onDidChangeVisible: (callback) ->
     @emitter.on 'did-change-visible', callback

-  # Calls your `callback` when the {Gutter} is destroyed
+  # Public: Calls your `callback` when the gutter is destroyed.
   #
   # * `callback` {Function}
   #


Guard against null package

Guard against null package

Closes #171

--- src/stars.coffee
+++ src/stars.coffee
@@ -49,7 +49,7 @@
       if error?
         callback(error)
       else if response.statusCode is 200
-        packages = body.filter (pack) -> pack.releases?.latest?
+        packages = body.filter (pack) -> pack?.releases?.latest?
         packages = packages.map ({readme, metadata, downloads}) -> _.extend({}, metadata, {readme, downloads})
         packages = _.sortBy(packages, 'name')
         callback(null, packages)


Fix classification send without favorite

--- app/models/classification.coffee
+++ app/models/classification.coffee
@@ -51,11 +51,12 @@
     Api.post(@url(), @toJSON(), arguments...).deferred

     recent = Recent.create subjects: @subject
-    favorite = Favorite.create subjects: @subject if @favorite

-    favoriteSend = favorite.send().deferred
-    favoriteSend.done ->
-      favorite.trigger 'send'
-      favorite.trigger 'is-new'
+    if @favorite
+      favorite = Favorite.create subjects: @subject
+      favoriteSend = favorite.send().deferred
+      favoriteSend.done ->
+        favorite.trigger 'send'
+        favorite.trigger 'is-new'

 module.exports = Classification


Added method for getting fields from a form and getting the form element.

--- src/Forms.coffee
+++ src/Forms.coffee
@@ -164,6 +164,9 @@

     getTemplate = Form.getTemplate = (template) -> Templates.getNamedInstance(name, template)

+    Form.getElement = -> getTemplate().$('form:first')
+    Form.getFieldElement = (name) -> Forms.getFieldElement(name, Form.getElement())
+
     return Form

   addRequiredLabel: ($label) ->


Fix wrong codo markup (@params -> @param)

--- app/src/utils/http_client.coffee
+++ app/src/utils/http_client.coffee
@@ -6,7 +6,7 @@

   ###
    @private This method should not be used outside this class and its descendants.
-   @params [Object] See jQuery.ajax() params.
+   @param [Object] See jQuery.ajax() params.
    @return [jqXHR] A jQuery.jqXHR
   ###
   jqAjax: (r) ->
@@ -43,7 +43,7 @@
             ... Handle error ...
           .done()

-    @params [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
+    @param [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
     @return [Q.Promise] A Q.Promise
   ###
   do: (r) -> Q(@jqAjax(r))
@@ -51,7 +51,7 @@
   ###
     Performs a HTTP GET request.

-    @params [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
+    @param [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
     @return [Q.Promise] A Q.Promise
     @see {HttpClient#do}
   ###
@@ -61,7 +61,7 @@
   ###
     Performs a HTTP POST request.

-    @params [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
+    @param [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
     @return [Q.Promise] A Q.Promise
     @see HttpClient#do
   ###
@@ -71,7 +71,7 @@
   ###
    Performs a HTTP POST request using a form url encoded body.

-   @params [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
+   @param [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
    @return [Q.Promise] A Q.Promise
    @see HttpClient#do
   ###
@@ -81,7 +81,7 @@
   ###
    Performs a HTTP PUT request.

-   @params [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
+   @param [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
    @return [Q.Promise] A Q.Promise
    @see HttpClient#do
   ###
@@ -91,7 +91,7 @@
   ###
    Performs a HTTP DELETE request.

-   @params [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
+   @param [Object] r A jQuery style request {http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings jQuery Ajax Setting}
    @return [Q.Promise] A Q.Promise
    @see HttpClient#do
   ###


[Fix] Handle user having no `emails` field

--- app/client/helpers.coffee
+++ app/client/helpers.coffee
@@ -16,7 +16,10 @@
 # helpers

 @currentPlayerEmails = ->
-  Meteor.user().emails.map (c) -> c.address
+  if Meteor.user().emails
+    Meteor.user().emails.map (c) -> c.address
+  else
+    []

 @currentPlayerId = ->
   # Session.get 'playerId' or localStorage.getItem 'playerId'


js state machine

js state machine

--- src/State.coffee
+++ src/State.coffee
@@ -224,15 +224,12 @@
       if typeof name == 'string'
         state = State(name)
         states.push(state)
-      else
-        name.each (item) ->
-
+      else
         `for(var i=0;i<name.length;i++){
           this.add(name[i]);
         }`

-    all: ->
-      states
+    all: -> states

 Transition = (machine, event, from, to, params) ->
   self =


js state machine

js state machine

--- src/State.coffee
+++ src/State.coffee
@@ -7,15 +7,9 @@
         else
           return false

-      if options.to == to_state
-        return true
-
-      if options.from == from_state
-        return true
-
-      if options.on == event.name
-        return true
-
+      if (options.to == to_state) || (options.from == from_state) || (options.on == event.name)
+        return true
+
     run: (params) ->
       block?.apply(machine.object, params)


js state machine

js state machine

--- src/State.coffee
+++ src/State.coffee
@@ -58,7 +58,8 @@
   self =
     transition: (options) ->
       guards.add(name, machine.object, options)
-      machine.states.add([options.from, options.to])
+      machine.states.push(options.from)
+      machine.states.push(options.to)

       return self

@@ -166,7 +167,9 @@
 Machine = (name, object, options, block) ->
   events = EventCollection()
   #states = StateCollection()
-    callbacks = CallbackCollection()
+  states = []
+
+  callbacks = CallbackCollection()

   machine_name = name


Render builds/not_found and repo/not_found in the next runloop run

This is done to make sure that if something else render just after
not_found, not_found will still be rendered.

--- assets/scripts/app/routes.coffee
+++ assets/scripts/app/routes.coffee
@@ -124,7 +124,8 @@
     # TODO: it would be nicer to do it with promises
     repo = @controllerFor('repo').get('repo')
     if repo && repo.get('isLoaded') && !repo.get('lastBuild')
-      @render('builds/not_found', outlet: 'pane', into: 'repo')
+      Ember.run.next =>
+        @render('builds/not_found', outlet: 'pane', into: 'repo')

 Travis.GettingStartedRoute = Ember.Route.extend
   setupController: ->
@@ -281,7 +282,8 @@
         proxy.set 'isLoading', false

         if repos.get('length') == 0
-          self.render('repos/not_found', outlet: 'main')
+          Ember.run.next ->
+            self.render('repos/not_found', outlet: 'main')
         else
           proxy.set 'content', repos.objectAt(0)


fixes to dumb brain

fixes to dumb brain

--- src/brain.coffee
+++ src/brain.coffee
@@ -27,12 +27,17 @@
   #
   # Returns int
   llen: (key) ->
-    Q(@data._private[@key key].length)
+    Q(@data._private[@key key]?.length)

   # Public: set the list value at the specified index
   #
   # Returns promise
   lset: (key, index, value) ->
+    key = @key key
+
+    if not @data._private[key]
+      @data._private[key] = []
+
     @data._private[@key key][index] = @serialize value
     Q @

@@ -40,34 +45,36 @@
   #
   # Returns promise
   linsert: (key, placement, pivot, value) ->
-    key = @key key
-    if @data._private[key] isnt undefined
-      index = _.find @data._private[key], pivot
-
-      if index
-        @data._private[key].splice 0, placement is 'AFTER' ? index + 1 : index, @serialize(value)
-
-    Q @
-
-  # Public: push a new value onto the left-side of the list
-  #
-  # Returns promise
-  lpush: (key, value) ->
     key = @key key
     if @data._private[key] is undefined
       @data._private[key] = []

-    @data._private[key].unshift(@serialize value)
-    Q @
-
-  # Public: push a new value onto the right-side of the list
-  #
-  # Returns promise
-  rpush: (key, value) ->
+    index = _.find @data._private[key], pivot
+
+    if index
+      @data._private[key].splice 0, placement is 'AFTER' ? index + 1 : index, @serialize(value)
+
+    Q @
+
+  # Public: push a new value onto the left-side of the list
+  #
+  # Returns promise
+  lpush: (key, value) ->
     key = @key key
     if @data._private[key] is undefined
       @data._private[key] = []

+    @data._private[key].unshift(@serialize value)
+    Q @
+
+  # Public: push a new value onto the right-side of the list
+  #
+  # Returns promise
+  rpush: (key, value) ->
+    key = @key key
+    if @data._private[key] is undefined
+      @data._private[key] = []
+
     @data._private[key].push(@serialize value)
     Q @

@@ -75,19 +82,19 @@
   #
   # Returns promise for list item
   lpop: (key) ->
-    Q(@deserialize(@data._private[@key key].shift()))
+    Q(@deserialize(@data._private[@key key]?.shift()))

   # Public: pop a value off of the right-side of the list
   #
   # Returns promise for list item
   rpop: (key) ->
-    Q(@deserialize(@data._private[@key key].pop()))
+    Q(@deserialize(@data._private[@key key]?.pop()))

   # Public: get a list item by index
   #
   # Returns promise for list item
   lindex: (key, index) ->
-    Q(@deserialize(@data._private[@key key][index]))
+    Q(@deserialize(@data._private[@key key]?[index]))

   # Public: get an entire list
   #
@@ -102,9 +109,9 @@
     key = @key key

     if end < 0
-      end = @data._private[key].length + end
-
-    Q(_.map(@data._private[key].slice(start, end + 1), @deserialize.bind(@)))
+      end = @data._private[key]?.length + end
+
+    Q(_.map(@data._private[key]?.slice(start, end + 1), @deserialize.bind(@)))

   # Public: remove values from a list
   #
@@ -149,17 +156,17 @@
   #
   # Returns promise for int
   scard: (key) ->
-    Q @data._private[@key key].length
+    Q @data._private[@key key]?.length

   # Public: Get and remove a random member from the set
   #
   # Returns promise for a set member
   spop: (key) ->
     key = @key key
-    index = _.random 0, @data._private[key].length - 1
-    item = @data._private[key][index]
-
-    @data._private[key].splice(1, index)
+    index = _.random 0, @data._private[key]?.length - 1
+    item = @data._private[key]?[index]
+
+    @data._private[key]?.splice(1, index)

     Q item

@@ -168,7 +175,7 @@
   # Returns promise for a set member
   srandmember: (key) ->
     key = @key key
-    Q @data._private[key][_.random 0, @data._private[key].length - 1]
+    Q @data._private[key]?[_.random 0, @data._private[key]?.length - 1]

   # Public: Get all the members of the set
   #
@@ -267,13 +274,13 @@
   #
   # Returns: promise for the value.
   hget: (table, key) ->
-    Q(@deserialize @data._private[@key table][key])
+    Q(@deserialize @data._private[@key table]?[key])

   # Public: Delete a field from a hash table
   #
   # Returns promise
   hdel: (table, key) ->
-    delete @data._private[@key table][key]
+    delete @data._private[@key table]?[key]
     Q @

   # Public: Get the whole hash table as an object.
@@ -384,7 +391,7 @@
     matchedUsers = @usersForRawFuzzyName(fuzzyName)
     lowerFuzzyName = fuzzyName.toLowerCase()
     for user in matchedUsers
-      return [user] if user.name.toLowerCase() is lowerFuzzyName
+      return Q([user]) if user.name?.toLowerCase() is lowerFuzzyName

     Q(matchedUsers)


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color.coffee
+++ src/color.coffee
@@ -911,10 +911,10 @@
     # => 0.5
     </pre></code>

-    @name transparentize
+    @name transparentize$
     @methodOf Color#

-    @returns {Color} A copy of the calling color with its alpha reduced by `amount`
+    @returns {Color} The calling color with its alpha reduced by `amount`
     ###
     transparentize$: (amount) ->
       @a = (@a - amount).clamp(0, 1)


pixie

pixie

--- src/color.coffee
+++ src/color.coffee
@@ -1,4 +1,3 @@
-test = true
 Color = (I) ->
   I ||= {}


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color.coffee
+++ src/color.coffee
@@ -56,13 +56,13 @@

     r = g = b = null

-    hueToRgb = (p, q, t) ->
-      t += 1 if t < 0
-      t -= 1 if t > 1
-
-      return p + (q - p) * 6 * t if t < 1/6
-      return q if t < 1/2
-      return p + (q - p) * (2/3 - t) * 6 if t < 2/3
+    hueToRgb = (p, q, hue) ->
+      hue += 1 if hue < 0
+      hue -= 1 if hue > 1
+
+      return p + (q - p) * 6 * hue if hue < 1/6
+      return q if hue < 1/2
+      return p + (q - p) * (2/3 - hue) * 6 if hue < 2/3
       return p

     if s == 0


cleaning up array constructions

cleaning up array constructions

--- src/color.coffee
+++ src/color.coffee
@@ -208,7 +208,7 @@

           hue *= 60

-        return [hue.round(), saturation, lightness, channels[3]]
+        return [hue, saturation, lightness, channels[3]]

       toString: -> self.rgba()


Started with the profile editor - needs to redo the before, success, error conditions

--- public/dreamcatcher/controllers/common/context_panel_controller.coffee
+++ public/dreamcatcher/controllers/common/context_panel_controller.coffee
@@ -107,5 +107,21 @@
       @model.user.follow({username: followUsername},@callback('updateFollowRelationship', el))
     else if currentRelationship is 'friends' or currentRelationship is 'following'
       @model.user.unfollow({username: followUsername},@callback('updateFollowRelationship', el))
+
+
+  '.context click': (el) ->
+    detailsEl = $('.view .details', @element)
+    if detailsEl.is ':visible'
+      detailsEl.slideDown 'fast'
+    else
+      detailsEl.slideDown 'fast'
+
+  '.change click': (el) ->
+    $('.view', @element).hide()
+    $('.edit', @element).show()
+
+  '.cancel click': (el) ->
+    $('.edit', @element).hide()
+    $('.view', @element).show()

 }