Don't count hidden nodes towards sankey space

Nodes which are not to be displayed should not be included when using up
the available vertical space in the sankey chart. Doing so causes the
node vertical margin to be added for nodes which will not be visible,
reducing the available space for those which are shown.

--- app/assets/javascripts/d3/sankey.coffee
+++ app/assets/javascripts/d3/sankey.coffee
@@ -886,6 +886,8 @@
       data = []

       for node in @node_list
+        continue unless node.should_show()
+
         column = node.get('column')

         data[column] ||= { sum: 0.0, nodes: 0, nodeCompensation: 0 }


Remove old js.

Remove old js.

--- app/assets/javascripts/groups.js.coffee
+++ app/assets/javascripts/groups.js.coffee
@@ -26,20 +26,6 @@

 #*** ajax for discussions on group page ***
 $ ->
-  if $("body.groups.show").length > 0 && $('#group-discussions').html() != null
-    $(document).on('click', '#group-closed-motions .pagination a', (e)->
-      unless $(this).parent().hasClass("gap")
-        $("#closed-motion-list").hide()
-        $("#closed-motions-loading").show()
-        $('#group-closed-motions').load($(this).attr('href'), ->
-          $("#closed-motion-list").show()
-          $("#closed-motions-loading").hide()
-        )
-        e.preventDefault()
-    )
-# discussions
-
-$ ->
   if $("body.groups.show").length > 0
     idStr = new Array
     idStr = $('#group-discussions').children().attr('class').split('_')
@@ -53,7 +39,7 @@
     $("#all-discussions-loading").addClass('hidden')

 $ ->
-  if $("body.groups.show").length > 0
+  if $("body.groups.show").length > 0 && $('#group-discussions').html() != null
     $(document).on('click', '#group-discussions .pagination a', (e)->
       unless $(this).parent().hasClass("gap")
         if Application.html5.supported


Convert number animation to use TweenJS

Convert number animation to use TweenJS

--- app/assets/javascripts/static.js.coffee
+++ app/assets/javascripts/static.js.coffee
@@ -5,10 +5,15 @@
 $ ->
   animateMetric = $(".metric-box strong").each ->
     $this = $(this)
-    jQuery(counter: 0).animate { counter: $this.text().replace(/\,/g, '') },
-      duration: 3000
-      easing: 'swing'
-      step: ->
-        $this.text Math.ceil(@counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
-        return
-    return
+    starting_point = 0
+    $target_count = parseInt($this.text().replace(/\,/g, ''))
+
+    # set the test to 0
+    $this.text(starting_point)
+    $this.counter = starting_point
+
+    tween = createjs.Tween.get($this).to( {counter: $target_count}, 3000 )
+
+    tween.addEventListener 'change', (event) ->
+      $this.text(Math.round($this.counter).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","))
+      return


Extract variable (refactor only)

Extract variable (refactor only)

--- app/assets/javascripts/static.js.coffee
+++ app/assets/javascripts/static.js.coffee
@@ -6,13 +6,14 @@
   Math.ceil(number).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")

 animateNumber = (element, target_count, duration) ->
-  jQuery(counter: 0).animate { counter: target_count - 40 },
+  step_one_target_count = target_count - 40
+  jQuery(counter: 0).animate { counter: step_one_target_count },
     duration: duration
     easing: "easeInOutQuint"
     step: ->
       element.text formatNumberWithCommaDelimiter(@counter)
     complete: ->
-      jQuery(counter: target_count - 40).animate { counter: (target_count) },
+      jQuery(counter: step_one_target_count).animate { counter: (target_count) },
         duration: 400
         easing: "easeOutQuint"
         step: ->


Pass lineNumber and lineSource in changed event

--- app/assets/javascripts/task_list.coffee
+++ app/assets/javascripts/task_list.coffee
@@ -149,12 +149,18 @@
     @field.dispatchEvent changeEvent

     unless changeEvent.defaultPrevented
-      @field.value = TaskList.updateSource(@field.value, index, item.checked)
+      { result, lineNumber, lineSource } =
+        TaskList.updateSource(@field.value, index, item.checked)
+
+      @field.value = result
       changeEvent = createEvent 'change'
       @field.dispatchEvent changeEvent
-      changedEvent = createEvent 'tasklist:changed',
+      changedEvent = createEvent 'tasklist:changed', {
         index: index
         checked: item.checked
+        lineNumber: lineNumber
+        lineSource: lineSource
+      }
       @field.dispatchEvent changedEvent

   # Static interface
@@ -220,7 +226,10 @@
       split("\n")
     index = 0
     inCodeBlock = false
-    result = for line in source.split("\n")
+    lineNumber
+    lineSource
+
+    result = for line, i in source.split("\n")
       if inCodeBlock
         # Lines inside of a code block are ignored.
         if line.match(@endFencesPattern)
@@ -232,13 +241,19 @@
       else if line in clean && line.match(@itemPattern)
         index += 1
         if index == itemIndex
+          lineNumber = i + 1
+          lineSource = line
           line =
             if checked
               line.replace(@incompletePattern, @complete)
             else
               line.replace(@completePattern, @incomplete)
       line
-    result.join("\n")
+    return {
+      result: result.join("\n")
+      lineNumber: lineNumber
+      lineSource: lineSource
+    }

 if typeof jQuery != 'undefined'
   jQuery.fn.taskList = (method) ->


Revert "fix issue with long folder names in file tree"

This reverts commit bbe6d580e70ec73b833e78cb733c62e1b24fc781.

Change-Id: I0dca6f0cc35a5b9358d9765a67f9019f443372a1
Reviewed-on: https://gerrit.instructure.com/56003
Tested-by: Jenkins
Reviewed-by: Sterling Cobb <7a57d889ea7f266299434459898a90c7f6a1ca4d@instructure.com>
QA-Review: Sterling Cobb <7a57d889ea7f266299434459898a90c7f6a1ca4d@instructure.com>
Tested-by: Sterling Cobb <7a57d889ea7f266299434459898a90c7f6a1ca4d@instructure.com>
Product-Review: Sterling Cobb <7a57d889ea7f266299434459898a90c7f6a1ca4d@instructure.com>
Reviewed-by: Dan Minkevitch <2591e5f46f28d303f9dc027d475a5c60d8dea17a@instructure.com>

--- app/coffeescripts/views/TreeView.coffee
+++ app/coffeescripts/views/TreeView.coffee
@@ -6,8 +6,7 @@
   'compiled/views/PaginatedCollectionView'
   'compiled/views/TreeItemView'
   'jst/TreeCollection'
-  'compiled/str/TextHelper'
-], (Backbone, $, _, preventDefault, PaginatedCollectionView, TreeItemView, collectionTemplate, textHelper) ->
+], (Backbone, $, _, preventDefault, PaginatedCollectionView, TreeItemView, collectionTemplate) ->

   class TreeView extends Backbone.View

@@ -51,26 +50,6 @@
     render: ->
       @renderSelf()
       @renderContents()
-      @truncateLinks()
-
-    truncateLinks: ->
-      truncLength = 37
-      items = @$('.truncate')
-      items.each ->
-        $this = $(this)
-        the_text = $this.text()
-        $this.attr('data-tooltip', '')
-
-        # only truncate text that hasn't already been truncated
-        # This is neccessary because the "render" function calls each node once,
-        # then a final render with all of the nodes. Yikes.
-        if (the_text.length > truncLength)
-          truncateText = textHelper.truncateText(the_text, {max: truncLength})
-          $this.text(truncateText)
-          $this.attr('title', the_text)
-
-        # Handles any folders that didn't get a tooltip added to them
-        $this.attr('title', the_text) unless $this.attr('title')?

     toggle: (event) ->
       # prevent it from bubbling up to parents and from following link
@@ -96,7 +75,6 @@
             $('.' + _this.selectedStyleClass).each((key, element) => $(element).removeClass(@selectedStyleClass))
             $(event.target).addClass(@selectedStyleClass)
           @onClick?(event, @model)
-        @$labelInner.addClass('truncate')

         $label = $("""
           <a


Returns early in lines decoration

Returns early in lines decoration

--- lib/minimap-git-diff-binding.coffee
+++ lib/minimap-git-diff-binding.coffee
@@ -74,6 +74,8 @@
           @decorateLines(lines, start, end, 'modified')

   decorateLines: (lines, start, end, status) ->
+    return if lines.length < end or lines.length < end
+
     for row in [start..end]
       lines[row - 1].className += " git-line-#{status}"


:bug: Fix injection of settings schema for registered plugins

--- lib/mixins/plugin-management.coffee
+++ lib/mixins/plugin-management.coffee
@@ -75,7 +75,9 @@
   # plugin - The plugin {Object}.
   registerPluginControls: (name, plugin) ->
     settingsKey = "minimap.plugins.#{name}"
-    @configDefaults.plugins[name] = true
+    @config.plugins.properties[name] =
+      type: 'boolean'
+      default: true

     atom.config.set(settingsKey, true) unless atom.config.get(settingsKey)?

@@ -94,4 +96,4 @@
   unregisterPluginControls: (name) ->
     atom.config.unobserve "minimap.plugins.#{name}"
     atom.workspaceView.off "minimap:toggle-#{name}"
-    delete @configDefaults.plugins[name]
+    delete @config.plugins.properties[name]


Bound compiler to nodejs requirejs module

--- node/compiler.coffee
+++ node/compiler.coffee
@@ -1,8 +1,26 @@
-require {
-  paths:
-    cs:              '../lib/requirejs/cs'
-    'coffee-script': '../lib/cs/coffee-script-iced'
-}, [
+var requirejs = require('requirejs');
+
+requirejs.config
+    # Use node's special variable __dirname to
+    # get the directory containing this file.
+    # Useful if building a library that will
+    # be used in node but does not require the
+    # use of node outside
+    baseUrl: __dirname
+
+    # Pass the top-level main.js/index.js require
+    # function to requirejs so that node modules
+    # are loaded relative to the top-level JS file.
+    nodeRequire: require
+
+    paths:
+      cs:              '../lib/requirejs/cs'
+      'coffee-script': '../lib/cs/coffee-script-iced'
+
+
+
+
+require [
   'cs!../src/metacoffee'
   'cs!./ErrorHandler'
 ], (MetaCoffee, ErrorHandler) ->
@@ -22,6 +40,6 @@
         tree, "trans", undefined, (m, i) ->
         throw new Error("Translation error - please tell Alex about this!")
       )
-    catch (e)
+    catch e
       return e.toString()
     return result


Do not destroy and re-draw the icon when its updated just update the data

--- client/landing/app/Applications/StartTab.kdapplication/AppView.coffee
+++ client/landing/app/Applications/StartTab.kdapplication/AppView.coffee
@@ -205,10 +205,12 @@
   createAppIcon:(app, appData)->

     log "ADDING:", appData
-    @appIcons[appData.name]?.destroy()
-    @appItemContainer.addSubView @appIcons[appData.name] = new StartTabAppThumbView
-      delegate : @
-    , appData
+    if @appIcons[appData.name]?
+      @appIcons[appData.name].setData appData
+    else
+      @appItemContainer.addSubView @appIcons[appData.name] = new StartTabAppThumbView
+        delegate : @
+      , appData

   createAppsIcons:(apps)->
     for app, appData of apps


District Map: Modification to selection of districts, error message shows when selecting territories.

--- app/scripts/controllers/district.coffee
+++ app/scripts/controllers/district.coffee
@@ -93,7 +93,6 @@
       if $scope.map_width is 960
         district_element.call($scope.zoomIn)
       else unless $scope.usMap.text().slice(0, 2) is $scope.state_district.state
-          console.log "Called zoomIn for state view"
           $("#map_holder").html('')
           $scope.drawMapByState($scope.state_to_FIPS[$scope.state_district.state])

@@ -295,12 +294,12 @@
       for one_district_state in ["AK", "DE", "MT", "ND", "SD", "VT", "WY"]
         if state is one_district_state
           setDist = true
-          $scope.state_district = {state: state, district: "0"}
-        if state is "DC"
-          setDist = true
-          $scope.state_district = {state: state, district: "98"}
+          return $scope.state_district = {state: state, district: "0"}
+      for territory in ["AS","DC", "FM", "GU", "MH", "MP", "PW", "PR"]
+        if state is territory
+          return $('.help-inline.error-text').text('Sorry, this map does not display data for Congressional Delegates.').delay(5500).fadeOut(500)
       if !setDist
-        $scope.state_district = {state: state, district: "1"}
+        return $scope.state_district = {state: state, district: "1"}

     $scope.defaultFocus()


Correction bug de connection kgb

Correction bug de connection kgb

--- app/scripts/services/UserService.coffee
+++ app/scripts/services/UserService.coffee
@@ -66,7 +66,7 @@

     hasRole: (roleName) ->
       @promise.then (user) ->
-        unless roleName? and user.roles.length > 0
+        if not roleName? and user.roles.length > 0
           return true
         for role in user.roles when role.nom is roleName
           return true


kodingAppsController requires manifest instead of name, so we need to fetch manifest before request to run

--- client/app/MainApp/filetree/controllers/findertreecontroller.coffee
+++ client/app/MainApp/filetree/controllers/findertreecontroller.coffee
@@ -394,8 +394,11 @@

     folder = nodeView.getData()
     folder.emit "fs.run.started"
-    name = FSHelper.trimExtension folder.path
-    @getSingleton('kodingAppsController').runApp name, =>
+    kodingAppsController = @getSingleton('kodingAppsController')
+
+    manifest = KodingAppsController.getManifestFromPath folder.path
+
+    kodingAppsController.runApp manifest, =>
       folder.emit "fs.run.finished"
       callback?()


Implemented XSS defensive check to file & folder rename workflow

--- client/finder/lib/filetree/controllers/nfindertreecontroller.coffee
+++ client/finder/lib/filetree/controllers/nfindertreecontroller.coffee
@@ -279,7 +279,8 @@
     nodeData = nodeView.getData()
     oldPath = nodeData.path
     nodeView.showRenameView (newValue)=>
-      return if newValue is nodeData.name
+      return  if newValue is nodeData.name
+      return  unless FSHelper.isValidFileName newValue

       nodeData.rename newValue, (err)=>
         if err then @notify null, null, err


clean up input values

clean up input values

--- SingularityUI/app/views/requestForm.coffee
+++ SingularityUI/app/views/requestForm.coffee
@@ -129,14 +129,15 @@
             requestObject.rackAffinity = @taggableList "#rackAffinity-#{ type }"

         if type in ['SCHEDULED', 'ON_DEMAND', 'RUN_ONCE']
-            requestObject.killOldNonLongRunningTasksAfterMillis = parseInt @$("#killOldNRL-#{ type }").val()
+            killOld = parseInt @$("#killOldNRL-#{ type }").val()
+            requestObject.killOldNonLongRunningTasksAfterMillis = killOld if killOld

         if type in ['ON_DEMAND', 'RUN_ONCE']
             requestObject.daemon = false

         if type is 'SCHEDULED'
+            schedule = @$('#schedule').val()
             retries  = parseInt @$('#retries-on-failure').val()
-            schedule = @$('#schedule').val()
             expectedRuntime = parseInt @$('#scheduled-expected-runtime').val()

             requestObject.schedule = schedule if schedule
@@ -146,10 +147,6 @@
         if type is 'SERVICE'
             requestObject.loadBalanced  = @$('#load-balanced').is ':checked'

-        # TO DO: Add validation
-        ## killOldNonLongRunningTasksAfterMillis
-        ## scheduledExpectedRuntimeMillis
-        ## waitAtLeastMillisAfterTaskFinishesForReschedule

         request = new Request requestObject
         request.url = "#{ config.apiRoot }/requests?user=#{ app.getUsername() }"


add serialization

add serialization

--- lib/ui/console.coffee
+++ lib/ui/console.coffee
@@ -6,13 +6,16 @@
 views =         require './views'

 module.exports =
+
+  uri: 'atom://julia-client/console'
+
   activate: (@client) ->
     @create()

     @subs = new CompositeDisposable

     @subs.add atom.workspace.addOpener (uri) =>
-      if uri is 'atom://julia-client/console'
+      if uri is @uri
         @c

     @client.handle 'info', (msg) =>
@@ -36,7 +39,10 @@
     @c.onEval (ed) => @eval ed
     @client.onWorking => @c.loading true
     @client.onDone => @c.loading false
+    @c.getURI = => @uri
     atom.views.getView(@c).classList.add 'julia'
+    @c.serialize = ->
+      deserializer: 'JuliaConsole'
     history.read().then (entries) =>
       @c.history.set entries


fix issue #388 - error msgs not being cleared on Next event

Errors would still be there after going back to a corrected step; now they're not.

--- app/assets/javascripts/hat-trick.js.coffee
+++ app/assets/javascripts/hat-trick.js.coffee
@@ -89,6 +89,7 @@
       # beforeSubmit: (data) =>
       #   log "Sending these data to the server: #{JSON.stringify data}"
       success: (serverData) =>
+        this.clearErrors()
         this.handleServerData serverData
         @form.trigger 'ajaxSuccess', serverData
         # log "Successful form POST; got #{JSON.stringify(serverData)}"


tutorial fixe (new polygons)

tutorial fixe (new polygons)


return a value

return a value

--- lib/y-richtext.coffee
+++ lib/y-richtext.coffee
@@ -210,14 +210,13 @@

       if delta.insert?
         insertHelper thisObj, position, delta.insert
-        length =
-          if typeof delta.insert == "string"
-            delta.insert.length
-          else if typeof delta.insert == "number"
-            1
-          else
-            console.warn "Got an unexpected value in delta.insert:",delta.insert
-            return
+        if typeof delta.insert == "string"
+          length = delta.insert.length
+        else if typeof delta.insert == "number"
+          length = 1
+        else
+          console.warn "Got an unexpected value in delta.insert:",delta.insert
+          return position

         from = thisObj._model.getContent("characters").ref position
         to = thisObj._model.getContent("characters").ref(


Fixed analytics checkout process

Fixed analytics checkout process

--- app/coffee/modules/common/analytics.coffee
+++ app/coffee/modules/common/analytics.coffee
@@ -156,7 +156,7 @@
             'position': 1,
         })
         @win.ga('ec:setAction','checkout', {'step': 1,})
-        @.trackEvent("ecommerce", "start-checkout", step, stepId)
+        @.trackEvent("ecommerce", "start-checkout", "start", 1)

     ecPurchase: (plan_id, plan_name, plan_price) ->
         return if not @.initialized
@@ -172,7 +172,7 @@
         })

         @win.ga('ec:setAction','checkout', {'step': 2,})
-        @.trackEvent("ecommerce", "start-checkout", step, stepId)
+        @.trackEvent("ecommerce", "end-checkout", "end", 2)

         @win.ga('ec:addProduct', {
             'id': plan_id,


Add identify hook for auth:logout

Add identify hook for auth:logout

--- app/coffee/modules/common/userpilot.coffee
+++ app/coffee/modules/common/userpilot.coffee
@@ -42,6 +42,9 @@
             @.identify()

         @rootScope.$on "auth:login", (ctx, user) =>
+            @.identify()
+
+        @rootScope.$on "auth:logout", (ctx, user) =>
             @.identify()

         @.initialized = true


will add reserve text to reserved events on calendar

fixes CNVS-32182

Test Plan:
- Create some apponitment groups
- As a student reserve a slot
- As a teacher hover over said reserved slot
- Notice the reserved text
- Repeat for multiple appointment slots and
  multiple users on an appointment slot

Change-Id: I6847a25a5f5661ff3a4e76a6514563b129ee2d8f
Reviewed-on: https://gerrit.instructure.com/91344
Tested-by: Jenkins
Reviewed-by: Clay Diffrient <9dff2e5c98626d20d2848250c411e8009465bb87@instructure.com>
QA-Review: David Tan <6283e310a2278fc51bdc4fb5974f70dd9c3366b9@instructure.com>
Product-Review: Steven Burnett <a0b450117c5d20a22d5c4d52bb8ae13adee003d8@instructure.com>

--- app/coffeescripts/calendar/Calendar.coffee
+++ app/coffeescripts/calendar/Calendar.coffee
@@ -237,7 +237,14 @@
         else
           I18n.t('event_event_title', 'Event Title:')

-      $element.attr('title', $.trim("#{timeString}\n#{$element.find('.fc-title').text()}\n\n#{I18n.t('calendar_title', 'Calendar:')} #{htmlEscape(event.contextInfo.name)}"))
+      reservedText = ""
+      if event.isAppointmentGroupEvent()
+        if event.reservedUsers == ""
+            reservedText = "\n\n#{I18n.t('Unreserved')}"
+        else
+          reservedText = "\n\n#{I18n.t('Reserved By: ')} #{event.reservedUsers}"
+
+      $element.attr('title', $.trim("#{timeString}\n#{$element.find('.fc-title').text()}\n\n#{I18n.t('Calendar:')} #{htmlEscape(event.contextInfo.name)} #{htmlEscape(reservedText)}"))
       $element.find('.fc-content').prepend($("#{htmlEscape I18n.t('calendar_title', 'Calendar:')} #{htmlEscape(event.contextInfo.name)}"))
       $element.find('.fc-title').prepend($("#{htmlEscape screenReaderTitleHint} "))
       $element.find('.fc-title').toggleClass('calendar__event--completed', event.isCompleted())


Edit buffalo text

Edit buffalo text

Removed parentheses from scientific name

--- app/lib/field-guide-content/buffalo.coffee
+++ app/lib/field-guide-content/buffalo.coffee
@@ -4,7 +4,7 @@
     A massive animal, the African buffalo is Africa’s only wild cattle species and is recognized as one of the “Big Five” mammals by safari goers. It is an imposing animal with its oxlike barrel shape, broad chest, bulky limbs, sizable head, and thick horns. African buffalo can vary greatly in coloring, but generally are dark gray or black to reddish-brown. Soft hairs fringe the large ears and the long tail, which ends in a tuft of hairs.
   '''

-  scientificName: '(Syncerus caffer)'
+  scientificName: 'Syncerus caffer'
   mainImage: 'assets/fieldguide-content/mammals/buffalo/buffalo-feature.jpg'
   conservationStatus: 'Least Concern' # valid options: low, medium, high. Or you can exclude it


Also unpack arguments in ipc-message-host message

--- atom/browser/lib/guest-view-manager.coffee
+++ atom/browser/lib/guest-view-manager.coffee
@@ -68,7 +68,8 @@
         embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{guest.viewInstanceId}", event, args...

   # Dispatch guest's IPC messages to embedder.
-  guest.on 'ipc-message-host', (_, channel, args...) ->
+  guest.on 'ipc-message-host', (_, packed) ->
+    [channel, args...] = packed
     embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{guest.viewInstanceId}", channel, args...

   # Autosize.


cleanup

cleanup

--- src/art/engine/elements/filters/filter_element.coffee
+++ src/art/engine/elements/filters/filter_element.coffee
@@ -35,7 +35,6 @@
       if _currentSize.eq filterSourceSize
         1
       else
-        # log filterSourceSizeRatio:_currentSize.div filterSourceSize
         _currentSize.div filterSourceSize

     elementSpaceSourceDrawArea: getterNew: (pending) ->
@@ -44,13 +43,8 @@
     baseDrawArea: getterNew: (pending) ->
       {_currentSize, _radius} = @getState pending

-      elementSpaceSourceDrawArea = @getElementSpaceSourceDrawArea pending
-
-      # log baseDrawArea:
-      #   elementSpaceSourceDrawArea: elementSpaceSourceDrawArea
-      #   baseDrawArea: elementSpaceSourceDrawArea.grow _radius
-
-      elementSpaceSourceDrawArea.grow _radius
+      @getElementSpaceSourceDrawArea pending
+      .grow _radius

     filterSourceElement:      getterNew: (pending) -> @_getFilterSourceElement pending
     filterSourceChildElement: getterNew: (pending) -> @_getFilterSourceElement pending, true
@@ -88,11 +82,9 @@

   fillShape: (target, elementToTargetMatrix, options) ->
     filterSource = @getFilterSourceElement()
+    elementSpaceDrawArea = @getElementSpaceDrawArea()

-    elementSpaceDrawArea = @elementSpaceDrawArea
     scale = elementToTargetMatrix.exactScaler
-
-    filterScratch = target.newBitmap elementSpaceDrawArea.size.add(@radius * 2).mul(scale)

     elementToFilterScratchMatrix = Matrix.translate elementSpaceDrawArea.location.neg.add @radius
     .scale scale
@@ -101,28 +93,14 @@
     .scale @getFilterSourceSizeRatio()
     .mul elementToFilterScratchMatrix

-    filterScratchToTargetMatrix = elementToFilterScratchMatrix.inv.mul elementToTargetMatrix
+    filterScratch = target.newBitmap elementSpaceDrawArea.size.add(@radius * 2).mul scale
+    .drawBitmap filterSourceTargetToFilterScratchMatrix, filterSource._currentDrawTarget

-    # log
-    #   scale: scale
-    #   targetToFilterSource: filterSource._currentToTargetMatrix.inv
-    #   elementSpaceDrawArea: elementSpaceDrawArea
-    #   filterSourceTargetToFilterScratchMatrix:filterSourceTargetToFilterScratchMatrix
-
-    filterScratch.drawBitmap filterSourceTargetToFilterScratchMatrix, filterSource._currentDrawTarget
-
-    # log fsBefore = filterScratch.clone()
-
-    filterScratch = @filter filterScratch, scale
-
-    # log FilterElement:
-    #   filterScratch: before: fsBefore, after: filterScratch
-    #   elementSpaceDrawArea: elementSpaceDrawArea
-    #   scale: scale
-    #   filterScratchToTargetMatrix:filterScratchToTargetMatrix
-    #   options: options
-
-    target.drawBitmap filterScratchToTargetMatrix, filterScratch, options
+    target.drawBitmap(
+      elementToFilterScratchMatrix.inv.mul elementToTargetMatrix
+      @filter filterScratch, scale
+      options
+    )

   ################
   # PRIVATE


Fix day position in month widget

Fix day position in month widget

--- coffee/views/datepicker_view.coffee
+++ coffee/views/datepicker_view.coffee
@@ -17,7 +17,8 @@

     for day in [month_begin.getDate()..month_end.getDate()]
       buttonClasses = if @active_date.getDate() is day then " active" else ""
-      liClasses = if day is 1 then "day-col-coffset-#{month_begin.getDay() - 1}" else ""
+      offsetWidth = if month_begin.getDay() is 0 then 6 else month_begin.getDay() - 1
+      liClasses = if day is 1 then "day-col-coffset-#{offsetWidth}" else ""
       buffer += "<li class=\"#{liClasses}\">
                    <button type=\"button\" class=\"day-button#{buttonClasses}\">
                      <time datetime=\"#{@active_date.getFullYear()}-#{@active_date.getMonth() + 1}-#{day}\">


more tests are less wrong

more tests are less wrong

--- coffeequate/tests/spec/nodes.coffee
+++ coffeequate/tests/spec/nodes.coffee
@@ -7,46 +7,46 @@
 			it "represent addition", ->
 				add = new operators.Add("2", "3")
 				expect(add.label).toBe("+")
-				expect(add.toLisp()).toBe("(2 + 3)")
+				expect(add.toLisp()).toBe("(+ 2 3)")

 				add = new operators.Add("2", "3", "4")
 				expect(add.label).toBe("+")
-				expect(add.toLisp()).toBe("(2 + 3 + 4)")
+				expect(add.toLisp()).toBe("(+ 2 3 4)")

 			it "require at least two children", ->
 				expect(-> new operators.Add()).toThrow(new Error("Add nodes must have at least one child."))

 			it "expand", ->
 				add = parse.stringToExpression("a + (b + c)")
-				expect(add.expand().toLisp()).toBe("(a + b + c)")
+				expect(add.expand().toLisp()).toBe("(+ a b c)")
 				add = parse.stringToExpression("a + (b + (c + 4))")
-				expect(add.expand().toLisp()).toBe("(4 + a + b + c)")
+				expect(add.expand().toLisp()).toBe("(+ 4 a b c)")
 				add = parse.stringToExpression("a + ((b + e) + (c + d))")
-				expect(add.expand().toLisp()).toBe("(a + b + c + d + e)")
+				expect(add.expand().toLisp()).toBe("(+ a b c d e)")
 				add = parse.stringToExpression("((a * b) + (c * d)) + ((e * f) + (g * h))")
-				expect(add.expand().toLisp()).toBe("((a * b) + (c * d) + (e * f) + (g * h))")
+				expect(add.expand().toLisp()).toBe("(+ (* a b) (* c d) (* e f) (* g h))")
 				add = parse.stringToExpression("c + b + a")
-				expect(add.expand().toLisp()).toBe("(a + b + c)")
+				expect(add.expand().toLisp()).toBe("(+ a b c)")
 				add = parse.stringToExpression("c + x + a")
-				expect(add.expand().toLisp()).toBe("(a + c + x)")
+				expect(add.expand().toLisp()).toBe("(+ a c x)")

 			it "simplify", ->
 				add = parse.stringToExpression("1 + 1")
-				expect(add.simplify().toLisp()).toBe("2")
+				expect(add.simplify().toString()).toBe("2")
 				add = parse.stringToExpression("x + x")
-				expect(add.simplify().toLisp()).toBe("(2 * x)")
+				expect(add.simplify().toLisp()).toBe("(* 2 x)")
 				add = parse.stringToExpression("x + x + y + y")
-				expect(add.simplify().toLisp()).toBe("((2 * x) + (2 * y))")
+				expect(add.simplify().toLisp()).toBe("(+ (* 2 x) (* 2 y))")
 				add = parse.stringToExpression("((2 * x) + (3 * x))")
-				expect(add.simplify().toLisp()).toBe("(5 * x)")
+				expect(add.simplify().toLisp()).toBe("(* 5 x)")
 				add = parse.stringToExpression("(x + 0)")
-				expect(add.simplify().toLisp()).toBe("x")
+				expect(add.simplify().toString()).toBe("x")
 				add = parse.stringToExpression("(x + 0 + 0 + y)")
-				expect(add.simplify().toLisp()).toBe("(x + y)")
+				expect(add.simplify().toLisp()).toBe("(+ x y)")
 				add = parse.stringToExpression("(x + (2 * x))")
-				expect(add.simplify().toLisp()).toBe("(3 * x)")
+				expect(add.simplify().toLisp()).toBe("(* 3 x)")
 				add = parse.stringToExpression("(-1 + 1**1)")
-				expect(add.simplify().toLisp()).toBe("0")
+				expect(add.simplify().toString()).toBe("0")

 			it "can be solved", ->
 				add = new operators.Add("x") # 0 = x
@@ -54,31 +54,31 @@
 				add = parse.stringToExpression("x + -1") # 1 = x
 				expect(add.solve("x")[0].evaluate()).toEqual(1)
 				add = parse.stringToExpression("x + -y") # y = x
-				expect(add.solve("x")[0].toLisp()).toEqual("y")
+				expect(add.solve("x")[0].toString()).toEqual("y")
 				add = parse.stringToExpression("x + y + 2") # y = x
-				expect(add.solve("x")[0].toLisp()).toEqual("(-2 + (-1 * y))")
+				expect(add.solve("x")[0].toLisp()).toEqual("(+ -2 (* -1 y))")

 				# Works so far. Let's try some multiplication.
 				add = parse.stringToExpression("2 * x + -y") # x = y/2
-				expect(add.solve("x")[0].toLisp()).toEqual("(1/2 * y)")
+				expect(add.solve("x")[0].toLisp()).toEqual("(* 1/2 y)")

 				# Quadratics?
 				add = parse.stringToExpression("-4 + x ** 2") # Simple quadratic.
-				expect(add.solve("x").sort().toLisp()).toEqual("-2,2")
+				expect(add.solve("x").sort().toString()).toEqual("-2,2")
 				add = parse.stringToExpression("-4 * x + x ** 2") # Slightly more complex quadratic.
-				expect(add.solve("x")[0].toLisp()).toEqual("0")
-				expect(add.solve("x")[1].toLisp()).toEqual("4")
+				expect(add.solve("x")[0].toString()).toEqual("0")
+				expect(add.solve("x")[1].toString()).toEqual("4")
 				add = parse.stringToExpression("(x + 3)**2")
-				expect(add.solve("x")[0].toLisp()).toEqual("-3")
+				expect(add.solve("x")[0].toString()).toEqual("-3")
 				expect(add.solve("x").length).toEqual(1)
 				add = parse.stringToExpression("(x + 3) * (x + -2)")
-				expect(add.solve("x")[0].toLisp()).toEqual("2")
-				expect(add.solve("x")[1].toLisp()).toEqual("-3")
+				expect(add.solve("x")[0].toString()).toEqual("2")
+				expect(add.solve("x")[1].toString()).toEqual("-3")

 				# Projectile motion for t?
 				add = parse.stringToExpression("u * t + a * t ** 2 * 0.5 + -s")
-				expect(add.solve("t").toLisp()).toEqual(
-					"((a ** -1) * ((((u ** 2) + (2 * a * s)) ** 1/2) + (-1 * u))),((a ** -1) * ((-1 * u) + (-1 * (((u ** 2) + (2 * a * s)) ** 1/2))))")
+				expect(add.solve("t").toString()).toEqual(
+					"(sqrt(u**2 + 2*a*s) + -1*u)/a,(-1*u + -1*sqrt(u**2 + 2*a*s))/a")

 			it "substitute values", ->
 				add = parse.stringToExpression("a + b + c")
@@ -109,7 +109,7 @@
 			it "represent multiplication", ->
 				mul = new operators.Mul("b", "3")
 				expect(mul.label).toBe("*")
-				expect(mul.toString()).toBe("(b * 3)")
+				expect(mul.toString()).toBe("b * 3")

 				mul = new operators.Mul("b", "3", "d")
 				expect(mul.toString()).toBe("(b * 3 * d)")


Social: clean-up some code

Social: clean-up some code

--- workers/social/lib/social/models/socialapi/channel.coffee
+++ workers/social/lib/social/models/socialapi/channel.coffee
@@ -35,7 +35,6 @@

   {fetchGroup} = require "./helper"

-
   @fetchActivity = secure (client, options = {}, callback)->
     fetchGroup client, (err, group)->
       return callback err if err
@@ -49,8 +48,7 @@
           groupName: group.slug

         {fetchChannelActivity} = require './requests'
-        fetchChannelActivity data, (err, activities)->
-          callback err, activities
+        fetchChannelActivity data, callback

   @fetchChannels = secure (client, options = {}, callback)->
     fetchGroup client, (err, group)->
@@ -60,9 +58,8 @@
         return callback err if err

         data =
-          groupName: slug.groupName
+          groupName: group.slug
           accountId: socialApiId

         {fetchGroupChannels} = require './requests'
-        fetchGroupChannels data, (err, activities)->
-          callback err, activities
+        fetchGroupChannels data, callback


fixed coffeelint errors on workers/social/lib/social/models/verificationtoken.coffee

--- workers/social/lib/social/models/verificationtoken.coffee
+++ workers/social/lib/social/models/verificationtoken.coffee
@@ -1,21 +1,22 @@
-{Module} = require 'jraphical'
+# coffeelint: disable=no_implicit_braces
+{ Module } = require 'jraphical'
 KodingError = require '../error'

 emailsanitize = require './user/emailsanitize'

 class PINExistsError extends Error
-  constructor:(message)->
-    return new PINExistsError(message) unless @ instanceof PINExistsError
-    Error.call @
+  constructor:(message) ->
+    return new PINExistsError(message) unless this instanceof PINExistsError
+    Error.call this
     @message = message
     @name = 'PINExistsError'

 module.exports = class JVerificationToken extends Module

-  {secure} = require 'bongo'
-  crypto   = require 'crypto'
-  hat      = require 'hat'
-  Tracker  = require './tracker'
+  { secure } = require 'bongo'
+  crypto     = require 'crypto'
+  hat        = require 'hat'
+  Tracker    = require './tracker'

   @share()

@@ -41,13 +42,13 @@
           ['update-email', 'verify-account', 'test-verify']
         ]

-  isAlive = (confirmation)->
+  isAlive = (confirmation) ->
     # 20 Min. default TTL for tokens
-    Math.round((Date.now()-confirmation.createdAt)/60000) < 20
+    Math.round((Date.now() - confirmation.createdAt) / 60000) < 20

-  @requestNewPin = (options, callback)->
+  @requestNewPin = (options, callback) ->

-    {action, email, subject, user, firstName, resendIfExists} = options
+    { action, email, subject, user, firstName, resendIfExists } = options

     email = emailsanitize email  if email

@@ -58,43 +59,43 @@

     if not email

-      callback new KodingError "E-mail is not provided!"
+      callback new KodingError 'E-mail is not provided!'

     else

-      @one {username, action}, (err, confirmation)=>
+      @one { username, action }, (err, confirmation) =>

         if confirmation and isAlive confirmation
           if resendIfExists
-            confirmation.sendEmail {username, subject, firstName, action}, callback
+            confirmation.sendEmail { username, subject, firstName, action }, callback
           else
             callback if err then err else new PINExistsError \
-              "PIN exists and not expired,
-              try again after 20 min for new PIN."
+              'PIN exists and not expired,
+              try again after 20 min for new PIN.'

           return

         # Remove all waiting pins for given action and email
-        @remove {username, action}, (err, count)=>
+        @remove { username, action }, (err, count) =>

           return console.warn err  if err

           if count > 0 then console.log "#{count} expired PIN removed."
-          else console.log "No such waiting PIN found."
+          else console.log 'No such waiting PIN found.'

-          @createNewPin {username, action, email}, (err, confirmation)->
+          @createNewPin { username, action, email }, (err, confirmation) ->
             return callback err  if err

-            confirmation.sendEmail {username, subject, firstName, action}, callback
+            confirmation.sendEmail { username, subject, firstName, action }, callback

-  @confirmByPin = (options, callback)->
+  @confirmByPin = (options, callback) ->

-    {pin, email, action, username} = options
+    { pin, email, action, username } = options

     email = emailsanitize email

-    @one {email, action, pin, username}, (err, confirmation)->
+    @one { email, action, pin, username }, (err, confirmation) ->

       return callback err  if err

@@ -109,29 +110,31 @@
         callback null, false

-  sendEmail: ({subject, firstName, username, action}, callback)->
+  sendEmail: ({ subject, firstName, username, action }, callback) ->

-    Tracker.track username, {to:@email, subject}, {firstName, @pin, action}
+    Tracker.track username, { to:@email, subject }, { firstName, @pin, action }
     callback null

-  @invalidatePin = (options, callback)->
-    {email, action, username} = options
+  @invalidatePin = (options, callback) ->
+    { email, action, username } = options

     email = emailsanitize email

-    @one {email, action, username}, (err, verify)->
+    @one { email, action, username }, (err, verify) ->
       return callback err  if err
-      return callback new KodingError "token not found" unless verify
+      return callback new KodingError 'token not found' unless verify
       verify.remove()
       callback null

-  @createNewPin = (options, callback)->
-    {username, action, email} = options
+  @createNewPin = (options, callback) ->
+    { username, action, email } = options
     pin = hat 16

     email = emailsanitize email

-    confirmation = new JVerificationToken {username, action, email, pin}
-    confirmation.save (err)-> callback err, confirmation
+    confirmation = new JVerificationToken { username, action, email, pin }
+    confirmation.save (err) -> callback err, confirmation
+
+


support view in room in IE < 11

support view in room in IE < 11

--- apps/artwork/client/view-in-room.coffee
+++ apps/artwork/client/view-in-room.coffee
@@ -53,14 +53,23 @@
     @$artwork.css @getRect(@$img)

   getRect: ($el) ->
-    _.pick($el[0].getBoundingClientRect(), 'height', 'width', 'top', 'right', 'bottom', 'left')
+    _.pick($el[0].getBoundingClientRect(), 'height', 'width', 'top', 'left')

   transitionIn: ->
     @$el.attr 'data-state', 'in'
     @$img.css visibility: 'hidden'
+
+    artworkTransformCSS = @getRect(@$placeholder)
+
+    # We need to manually compute in IE < 11
+    if navigator.userAgent.match('MSIE')
+      for key in ['top', 'height', 'width']
+        artworkTransformCSS[key] = Math.abs(artworkTransformCSS[key] * @roomScalingFactor())
+      artworkTransformCSS['left'] = Math.floor( ($(window).innerWidth() - artworkTransformCSS['width']) / 2)
+
     @$artwork.
       addClass('is-transition').
-      css(@getRect(@$placeholder)).
+      css(artworkTransformCSS).
       one($.support.transition.end, =>
         @$artwork.addClass('is-notransition')
         if @artworkScalingFactor() > 1
@@ -107,7 +116,7 @@
     viewportRatio   = @$el.width() / @$el.height()
     direction       = if viewportRatio > roomRatio then 'width' else 'height'
     factor          = @$el[direction]() / @$room[direction]()
-    Math.ceil(factor * 100) / 100
+    Math.round(factor * 100) / 100

   artworkScalingFactor: ->
     @__artworkFactor__ ?= if @artwork.hasDimension('diameter') and not @artwork.hasDimension('width')
@@ -118,7 +127,8 @@
       Math.round(width * @benchRatio)
     else
       1
-    @__artworkFactor__ / @$placeholder.width()
+    scailing = @__artworkFactor__ / @$placeholder.width()
+    Math.round(scailing * 100)/100

   # @return {Array} height, width
   getArtworkDimensions: ->
@@ -134,4 +144,4 @@
       $('.artwork-container').attr style: null # Remove hard-coded height
       @$body.removeClass @bodyClasses
       @$img.css visibility: 'visible'
-      ViewInRoom.__super__.remove.apply(this, arguments)
+      ViewInRoom.__super__.remove.apply(@, arguments)


pend before that?

pend before that?

--- test/lib/halbone.coffee
+++ test/lib/halbone.coffee
@@ -3,7 +3,7 @@
 halbone = rewire '../../lib/halbone'
 integration = require "../helpers/integration"

-describe 'halbone', ->
+xdescribe 'halbone', ->

   before (done) ->
     @api = halbone 'http://localhost:5000/__spooky'
@@ -12,7 +12,7 @@
   after ->
     integration.closeServer()

-  xit 'crawls links and creates models from the API data like a BOSS', (done) ->
+  it 'crawls links and creates models from the API data like a BOSS', (done) ->
     @api.new Backbone.Collection, 'articles.articles', (err, articles) ->
       articles.first().get('title').should.equal 'The art in Copenhagen is soo over'
       done()


SocialWorker: pass redisClient instance to bongo and usertracker

--- workers/social/lib/social/main.coffee
+++ workers/social/lib/social/main.coffee
@@ -23,6 +23,12 @@
 Object.defineProperty global, 'KONFIG', { value: KONFIG }
 { mq, email, social, mongoReplSet, socialapi } = KONFIG

+redisClient = require('redis').createClient(
+  KONFIG.monitoringRedis.split(':')[1]
+  KONFIG.monitoringRedis.split(':')[0]
+  {}
+)
+
 mongo = "mongodb://#{KONFIG.mongo}"  if 'string' is typeof KONFIG.mongo

 mqOptions = extend {}, mq
@@ -45,6 +51,7 @@
   mq          : broker
   mqConfig    : mqConfig
   metrics     : datadog
+  redisClient : redisClient

   kite          :
@@ -134,7 +141,7 @@
 app = express()

 do ->
-  usertracker.start()
+  usertracker.start redisClient

   # start monitoring nodejs metrics (memory, gc, cpu etc...)
   nodejsProfiler = new NodejsProfiler 'socialWorker'


Workspace: Used KDBlockingModalView when session disconnected.

--- client/landing/app/CommonViews/workspace/collaborativeworkspace.coffee
+++ client/landing/app/CommonViews/workspace/collaborativeworkspace.coffee
@@ -50,6 +50,9 @@
     @workspaceRef.on "child_added", (snapshot) =>
       log "everything is something happened", "child_added", snapshot.val(), snapshot.name()

+    @workspaceRef.on "child_changed", (snapshot) =>
+      log "everything is something happened", "child_changed", snapshot.val(), snapshot.name()
+
     @workspaceRef.on "child_removed", (snapshot) =>
       log "possible disconnection occured"

@@ -139,7 +142,7 @@
       title   = "Host disconnected"
       content = "It seems, host is disconnected from Firebase server. You cannot continue this session."

-    @disconnectedModal = new KDModalView
+    @disconnectedModal = new KDBlockingModalView
       title        : title
       content      : "<p>#{content}</p>"
       cssClass     : "host-disconnected-modal"


Workspace: Fix for join session.

Workspace: Fix for join session.

--- client/landing/app/CommonViews/workspace/collaborativeworkspace.coffee
+++ client/landing/app/CommonViews/workspace/collaborativeworkspace.coffee
@@ -189,8 +189,7 @@
           title           : "Join Session"
           cssClass        : "modal-clean-green"
           callback        : =>
-            @joinSession sessionKeyInput.getValue()
-            modal.destroy()
+            @handleJoinASessionFromModal sessionKeyInput.getValue(), modal
         Close             :
           title           : "Close"
           cssClass        : "modal-cancel"
@@ -200,10 +199,14 @@
       type        : "text"
       placeholder : "Paste new session key and hit enter to join"
       callback    : =>
-        @joinSession sessionKeyInput.getValue()
-        modal.destroy()
+        @handleJoinASessionFromModal sessionKeyInput.getValue(), modal

     callback modal
+
+  handleJoinASessionFromModal: (sessionKey, modal) ->
+    return unless sessionKey
+    @joinSession sessionKey
+    modal.destroy()

   showShareModal: (callback = noop) ->
     modal           = new KDModalView


Automated option sets

Automated option sets

--- test/option_sets.coffee
+++ test/option_sets.coffee
@@ -8,20 +8,20 @@
   all: '-a' in args
 options.all or= (not options.cache and not options.query_cache and not options.embed and not options.none)

-option_sets = []
-if options.all
-  option_sets.push({})
+OPTIONS = ['cache', 'query_cache', 'embed']
+gen = (keys) ->
+  results = {}
+  results[key] = true for key in keys
+  return results

-  option_sets.push({cache: true})
-  option_sets.push({query_cache: true})
-  option_sets.push({embed: true})
+combos = (array) ->
+  results = [{}]
+  results.push(gen([key])) for key in array # start with single keys
+  while array.length
+    keys = [array.pop()]
+    (keys.push(item); results.push(gen(keys))) for item in array
+  return results

-  option_sets.push({cache: true, query_cache: true})
-  option_sets.push({cache: true, embed: true})
-  option_sets.push({query_cache: true, embed: true})
+module.exports = if options.all then combos(OPTIONS) else [options]

-  option_sets.push({cache: true, query_cache: true, embed: true})
-else
-  option_sets = [options]
-
-module.exports = option_sets
+console.log module.exports


- [grunt] render only pages we need and exclude partials (files that starts with underscore)

--- tasks/grunt-nunjucks-2-html.coffee
+++ tasks/grunt-nunjucks-2-html.coffee
@@ -9,7 +9,7 @@
       files: [
         expand: true
         cwd: '<%= path.source.layouts %>/'
-        src: '**/*.nj'
+        src: ['**/*.nj', '!**/_*.nj']
         dest: '<%= path.build.root %>/'
         ext: '.html'
       ]


[grunt] allow Nunjucks' `config()` to set and get on paths in form of string or array, similar to `grunt.config()`

--- tasks/grunt-nunjucks-2-html.coffee
+++ tasks/grunt-nunjucks-2-html.coffee
@@ -245,31 +245,28 @@
            * defined on parent, it will extend it, unless `merge` set to false.
            * If no `value` will be provided, it will return value of specified property.
            * Works similar to `grunt.config()`
-           * @param  {string} prop         Prop name on which should be set `value`
-           *                               Returns `prop` if `value` not set
-           * @param  {*}      value        Value to set on specified `prop`
+           * @param  {string|array} prop   Prop name or path on which should be set `value`
+           * @param  {*}      value        Value to be set on specified `prop`
            * @param  {bool}   merge = true Should config extend already existing same prop or no
-           * @return {*}                   Value of `prop`
+           * @return {*}                   Value of `prop` if no `value` specified
           ###
           env.addGlobal 'config', (prop, value, merge = true) ->
             ctx           = this.ctx
             valueIsObject = typeof value == 'object' and value and not Array.isArray(value)

-            # Set in case `value` provided
+            # Set if `value` provided
             if value

               if not valueIsObject or not merge or not ctx.hasOwnProperty(prop)
-                ctx[prop] = value
-              else
-                if ctx.hasOwnProperty(prop)
-                  result = Object.assign(value, ctx[prop])
-                  ctx[prop] = result
+                _.set(ctx, prop, value)
+              else if ctx.hasOwnProperty(prop)
+                result = Object.assign(value, ctx[prop])
+                _.set(ctx, prop, result)

               return

             # Get if no `value` provided
-            else
-              return ctx[prop]
+            else return _.get(prop, prop)

           ###*
            * Get information about page and its childs from specified object.


[grunt] remove `todo` about `sprintf` limitations in `gettext` function, since it's no longer the case

--- tasks/grunt-nunjucks-2-html.coffee
+++ tasks/grunt-nunjucks-2-html.coffee
@@ -211,7 +211,6 @@

           ###*
           * Load string from current locale
-          * @note So far `sprintf` supports only named placeholders
           * @param {string}              string          String, which should be loaded
           * @param {string|object|array} placeholders... List of placeholders, object with named
           *                                              placeholders or arrays of placeholders
@@ -224,7 +223,6 @@

           ###*
            * Load string from specified locale
-           * @note So far `sprintf` supports only named placeholders
            * @param {string}              locale = currentLocale Locale, from which string should be loaded
            * @param {string}              string                 String, which should be loaded
            * @param {string|object|array} placeholders...        List of placeholders, object with named
@@ -238,7 +236,6 @@

           ###*
           * Load plural string from current locale
-          * @note So far `sprintf` supports only named placeholders
           * @param {string}              string          String, which should be loaded
           * @param {string}              stringPlural    Plural form of string
           * @param {number}              count           Count for detecting correct plural form
@@ -253,7 +250,6 @@

           ###*
            * Load plural string from specified locale
-           * @note So far `sprintf` supports only named placeholders
            * @param {string}              locale = currentLocale Locale, from which string should be loaded
            * @param {string}              string                 String, which should be loaded
            * @param {string}              stringPlural           Plural form of string
@@ -269,7 +265,6 @@

           ###*
           * Load string of specific context from current locale
-          * @note So far `sprintf` supports only named placeholders
           * @param {string}              context         Context of curret string
           * @param {string}              string          String, which should be loaded
           * @param {string|object|array} placeholders... List of placeholders, object with named
@@ -283,7 +278,6 @@

           ###*
            * Load string of specific context from specified locale
-           * @note So far `sprintf` supports only named placeholders
            * @param {string}              locale = currentLocale Locale, from which string should be loaded
            * @param {string}              context                Context of curret string
            * @param {string}              string                 String, which should be loaded
@@ -298,7 +292,6 @@

           ###*
           * Load plural string of specific context from current locale
-          * @note So far `sprintf` supports only named placeholders
           * @param {string}              context         Context of curret string
           * @param {string}              string          String, which should be loaded
           * @param {string}              stringPlural    Plural form of string
@@ -314,7 +307,6 @@

           ###*
            * Load plural string of specific context from specified locale
-           * @note So far `sprintf` supports only named placeholders
            * @param {string}              locale = currentLocale Locale, from which string should be loaded
            * @param {string}              context                Context of curret string
            * @param {string}              string                 String, which should be loaded


+ overwrite inspect to show the file whether loaded + add the exclude argument to toObject method * convert the virtual folder objects to the Resource object.

--- src/index.coffee
+++ src/index.coffee
@@ -2,11 +2,14 @@
 File              = require 'custom-file/lib/advance'
 inherits          = require 'inherits-ex/lib/inherits'
 getPrototypeOf    = require 'inherits-ex/lib/getPrototypeOf'
+setPrototypeOf    = require 'inherits-ex/lib/setPrototypeOf'
 matter            = require 'front-matter-markdown/lib/'
 loadCfgFile       = require 'load-config-file'
 loadCfgFolder     = require 'load-config-folder'
 extend            = require 'util-ex/lib/_extend'
 isObject          = require 'util-ex/lib/is/type/object'
+isString          = require 'util-ex/lib/is/type/string'
+isArray           = require 'util-ex/lib/is/type/array'
 defineProperty    = require 'util-ex/lib/defineProperty'
 Promise           = require 'bluebird'
 createFileObject  = require './create-file-object'
@@ -59,12 +62,33 @@
     path = fs.path if fs and !path
     return

+  # TODO: howto validate a virtual file?
+  # fake a stat object.
+  # currently has only virtual folder object. (no virtual file yet)
+  #_validate: (file)-> file.hasOwnProperty('contents') and file.contents?
+  inspect: ->
+    name = 'File'
+    if @loaded()
+      name = 'Folder' if @isDirectory()
+    else
+      name += '?'
+    '<'+ name + ' ' + @_inspect() + '>'
+
   isDirectory: ->
     if @hasOwnProperty('isDir') and @isDir isnt undefined
       result = @isDir
     else
       result = super()
     result
+
+  toObject: (options, aExclude)->
+    if isString aExclude
+      aExclude = [aExclude]
+    else if !isArray aExclude
+      aExclude = []
+    aExclude.push 'contents' unless @hasOwnProperty('contents')
+    aExclude.push 'stat' unless @hasOwnProperty('stat')
+    @exportTo(options, aExclude)

   getContentSync: (aOptions)->
     aOptions = {} unless isObject aOptions
@@ -85,23 +109,31 @@
     # TODO:whether export the non-enumerable $compiled attribute?
     result

+  convertVirtualFolder: (aContents)->
+    for k in aContents
+      if k.path?
+        k.base = @path
+        setPrototypeOf k, @
+    aContents
+
   loadConfig: (aOptions, aContents, done)->
     that = @
     processCfg = (err, aConfig)->
       return done(err) if err
       if aConfig
         that.assign aConfig
-        aContents = aConfig.contents if aConfig.contents
-        if aOptions.recursive and that.isDirectory()
-          aContents = aContents.filter (f)->f.isDirectory()
-          Promise.map aContents, (f)->
-            f.load aOptions
-          .nodeify (err, result)->
-            done(err, aConfig)
-        else
-          done(err, aConfig)
-      else
-        done(err, aConfig)
+        if that.isDirectory()
+          if aConfig.contents #virtual folder
+            that.convertVirtualFolder(result.contents)
+            aContents = result.contents
+          if aOptions.recursive
+            aContents = aContents.filter (f)->f.isDirectory()
+            Promise.map aContents, (f)->
+              f.load aOptions if f instanceof Resource
+            .nodeify (err, result)->
+              done(err, aConfig)
+            return
+      done(err, aConfig)
       return

     if !aOptions.stat.isDirectory()
@@ -139,10 +171,14 @@
     if result
       @assign result
       @$cfgPath = result.$cfgPath if result.$cfgPath
-      aContents = result.contents if result.contents
-      if aOptions.recursive and @isDirectory()
-        for vFile in aContents
-          vFile.loadSync aOptions if vFile.isDirectory()
+      if @isDirectory()
+        if result.contents #virtual folder
+          @convertVirtualFolder(result.contents)
+          aContents = result.contents
+        if aOptions.recursive
+          aContents = aContents.filter (f)->f.isDirectory()
+          for vFile in aContents
+            vFile.loadSync aOptions if vFile instanceof Resource
     result

   _getBufferSync: (aFile)->


Ensure after always set

Ensure after always set

--- src/index.coffee
+++ src/index.coffee
@@ -103,6 +103,8 @@
       after   = params
       params  = null

+    after = (->) if after is null
+
     @getInstance table, (db, collection) =>
       collection.count params, (error, results) =>
         if error


Remove extra eof line feed

Remove extra eof line feed

--- src/index.coffee
+++ src/index.coffee
@@ -187,4 +187,3 @@
       mapLimit versions, @config.opts.workers, @resizeAndUpload.bind(@), (err, versions) =>
         return cb err if err
         return cb null, versions, @meta
-


try send to namespace?

try send to namespace?

--- src/index.coffee
+++ src/index.coffee
@@ -59,8 +59,7 @@
         io.of('/teacher').emit 'render', onlineData()

     socket.on 'edit', (data) ->
-        console.log "aaaaaaaaaaaaaaaaaaaaa huge and stupid string that should be in the logsaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-        io.of('/teacher').emit 'render', data
+        io.of('/teacher').send 'render', data

     socket.on 'disconnect', (data) ->
         online = onlineData()


Normalize callback parameters for catching errors

--- src/index.coffee
+++ src/index.coffee
@@ -51,8 +51,7 @@
         else
           params._id = ensureObjectId params._id
     catch exception
-      console.log "Error with preparing params for find: #{exception}"
-      return after []
+      return after "Error with preparing params for find: #{exception}", []

     @getInstance table, (collection) =>
       cursor = collection.find params
@@ -62,71 +61,49 @@
       cursor.skip  options.skip  if options.skip

       cursor.toArray (error, results) =>
-        if error
-          console.log "Error with fetching documents: #{error}"
-          return after []
-
-        after results
+        return after "Error with fetching documents: #{error}", [] if error
+        return after null, results

   save: (table, params, after = ->) ->
     try
       params._id = ensureObjectId params._id if params._id?
     catch exception
-      console.log "Error with preparing params for save: #{exception}"
-      return after false
+      return after "Error with preparing params for save: #{exception}", false

     @getInstance table, (collection) =>
       collection.save params, safe: true, (error, results) =>
-        if error
-          console.log "Error with saving data: #{error}"
-          return after false
-
-        after if results is 1 then params else results
+        return after "Error with saving data: #{error}", false if error
+        return after null, if results is 1 then params else results

   count: (table, params, after) ->
-    if isFunction params
-      after   = params
-      params  = null
-
-    after = (->) if after is null
+    [params, options, after] = normalizeArguments params, after

     @getInstance table, (collection) =>
       collection.count params, (error, results) =>
-        if error
-          console.log "Error with fetching counts: #{error}"
-          return after false
-
-        after parseInt results, 10
+        return after "Error with fetching counts: #{error}", false if error
+        return after null, parseInt results, 10

   findById: (table, id, after = ->) ->
     try
       params = _id: ensureObjectId id
     catch exception
-      console.log "Error with preparing params for findById: #{exception}"
-      return after false
+      return after "Error with preparing params for findById: #{exception}", false

     @getInstance table, (collection) =>
       collection.find(params).toArray (error, results) =>
-        if error
-          console.log "Error with fetching document by id: #{error}"
-          return after false
-
-        after if results and results.length is 1 then results[0] else false
+        return after "Error with fetching document by id: #{error}", false if error
+        return after null, if results and results.length is 1 then results[0] else false

   removeById: (table, id, after = ->) ->
     try
       params = _id: ensureObjectId id
     catch exception
-      console.log "Error with preparing params for removeById: #{exception}"
-      return after false
+      return after "Error with preparing params for removeById: #{exception}", false

     @getInstance table, (collection) =>
       collection.findAndRemove params, (error, results) =>
-        if error
-          console.log "Error with removing document by id: #{error}"
-          return after false
-
-        after results
+        return after "Error with removing document by id: #{error}", false if error
+        return after null, results

   Long: (number)          -> new mongodb.Long number
   ObjectID: (hex)         -> ensureObjectId hex


[FIX] Authorization with <audio> * need https://github.com/flyingrub/cozy-data-system/commit/b26ed5ce1664843accc739f051d0286a727f4444

--- src/index.coffee
+++ src/index.coffee
@@ -165,6 +165,6 @@
     client.getToken (err, auth) ->
         return callback err if err

-        auth = "#{auth.appName}:#{auth.token}"
-        url = "#{window.location.protocol}//#{auth}@#{host}#{path}"
+        auth = "Basic " + btoa "#{auth.appName}:#{auth.token}"
+        url = "#{window.location.protocol}//#{host}#{path}?authorization=#{auth}"
         callback null, encodeURI(url)


Fix typo

Fix typo

--- src/index.coffee
+++ src/index.coffee
@@ -239,7 +239,7 @@
     .option '-d, --debug', 'Increase verbosity and error detail'
     .option '-k, --keyspace <keyspace>', 'Cassandra keyspace used for migration and schema_version table'
     .option '-t, --target-version <version>', 'Maximum migration version to apply (default runs all migrations)'
-    .option '-h, --hosts <hosts>', 'A comma separated list of cassandra hosts', parseCassandrahosts
+    .option '-h, --hosts <hosts>', 'A comma separated list of cassandra hosts', parseCassandraHosts
     .parse(process.argv)

   configFile = _(program.args).last()


https support

https support

added the https and fs deps

--- src/index.coffee
+++ src/index.coffee
@@ -2,6 +2,8 @@
 es = require("event-stream")
 util = require("gulp-util")
 http = require("http")
+https = require("https")
+fs = require("fs")
 connect = require("connect")
 liveReload = require("connect-livereload")
 tiny_lr = require("tiny-lr")


Fixing some comments.

Fixing some comments.

--- www/src/theoricus/core/process.coffee
+++ www/src/theoricus/core/process.coffee
@@ -75,9 +75,10 @@
         msg += "`#{action}` must return a View instance."
         console.error msg

+    # sets the callback
     @controller.after_render = @after_run
-    # executes the action passing all arguments, the callback will be executed
-    # with the resulting view
+
+    # executes action
     @controller[ action ] @params


Rename layout_location to panel_side

Rename layout_location to panel_side

Hopefully clearer what this is referencing, given new SidePanel setup

--- bokehjs/src/coffee/models/axes/axis.coffee
+++ bokehjs/src/coffee/models/axes/axis.coffee
@@ -228,7 +228,7 @@
     [nx, ny] = @mget('normals')
     [xoff, yoff]  = @mget('offsets')
     dim = @mget('dimension')
-    side = @mget('layout_location')
+    side = @mget('panel_side')
     orient = @mget('major_label_orientation')
     if _.isString(orient)
       angle = _angle_lookup[side][orient]
@@ -257,7 +257,7 @@
     [sx, sy] = @plot_view.map_to_screen(x, y, @_x_range_name, @_y_range_name)
     [nx, ny] = @mget('normals')
     [xoff, yoff]  = @mget('offsets')
-    side = @mget('layout_location')
+    side = @mget('panel_side')
     orient = 'parallel'
     angle = _angle_lookup[side][orient]
     standoff = (@_tick_extent() + @_tick_label_extent() + @mget('axis_label_standoff'))
@@ -290,7 +290,7 @@

     dim = @mget('dimension')
     coords = @mget('tick_coords').major
-    side = @mget('layout_location')
+    side = @mget('panel_side')
     orient = @mget('major_label_orientation')
     labels = @mget('formatter').doFormat(coords[dim])
     @visuals.major_label_text.set_value(ctx)
@@ -325,7 +325,7 @@
   _axis_label_extent: () ->
     extent = 0

-    side = @mget('layout_location')
+    side = @mget('panel_side')
     axis_label = @mget('axis_label')
     orient = 'parallel'
     ctx = @plot_view.canvas_view.ctx
@@ -391,7 +391,7 @@
   }

   @internal {
-    layout_location: [ p.Any ]
+    panel_side: [ p.Any ]
   }

   initialize: (attrs, options)->
@@ -405,7 +405,7 @@
     @add_dependencies('rule_coords', this, ['computed_bounds', 'side'])

     @define_computed_property('tick_coords', @_tick_coords, false)
-    @add_dependencies('tick_coords', this, ['computed_bounds', 'layout_location'])
+    @add_dependencies('tick_coords', this, ['computed_bounds', 'panel_side'])

     @define_computed_property('ranges', @_ranges, true)
     @define_computed_property('normals', (() -> @panel._normals), true)
@@ -415,10 +415,10 @@
   add_panel: (side) ->
     @panel = new SidePanel.Model({side: side})
     @panel.attach_document(@document)
-    @set('layout_location', side)
+    @set('panel_side', side)

   _offsets: () ->
-    side = @get('layout_location')
+    side = @get('panel_side')
     [xoff, yoff] = [0, 0]
     frame = @get('plot').get('frame')

@@ -539,7 +539,7 @@
   _get_loc: (cross_range) ->
     cstart = cross_range.get('start')
     cend = cross_range.get('end')
-    side = @get('layout_location')
+    side = @get('panel_side')

     if side == 'left' or side == 'below'
       loc = 'start'


ContextMenu: removed hardcoded max/min width values

--- src/components/contextmenu/contextmenu.coffee
+++ src/components/contextmenu/contextmenu.coffee
@@ -7,8 +7,8 @@
   constructor:(options = {}, data)->

     options.cssClass        = @utils.curry "jcontextmenu", options.cssClass
-    options.menuMaxWidth  or= 272
-    options.menuMinWidth  or= 172
+    options.menuMaxWidth  or= "auto"
+    options.menuMinWidth  or= "auto"
     options.menuWidth     or= 172
     options.offset        or= {}
     options.offset.left   or= 0


payment: fix pack selector parameter

payment: fix pack selector parameter

--- client/Main/VirtualizationController.coffee
+++ client/Main/VirtualizationController.coffee
@@ -354,11 +354,8 @@
       productForm.setCurrentSubscriptions subscriptions

     productForm.on 'PackOfferingRequested', (subscription) ->
-      options = targetOptions: selector: tags: 'vm'
-
-      KD.getGroup().fetchProducts 'pack', options, (err, packs) ->
+      KD.getGroup().fetchProducts 'pack', tags: 'vm', (err, packs) ->
         return  if KD.showError err
-
         productForm.setContents 'packs', packs

     workflow = new PaymentWorkflow


 Merge branch 'master.activity.pinnedlist' into 'master'

activity: show/hide pinned list when activity list is populated

--- client/Social/Activity/AppController.coffee
+++ client/Social/Activity/AppController.coffee
@@ -209,7 +209,10 @@
       {roles} = KD.config
       group   = groupObj?.slug

-      pinnedListView = view.feedWrapper.pinnedListController.getListView()
+      {togglePinnedList, pinnedListController} = view.feedWrapper
+      pinnedListView = pinnedListController.getListView()
+
+      togglePinnedList.hide()
       pinnedListView.hide()

       if not to and (searchText or @searchText)
@@ -241,7 +244,9 @@
         @once "publicFeedFetched_#{eventSuffix}", setFeedData
         @fetchPublicActivities options
         @setWarning()
-        pinnedListView.show()
+        if pinnedListController.getItemCount()
+          togglePinnedList.show()
+          pinnedListView.show()
         return

       else


activity: define `ActivityAppController::delete` method

--- client/Social/Activity/AppController.coffee
+++ client/Social/Activity/AppController.coffee
@@ -40,6 +40,13 @@

     {socialapi} = KD.singletons
     socialapi.message.reply {body, messageId}, callback
+
+
+  delete: ({id}, callback) ->
+
+    {socialapi} = KD.singletons
+    socialapi.message.delete {id}, callback
+

   fetch: (options = {}, callback = noop) ->


AceFindAndReplaceView: include missing jquery

--- client/ace/lib/acefindandreplaceview.coffee
+++ client/ace/lib/acefindandreplaceview.coffee
@@ -5,6 +5,7 @@
 KDMultipleChoice    = kd.MultipleChoice
 JView               = require 'app/jview'
 _                   = require 'lodash'
+$                   = require 'jquery'
 keycode             = require 'keycode'

 module.exports = class AceFindAndReplaceView extends JView


Environments: disable /Environments for non super-admins

--- client/environments/lib/routehandler.coffee
+++ client/environments/lib/routehandler.coffee
@@ -1,11 +1,18 @@
 kd             = require 'kd'
+globals        = require 'globals'

 lazyrouter     = require 'app/lazyrouter'
+checkFlag      = require 'app/util/checkFlag'
 registerRoutes = require 'app/util/registerRoutes'

-handleSection = (callback)->
+handleSection = (callback) ->
   kd.getSingleton('groupsController').ready ->
+
+    if globals.config.environment isnt 'dev' or not checkFlag 'super-admin'
+      kd.getSingleton('router').handleRoute '/'
+      return
+
     kd.singleton('appManager').open 'Environments', callback

 handle = ({params:{section}}) ->


broker connect/disconnect event / micro emitter is a mixin / broker autoReconnect option / misc other improvements

--- client/landing/app/MainApp/mq.config.coffee
+++ client/landing/app/MainApp/mq.config.coffee
@@ -9,5 +9,6 @@
       sockURL       : broker.sockJS
       authEndPoint  : broker.auth
       vhost         : broker.vhost
+      autoReconnect : yes
     }
     new Broker broker.apiKey, brokerOptions


Add image chooser for logo

Add image chooser for logo

--- client/skr/screens/locations/Locations.cjsx
+++ client/skr/screens/locations/Locations.cjsx
@@ -16,6 +16,9 @@
                 <LC.Input sm=6 name='name' model={@location} />
             </BS.Row>
             <BS.Row>
+                <LC.ImageSaver label='Logo' sm=4 model={@location} name='logo' />
+            </BS.Row>
+            <BS.Row>
                 <SC.Address lg=6 model={@location.address}  />
             </BS.Row>


stack-editor: read stack title input value from flux

--- client/stack-editor/lib/editor/index.coffee
+++ client/stack-editor/lib/editor/index.coffee
@@ -210,14 +210,25 @@
       tagName: 'header'
       cssClass: 'StackEditorView--header'

+    valueGetter = [
+      EnvironmentFlux.getters.teamStackTemplates
+      EnvironmentFlux.getters.privateStackTemplates
+      (teamTemplates, privateTemplates) ->
+        teamTemplates.merge(privateTemplates).getIn [ stackTemplate?._id, 'title' ]
+    ]
+
+    title = kd.singletons.reactor.evaluate valueGetter
+
     @header.addSubView @inputTitle = new kd.InputView
       cssClass: 'template-title'
       autogrow: yes
-      defaultValue : stackTemplate?.title or 'Default stack template' # can we auto generate cute stack names?
+      defaultValue : title or 'Default stack template' # can we auto generate cute stack names?
       bind: 'keyup'
       keyup: (e) ->
         { changeTemplateTitle } = EnvironmentFlux.actions
         changeTemplateTitle stackTemplate?._id, e.target.value
+
+    kd.singletons.reactor.observe valueGetter, (value) => @inputTitle.setValue value

     @inputTitle.on 'viewAppended', =>
       @inputTitle.prepareClone()


Tests: update tests for one step on boarding modal

--- client/test/lib/helpers/teamshelpers.coffee
+++ client/test/lib/helpers/teamshelpers.coffee
@@ -357,8 +357,6 @@

     stacksPageSelector = '.HomeAppView-Stacks--create'
     newStackButton = "#{stacksPageSelector} .kdbutton.GenericButton.HomeAppView-Stacks--createButton"
-    stackOnboardingPage = '.kdview.stack-onboarding.main-content.get-started'
-    createStackButton = '.kdbutton.GenericButton.StackEditor-OnboardingModal--create'
     providers = '.providers.box-wrapper'
     providerSelector = "#{providers} .provider.box.#{provider}"
     skipGuideButton = '.kdview.stack-onboarding.main-content a.custom-link-view.HomeAppView--button'
@@ -373,9 +371,6 @@
       .waitForElementVisible stacksPageSelector, 20000
       .click newStackButton
       .pause 1000
-      .waitForElementVisible stackOnboardingPage, 20000
-      .waitForElementVisible createStackButton, 20000
-      .click createStackButton
       .waitForElementVisible providers, 20000
       .click providerSelector
       .waitForElementVisible skipGuideButton, 20000


test/teamshelper: remove old teams helper functions

--- client/test/lib/helpers/teamshelpers.coffee
+++ client/test/lib/helpers/teamshelpers.coffee
@@ -331,265 +331,6 @@
         done()

-
-  clickSaveAndTestButton: (browser) ->
-
-    saveAndTestButton    = '.template-title-form .buttons .save-test'
-    editorSelector       = '.stack-template .output .output-view'
-    loaderIconNotVisible = "#{saveAndTestButton} .kdloader.hidden"
-
-    browser
-      .waitForElementVisible     saveAndTestButton, 20000
-      .scrollToElement           saveAndTestButton
-      .click                     saveAndTestButton
-      .waitForElementVisible     editorSelector, 35000
-      .waitForElementVisible     '.template-title-form .buttons .save-test .kdloader', 20000
-      .waitForElementNotVisible  loaderIconNotVisible, 500000
-      .pause                     3000
-
-
-  saveTemplate: (browser, deleteStack = yes, checkTags = yes, doExtra = yes) ->
-
-    stackModal           = '.stack-modal'
-    modalCloseButton     = "#{stackModal} .gray"
-    stackTabSelector     = '.team-stack-templates .kdtabhandle.stack-template.active'
-    finalizeStepsButton  = "#{sidebarSelector} a[href='/Home/Welcome']:not(.SidebarSection-headerTitle)"
-
-    if doExtra
-      @seeTemplatePreview(browser)
-      @updateStackReadme(browser)
-      @defineCustomVariables(browser)
-
-    @clickSaveAndTestButton(browser)
-
-    browser.element 'css selector', stackModal, (result) ->
-      if result.status is 0
-        browser
-          .assert.containsText    stackModal, 'Your stack script has been successfully saved'
-          .waitForElementVisible  modalCloseButton, 20000
-          .click                  modalCloseButton
-
-    browser
-      .waitForElementVisible     stackTabSelector, 20000
-      .waitForElementVisible     stackModalCloseButton, 20000
-      .click                     stackModalCloseButton
-      .pause                     3000
-      .waitForElementVisible     sidebarStackSection, 20000
-      .waitForElementNotPresent  finalizeStepsButton, 20000
-      .waitForElementVisible     envMachineStateModal, 20000
-
-    if checkTags
-      @checkStackTemplateTags(browser, deleteStack)
-
-
-  checkStackTemplateTags: (browser, deleteStack) ->
-
-    inUseTag       = "#{stackCatalogModal} [testpath=StackInUseTag]"
-    defaultTag     = "#{stackCatalogModal} [testpath=StackDefaultTag]"
-    accessTag      = "#{stackCatalogModal} [testpath=StackAccessLevelTag]"
-    deleteMenuItem = '.kdbuttonmenu .context-list-wrapper .delete'
-
-    @openStackCatalog(browser, no)
-
-    browser
-      .waitForElementVisible  stackTemplateList, 20000
-      .waitForElementVisible  inUseTag, 20000
-      .waitForElementVisible  defaultTag, 20000
-      .waitForElementVisible  accessTag, 20000
-      .assert.containsText    accessTag, 'GROUP'
-
-    if deleteStack
-      browser
-        .waitForElementVisible    stackSettingsMenuIcon, 20000
-        .click                    stackSettingsMenuIcon
-        .pause                    2000
-        .waitForElementVisible    deleteMenuItem, 20000
-        .click                    deleteMenuItem
-        .assert.containsText      '.kdnotification.main', 'This template currently in use by the Team'
-        .waitForElementNotVisible '.kdnotification.main', 30000
-
-    browser
-      .waitForElementVisible  stackModalCloseButton, 20000
-      .click                  stackModalCloseButton
-
-
-  editStack: (browser, openEditorAndClone = no) ->
-
-    editMenuItem             = '.kdbuttonmenu .context-list-wrapper .edit'
-    openEditorButton         = '.kdmodal-inner .kdmodal-buttons .red'
-    openEditorAndCloneButton = '.kdmodal-inner .kdmodal-buttons .green'
-    stackTemplatePage        = '.define-stack-view .stack-template'
-    stackEditorSelector      = "#{stackTemplatePage} .editor-pane"
-    numberNotification       = "#{sidebarStackSection} .SidebarListItem-unreadCount"
-    myStacksPage             = '.environments-modal.My-Stacks'
-    stackItems               = "#{myStacksPage} .environment-item"
-    makeTeamDefaultButton    = '.stacks .template-title-form .set-default'
-    makeTeamDefaultLoader    = "#{makeTeamDefaultButton} .kdloader.hidden"
-    newStackTemplate         = '.stacktemplates .stack-template-list .stacktemplate-item:last-child .title'
-    newStackInSidebar        = '.SidebarStackSection .SidebarMachinesListItem .SidebarMachinesListItem--MainLink'
-    updateNotification       = "#{stackItems} .update-notification"
-    updateStackButton        = "#{updateNotification} .reinit-stack"
-    reinitModal              = '.kdmodal[testpath=reinitStack]'
-    proceedButton            = "#{reinitModal} .red"
-    sidebarStackWidget       = '.SidebarStackWidgets'
-
-
-    browser.pause  3000
-    @openStackCatalog(browser, no)
-
-    browser
-      .waitForElementVisible  stackTemplateList, 20000
-      .waitForElementVisible  stackSettingsMenuIcon, 20000
-      .click                  stackSettingsMenuIcon
-      .pause                  2000
-      .waitForElementVisible  editMenuItem, 20000
-      .click                  editMenuItem
-      .pause                  2000
-
-    if openEditorAndClone
-      browser
-        .waitForElementVisible  openEditorAndCloneButton, 20000
-        .click                  openEditorAndCloneButton
-    else
-      browser
-        .waitForElementVisible  openEditorButton, 20000
-        .click                  openEditorButton
-
-    browser
-      .waitForElementVisible  stackTemplatePage, 20000
-      .waitForElementVisible  stackEditorSelector, 20000
-
-    @setTextToEditor browser, 'template', staticContents.multiMachineStackTemplate
-
-    if openEditorAndClone
-      @createCredential(browser, no, no, yes)
-
-    @clickSaveAndTestButton(browser)
-
-    if openEditorAndClone
-      browser
-        .waitForElementVisible  makeTeamDefaultButton, 20000
-        .click                  makeTeamDefaultButton
-        .pause                  3000
-        .waitForElementVisible  '.stacktemplates', 20000
-
-    browser
-      .waitForElementVisible  stackModalCloseButton, 20000
-      .click                  stackModalCloseButton
-
-    if openEditorAndClone
-      browser
-        .waitForElementVisible  sidebarStackWidget, 20000
-        .waitForTextToContain   sidebarStackWidget, 'Team admin has changed the default stack'
-        .click                  "#{sidebarStackWidget} a"
-        .waitForElementVisible  stackItems, 20000
-        .click                  "#{stackItems} .red"
-
-    else
-      browser
-        .waitForElementVisible  newStackInSidebar, 20000
-        .waitForElementVisible  numberNotification, 20000
-        .click                  numberNotification
-        .waitForElementVisible  stackItems, 20000
-        .waitForElementVisible  updateNotification, 20000
-        .assert.containsText    updateNotification, 'has updated this stack'
-        .waitForElementVisible  updateStackButton, 20000
-        .click                  updateStackButton
-
-    browser
-      .waitForElementVisible  reinitModal, 20000
-      .click                  proceedButton
-      .waitForTextToContain   sidebarSelector, 'mexample'
-
-
-  deleteStack: (browser) ->
-
-    deleteMenuItem = '.kdbuttonmenu .context-list-wrapper .delete'
-    stackTemplate  = '.stacktemplates .stack-template-list [testpath=privateStackListItem]'
-    stackMenuIcon  = "#{stackTemplate} .stack-settings-menu"
-    deleteModal    = '.kdmodal[testpath=RemoveStackModal]'
-    deleteButton   = "#{deleteModal} .red"
-
-
-    browser.element 'css selector', stackCatalogModal, (result) ->
-      if result.status is 0
-        browser
-          .waitForElementVisible  stackCatalogModal, 20000
-          .waitForElementVisible  closeButton, 20000
-          .click                  closeButton
-
-    @openStackCatalog(browser)
-
-    browser
-      .waitForElementVisible    myStackTemplatesButton, 20000
-      .click                    myStackTemplatesButton
-      .waitForElementVisible    stackTemplate, 20000
-      .pause                    3000
-      .waitForElementVisible    stackMenuIcon, 20000
-      .click                    stackMenuIcon
-      .waitForElementVisible    deleteMenuItem, 20000
-      .click                    deleteMenuItem
-      .pause                    3000
-      .waitForElementVisible    deleteModal, 20000
-      .assert.containsText      "#{deleteModal} .kdmodal-title", 'Remove stack template ?'
-      .waitForElementVisible    deleteButton, 20000
-      .click                    deleteButton
-      .waitForElementNotPresent deleteModal, 20000
-      .waitForElementVisible    closeButton, 20000
-      .click                    closeButton
-
-
-  buildStack: (browser) ->
-
-    buildStackButton     = "#{envMachineStateModal} .content-container .state-button"
-    progressbarContainer = "#{envMachineStateModal} .progressbar-container"
-    credentialsModal     = '.kdmodal[testpath=BuildRequirementsModal]'
-    addedCredential      = "#{credentialsModal} .credential-item"
-    titleInput           = "#{credentialsModal} input[name=title]"
-    usernameInput        = "#{credentialsModal} input[name=username]"
-    passwordInput        = "#{credentialsModal} input[name=password]"
-    credentialSaveButton = "#{credentialsModal} button.green"
-    useCredentialButton  = "#{addedCredential} .kdbutton:not(.secondary)"
-    readmeMarkdown       = "#{envMachineStateModal} .content-readme"
-    readmeHeader         = "#{readmeMarkdown} #test-stack-readme"
-    readmeLink           = "#{readmeMarkdown} a"
-
-    browser
-      .waitForElementVisible     buildStackButton, 20000
-      .waitForElementVisible     readmeMarkdown, 20000
-      .waitForElementVisible     readmeHeader, 20000
-      .waitForElementVisible     readmeLink, 20000
-      .click                     buildStackButton
-      .pause                     3500 # wait for credentials modal
-
-    browser.element 'css selector', credentialsModal, (result) ->
-      if result.status is 0
-
-        browser.element 'css selector', addedCredential, (result) ->
-          if result.status isnt 0
-            browser
-              .waitForElementVisible   titleInput, 20000
-              .waitForElementVisible   usernameInput, 20000
-              .waitForElementVisible   passwordInput, 20000
-              .setValue                titleInput, 'Build requirement data for testing'
-              .setValue                usernameInput, 'FOO'
-              .setValue                passwordInput, 'BAR'
-              .click                   credentialSaveButton
-              .waitForElementVisible   addedCredential, 20000
-
-          browser
-            .waitForElementVisible     useCredentialButton, 20000
-            .click                     useCredentialButton
-
-      browser
-        .waitForElementVisible     progressbarContainer, 20000
-        .waitForElementNotPresent  progressbarContainer, 500000
-        .pause                     3000 # wait for machine
-        .waitForElementVisible     stackMachine, 20000
-
-    browser.isStackBuilt = yes
-
-
   defineCustomVariables: (browser) ->

     wrongCustomVariable    = "foo: '"
@@ -611,114 +352,8 @@
     @setTextToEditor browser, 'template', staticContents.stackTemplate

-  reinitStack: (browser) ->
-
-    myStacksLink  = '.AppModal-navItem.my-stacks'
-    stackItem     = '.kdlistitemview.environment-item'
-    reinitButton  = "#{stackItem} .button-container .red"
-    reinitModal   = '.kdmodal[testpath=reinitStack]'
-    proceedButton = "#{reinitModal} .red"
-    notification  = '.kdnotification.main'
-
-    @openStackCatalog(browser, no)
-
-    browser
-      .waitForElementVisible    myStacksLink, 20000
-      .click                    myStacksLink
-      .waitForElementVisible    stackItem, 20000
-      .click                    reinitButton
-      .waitForElementVisible    reinitModal, 20000
-      .click                    proceedButton
-      .waitForElementNotPresent stackCatalogModal, 30000
-      .waitForElementVisible    envMachineStateModal, 20000
-
-
-  destroyEverything: (browser) ->
-
-    if browser.isStackBuilt
-      @reinitStack(browser)
-      browser.pause 10000 # wait before credential destroy
-      @createStack(browser, yes)
-      @createCredential(browser, no, yes)
-
-
-  seeTemplatePreview: (browser) ->
-
-    templatePreviewButton     = '.stack-template .template-preview-button'
-    stackTemplatePreviewModal = '.stack-template-preview'
-    tabsSelector              = "#{stackTemplatePreviewModal} .kdmodal-content .kdtabhandle-tabs"
-    yamlTabSelector           = "#{tabsSelector} .yaml"
-    jsonTabSelector           = "#{tabsSelector} .json"
-    stackTabSelector          = '.team-stack-templates .kdtabhandle.stack-template'
-
-    browser
-      .waitForElementVisible  stackTabSelector, 20000
-      .click                  stackTabSelector
-      .waitForElementVisible  templatePreviewButton, 20000
-      .click                  templatePreviewButton
-      .waitForElementVisible  stackTemplatePreviewModal, 20000
-      .waitForElementVisible  yamlTabSelector, 20000
-      .waitForElementVisible  jsonTabSelector, 20000
-      .waitForElementVisible  stackModalCloseButton, 20000
-      .click                  stackModalCloseButton
-
-
-  updateStackReadme: (browser) ->
-
-    @switchTabOnStackCatalog(browser, 'readme')
-    @setTextToEditor(browser, 'readme', staticContents.readme)
-
-    previewButton = '.editor-pane .preview-button'
-    previewModal  = '[testpath=ReadmePreviewModal]'
-    readmeLink    = 'https://koding.com/docs/creating-an-aws-stack'
-
-    browser
-      .waitForElementVisible  previewButton, 20000
-      .click                  previewButton
-      .waitForElementVisible  previewModal, 20000
-      .assert.containsText    "#{previewModal} h3", 'Test stack readme'
-      .waitForElementVisible  "#{previewModal} a[href='#{readmeLink}']", 20000
-      .waitForElementVisible  stackModalCloseButton, 20000
-      .click                  stackModalCloseButton
-
-
   getAwsKey: -> return awsKey

-
-  checkIconsStacks: (browser, removeNewStack = yes) ->
-
-    saveAndTestButton           = '.buttons button:nth-of-type(5)'
-    stackTemplateSelector       = '.kdtabhandlecontainer.hide-close-icons .stack-template'
-    stacksLogsSelector          = '.step-define-stack .kdscrollview'
-    iconsSelector               = '.kdlistitemview-default.stacktemplate-item .stacktemplate-info'
-    notReadyIconSelector        = "#{iconsSelector} .not-ready"
-    privateIconSelector         = "#{iconsSelector} .private"
-    stackTemplateSettingsButton = '.kdbutton.stack-settings-menu'
-    deleteButton                = '.kdlistview-contextmenu.expanded .delete'
-    confirmDeleteButton         = '.kdview.kdmodal-buttons .solid.red .button-title'
-
-    browser
-      .click                      saveAndTestButton
-      .pause                      2000 #for stack creation logs to appear
-      .waitForElementVisible      stacksLogsSelector, 20000
-      .assert.containsText        stacksLogsSelector, 'An error occured: Required credentials are not provided yet'
-      .click                      myStackTemplatesButton
-      .waitForElementVisible      notReadyIconSelector, 30000
-      .assert.containsText        notReadyIconSelector, 'NOT READY'
-      .assert.containsText        privateIconSelector, 'PRIVATE'
-
-    if removeNewStack
-      browser
-        .waitForElementVisible      stackTemplateSettingsButton, 20000
-        .click                      stackTemplateSettingsButton
-        .waitForElementVisible      deleteButton, 20000
-        .click                      deleteButton
-        .waitForElementVisible      confirmDeleteButton, 20000
-        .click                      confirmDeleteButton
-        .pause                      2000
-        .waitForElementVisible      stackTemplateSelector, 20000
-        .assert.containsText        stackTemplateSelector, 'Stack Template'
-        .assert.containsText        saveAndTestButton, 'SAVE & TEST'

   # possible values of tabName variable is 'stack', 'variables' or 'readme'
   switchTabOnStackCatalog: (browser, tabName) ->
@@ -801,94 +436,6 @@

         callback invitationUrl

-
-  enableAndDisableApiAccess: (browser, enableApi = no, disableApi = no) ->
-
-    apiAccessSelector       = '.kdtabhandle-tabs .api-access.AppModal-navItem'
-    toggleSwitch            = '.settings-row .koding-on-off.small.'
-    toggledOffSwitch        = "#{toggleSwitch}off"
-    toggledOnSwitch         = "#{toggleSwitch}on"
-    addNewApiDisabledButton = '.kdtabhandlecontainer.hide-close-icons [disabled="disabled"]'
-    addnewApiButton         = '.kdtabhandlecontainer.hide-close-icons .add-new'
-
-    browser
-      .waitForElementVisible     apiAccessSelector, 20000
-      .click                     apiAccessSelector
-      .element 'css selector', toggledOffSwitch, (result) ->
-        if result.status is 0
-          if enableApi
-            browser
-              .waitForElementVisible     toggledOffSwitch, 20000
-              .pause                     2000
-              .waitForElementVisible     addNewApiDisabledButton, 20000
-              .click                     toggledOffSwitch
-              .pause                     2000
-
-          if disableApi
-            browser
-              .waitForElementVisible     toggledOnSwitch, 20000
-              .waitForElementVisible     addnewApiButton, 20000
-              .click                     toggledOnSwitch
-              .pause                     2000
-              .waitForElementVisible     addNewApiDisabledButton, 20000
-
-
-  addNewApiToken: (browser) ->
-
-    addnewApiButton = '.kdtabhandlecontainer.hide-close-icons .add-new'
-    confirmDelete   = '.kddraggable.with-buttons .clearfix .solid.red'
-    deleteButton    = '.kdlistitemview-member .role.subview .delete'
-    tokenTimeStamp  = '.kdlistitemview-member .details .time'
-
-    browser
-      .click                     addnewApiButton
-      .waitForElementVisible     deleteButton, 20000
-      .assert.containsText       tokenTimeStamp, 'Created less than a minute ago by'
-      .click                     deleteButton
-      .waitForElementVisible     deleteButton, 20000
-      .click                     confirmDelete
-      .waitForElementNotVisible  tokenTimeStamp, 20000
-
-
-  editStackName: (browser) ->
-
-    stackTemplateSettingsButton = '.kdbutton.stack-settings-menu'
-    saveAndTestButton           = '.buttons button:nth-of-type(5)'
-    cancelButton                = '.buttons button:nth-of-type(2)'
-    stacksLogsSelector          = '.step-define-stack .kdscrollview'
-    myStackTemplatesButton      = '.kdview.kdtabhandle-tabs .my-stack-templates'
-    templateInputSelector       = '.template-title-form .template-title .input-wrapper input'
-    editedText                  = 'Edit stack name'
-    stackNameSelector           = '.stacktemplate-info.clearfix .title'
-    editButtonSelector          = '.kdbuttonmenu .context-list-wrapper .edit'
-
-    browser
-      .waitForElementVisible      stackTemplateSettingsButton, 20000
-      .click                      stackTemplateSettingsButton
-      .waitForElementVisible      editButtonSelector, 20000
-      .click                      editButtonSelector
-      .waitForElementVisible      templateInputSelector, 20000
-      .clearValue                 templateInputSelector
-      .setValue                   templateInputSelector, editedText
-      .click                      saveAndTestButton
-      .pause                      2000 #for stack creation logs to appear
-      .waitForElementVisible      stacksLogsSelector, 20000
-      .assert.containsText        stacksLogsSelector, 'An error occured: Required credentials are not provided yet'
-      .click                      myStackTemplatesButton
-      .waitForElementVisible      templateInputSelector, 20000
-      .click                      cancelButton
-      .waitForElementVisible      stackNameSelector, 20000
-      .assert.containsText        stackNameSelector, editedText
-
-
-  closeTeamSettingsModal: (browser) ->
-
-    adminModal  = '.AppModal.AppModal--admin.team-settings'
-    closeButton = "#{adminModal} .closeModal"
-
-    browser
-      .waitForElementVisible adminModal, 20000
-      .click                 closeButton

   logoutTeam: (browser, callback) ->


Remove another unused collection: desktop/collections/featured_links.coffee

--- src/desktop/collections/featured_links.coffee
+++ src/desktop/collections/featured_links.coffee
@@ -1,11 +0,0 @@
-Backbone = require 'backbone'
-sd = require('sharify').data
-_ = require 'underscore'
-FeaturedLink = require '../models/featured_link.coffee'
-{ Fetch } = require '@artsy/backbone-mixins'
-
-module.exports = class FeaturedLinks extends Backbone.Collection
-
-  _.extend @prototype, Fetch(sd.API_URL)
-
-  model: FeaturedLink


:memo: Set the correct name of class

:memo: Set the correct name of class

--- coffee/hatemile/util/CommonFunctions.coffee
+++ coffee/hatemile/util/CommonFunctions.coffee
@@ -23,7 +23,7 @@
 #
 @hatemile.util or= {}

-# The CommonFuncionts class contains the used methods by HaTeMiLe classes.
+# The CommonFunctions class contains the used methods by HaTeMiLe classes.
 #
 class @hatemile.util.CommonFunctions


don't use timestamps

don't use timestamps


SocialWorker: Tests: remove fetchGroup usage

--- workers/social/lib/social/models/computeproviders/managed.test.coffee
+++ workers/social/lib/social/models/computeproviders/managed.test.coffee
@@ -1,7 +1,6 @@
 { _
   daisy
   expect
-  fetchGroup
   withConvertedUser
   generateRandomString
   checkBongoConnectivity } = require '../../../../testhelper'
@@ -118,14 +117,11 @@
     it 'should be able to remove machine with valid request', (done) ->

       options = { provider : 'managed' }
-      withConvertedUserAnd ['Machine'], options, ({ client, account, user, machine }) ->
-
-        queue = [
-
-          ->
-            fetchGroup client, (group) ->
-              client.r = { account, user, group }
-              queue.next()
+      withConvertedUserAnd ['Machine'], options, (data) ->
+        { client, account, user, machine, group } = data
+        client.r = { account, user, group }
+
+        queue = [

           ->
             Managed.remove client, { machineId : machine._id.toString() }, (err) ->
@@ -151,7 +147,9 @@
     it 'should be able to update machine with valid request', (done) ->

       options = { provider : 'managed' }
-      withConvertedUserAnd ['Machine'], options, ({ client, account, user, machine }) ->
+      withConvertedUserAnd ['Machine'], options, (data) ->
+        { client, account, user, machine, group } = data
+        client.r = { account, user, group }

         updateOptions =
           storage     : '1'
@@ -164,11 +162,6 @@
         queue = [

           ->
-            fetchGroup client, (group) ->
-              client.r = { account, user, group }
-              queue.next()
-
-          ->
             Managed.update client, updateOptions, (err) ->
               expect(err?.message).to.not.exist
               queue.next()
@@ -191,20 +184,18 @@

     it 'should fail when required options not provided', (done) ->

-      withConvertedUser ({ client, account, user }) ->
+      withConvertedUser ({ client, account, user, group }) ->
+        client.r      = { account, user, group }
         expectedError = 'A valid machineId and an update option is required.'

-        fetchGroup client, (group) ->
-
-          client.r = { account, user, group }
-          Managed.update client, {}, (err) ->
-            expect(err?.message).to.be.equal expectedError
-            done()
+        Managed.update client, {}, (err) ->
+          expect(err?.message).to.be.equal expectedError
+          done()

     it 'should fail if provided some options are not valid', (done) ->

-      withConvertedUser ({ client, account, user }) ->
+      withConvertedUser ({ client, account, user, group }) ->

         generateDefaultOptions = (options) ->

@@ -218,13 +209,9 @@

           return _options

-
-        queue = [
-
-          ->
-            fetchGroup client, (group) ->
-              client.r = { account, user, group }
-              queue.next()
+        client.r = { account, user, group }
+
+        queue = [

           ->
             options = generateDefaultOptions { storage : 'invalidStorage' }


fix: typo in test

fix: typo in test

--- tests/integration/components/file-details-test.coffee
+++ tests/integration/components/file-details-test.coffee
@@ -13,4 +13,4 @@

   @render hbs """{{file-details}}"""

-  assert.equal @$().text().trim(), 'igh: Medium: Low: Passed: Unknown: Package: Version: PDF Password:   PDF Report'
+  assert.equal @$().text().trim(), 'High: Medium: Low: Passed: Unknown: Package: Version: PDF Password:   PDF Report'


Added placeholder to search bar

Added placeholder to search bar

--- core/app/backbone/views/react_topbar.coffee
+++ core/app/backbone/views/react_topbar.coffee
@@ -65,7 +65,7 @@
   render: ->
     _div ['topbar-search'],
       _form [onSubmit: @_onSubmit],
-        _input ['topbar-search-field', id: 'spec-search',
+        _input ['topbar-search-field', id: 'spec-search', placeholder: 'Search...',
                 onChange: @_onChange, value: @model().get('query')]

 window.ReactTopbar = React.createClass


Environments: Don't include unnecessary info on stack recipe for VMs.

--- client/Environments/views/stackview.coffee
+++ client/Environments/views/stackview.coffee
@@ -128,16 +128,13 @@
       @updateView yes

   dumpStack:->
+    dump = @getStackDump yes
     new KDModalView
+      width    : 600
+      overlay  : yes
       cssClass : 'recipe'
       title    : 'Stack recipe'
-      overlay  : yes
-      width    : 600
-      content  : """
-

-          #{@getStackDump yes}
-

-      """
+      content  : "
#{dump}
"

   getStackDump: (asYaml = no) ->
     {containers, connections} = @scene
@@ -151,6 +148,8 @@
           if name is 'domains'
             title   : dia.data.title
             aliases : dia.data.aliases
+          else if name is 'vms'
+            title   : dia.data.title
           else dia.data

     return if asYaml then jsyaml.dump dump else dump