now search MLB team news

now search MLB team news

--- src/scripts/espn.coffee
+++ src/scripts/espn.coffee
@@ -1,5 +1,5 @@
 # Description:
-#   Grab a headline from ESPN
+#   Grab a headline from ESPN through querying hubot
 #
 # Dependencies:
 #   None
@@ -8,7 +8,8 @@
 #   HUBOT_ESPN_ACCOUNT_KEY
 #
 # Commands:
-#   hubot espn - Displays a random headline from ESPN.com
+#   hubot espn headline - Displays a random headline from ESPN.com
+#   hubot espn mlb <name of team> - Displays ESPN.com team homepage
 #
 # Author:
 #   mjw56
@@ -18,7 +19,7 @@
   throw "You must enter your HUBOT_ESPN_ACCOUNT_KEY in your environment variables"

 module.exports = (robot) ->
-  robot.respond /espn/i, (msg) ->
+  robot.respond /espn headline/i, (msg) ->
     search = escape(msg.match[2])
     msg.http('http://api.espn.com/v1/sports/news/headlines?apikey=' + espnApiKey)
       .get() (err, res, body) ->
@@ -27,10 +28,23 @@
         if result.headlines.count <= 0
           msg.send "Couldn't find any headlines"
           return
-
+
         urls = [ ]
         for child in result.headlines
           urls.push(child.headline + "-  " + child.links.web.href)
-
+
         rnd = Math.floor(Math.random()*urls.length)
         msg.send urls[rnd]
+
+  robot.respond /(espn)( mlb)? (.*)/i, (msg) ->
+    msg.http('http://api.espn.com/v1/sports/baseball/mlb/teams?apikey=' + espnApiKey)
+      .get() (err, res, body) ->
+        result = JSON.parse(body)
+
+        for child in result.sports[0].leagues[0].teams
+          team = child.name.toLowerCase()
+          city = child.location.toLowerCase()
+          input = msg.match[3].toLowerCase()
+
+          if team is input || city is input
+            msg.send 'Team news for the '+ child.location + ' ' + child.name + '- ' + child.links.web.teams.href


Add stateChange event into collection

Add stateChange event into collection

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lookout/gringotts.git/'


Server: set cookie values correctly

Server: set cookie values correctly

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


add optouthandlerhelper

add optouthandlerhelper

error: pathspec 'servers/testhelper/optouthandlerhelper.coffee' did not match any file(s) known to git

--- servers/testhelper/optouthandlerhelper.coffee
+++ servers/testhelper/optouthandlerhelper.coffee
@@ -0,0 +1,39 @@
+querystring = require 'querystring'
+
+{ generateUrl
+  deepObjectExtend
+  generateRandomString
+  generateDefaultRequestParams } = require './index'
+
+
+generateOptoutRequestBody = (opts = {}) ->
+
+  defaultBodyObject =
+    name : generateRandomString()
+
+  deepObjectExtend defaultBodyObject, opts
+
+  return defaultBodyObject
+
+
+generateOptoutRequestParams = (opts = {}) ->
+
+  name = opts?.body?.name or generateRandomString()
+
+  url  = generateUrl
+    route : "#{encodeURIComponent name}/Optout"
+
+  body = generateOptoutRequestBody()
+
+  params               = { url, body }
+  defaultRequestParams = generateDefaultRequestParams params
+  requestParams        = deepObjectExtend defaultRequestParams, opts
+  # after deep extending object, encodes body param to a query string
+  requestParams.body   = querystring.stringify requestParams.body
+
+  return requestParams
+
+module.exports = {
+  generateOptoutRequestBody
+  generateOptoutRequestParams
+}


Create app.coffee

Create app.coffee

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Hiroto-K/EncryptionHelper.git/'


response with data from postgres

response with data from postgres

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/senotrusov/january.git/'


initialize sortable for attributes  [#71839334]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/people.git/'


Removed image params from compare create request

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


Use ctags to populate list

Use ctags to populate list

--- src/extensions/outline-view/outline-view.coffee
+++ src/extensions/outline-view/outline-view.coffee
@@ -2,6 +2,7 @@
 SelectList = require 'select-list'
 _ = require 'underscore'
 Editor = require 'editor'
+ChildProcess = require 'child-process'

 module.exports =
 class OutlineView extends SelectList
@@ -31,28 +32,54 @@
     if @hasParent()
       @cancel()
     else
-      @attach() if @populate()
+      @populate()
+
+  parsePrefix: (section = "") ->
+    if section.indexOf('class:') is 0
+      section.substring(6)
+    else if section.indexOf('namespace:') is 0
+      section.substring(10)
+    else if section.indexOf('file:') is 0
+      section.substring(5)
+    else if section.indexOf('signature:') is 0
+      section.substring(10)
+    else
+      section
+
+  parseTagLine: (line) ->
+    sections = line.split('\t')
+    return null if sections.length < 4
+
+    label = sections[0]
+    line = parseInt(sections[2]) - 1
+    if prefix = @parsePrefix(sections[4])
+      label = "#{prefix}::#{label}"
+    if signature = @parsePrefix(sections[5])
+      label = "#{label}#{signature}"
+
+    tag =
+      row: line
+      column: 0
+      name: label
+
+    return tag

   populate: ->
-    editor = @rootView.getActiveEditor()
-    session = editor.activeEditSession
-    language = session.tokenizedBuffer.languageMode.grammar.name
-    return false unless language is 'CoffeeScript'
+    tags = []
+    options =
+      bufferLines: true
+      stdout: (data) =>
+        lines = data.split('\n')
+        for line in lines
+          tag = @parseTagLine(line)
+          tags.push(tag) if tag
+        if tags.length > 0
+          @setArray(tags)
+          @attach()

-    functions = []
-    functionRegex = /(\s*)(@?[a-zA-Z$_]+)\s*(=|\:)\s*(\([^\)]*\))?\s*(-|=)>/
-    lineCount = editor.getLineCount()
-    for row in [0...lineCount]
-      line = session.buffer.lineForRow(row)
-      continue unless line.length
-      matches = line.match(functionRegex)
-      if matches
-        functions.push
-          row: row
-          column: matches[1].length
-          name: matches[2]
-    @setArray(functions)
-    return functions.length > 0
+    path = @rootView.getActiveEditor().getPath()
+    command = "ctags --fields=+KS -nf - #{path}"
+    deferred = ChildProcess.exec command, options

   confirmed : ({row, column, name}) ->
     @cancel()


refact (Notifications) Model existence is known at creation so don't check for it dynamically

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/supersonic.git/'


updates

updates

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/stevelacy/claru.git/'


Add locker function

Add locker function

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ICTU/self-healer.git/'


remove rail if no results have returned (as a failsafe to missing results)

--- apps/home_2/client/setup_home_page_modules.coffee
+++ apps/home_2/client/setup_home_page_modules.coffee
@@ -11,12 +11,13 @@
 iconicArtistsTemplate = -> require('../components/iconic_artists_context/templates/index.jade') arguments...
 auctionTemplate = -> require('../components/auction_context/templates/index.jade') arguments...
 fairTemplate = -> require('../components/fair_context/templates/index.jade') arguments...
+markdown = require '../../../components/util/markdown.coffee'

 contexts =
   iconic_artists: (module) ->
     iconicArtistsTemplate artists: module.context.artists
   live_auctions: (module) ->
-    auctionTemplate auction: module.context
+    auctionTemplate auction: module.context, md: markdown
   current_fairs: (module) ->
     fairTemplate fair: module.context, timeSpan: timeSpan

@@ -46,6 +47,7 @@
       module = home_page_module
       $el = $("#hpm-#{module.key}-#{index}")

+      return $el.remove() unless module.results.length
       return setupActiveBidsView(module, $el.find('.abrv-content'), user) if module.key is 'active_bids'
       return setupFollowedArtistsView(module, $el) if module.key is 'followed_artists'


Read package.json correctly.

Read package.json correctly.

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -50,13 +50,13 @@
   config

 exports.loadPlugins = (config, callback) ->
-  cwd = sysPath.resolve config.rootPath
-  fs.readFile 'package.json', (error, data) ->
+  rootPath = sysPath.resolve config.rootPath
+  fs.readFile (sysPath.join rootPath, 'package.json'), (error, data) ->
     return callback error if error?
     deps = Object.keys (JSON.parse data).dependencies
     plugins = deps
       .map (dependency) ->
-        require "#{cwd}/node_modules/#{dependency}"
+        require "#{rootPath}/node_modules/#{dependency}"
       .filter (plugin) ->
         (plugin::)? and plugin::brunchPlugin
       .map (plugin) ->


prevent crossfeed from different channel instances in the test suite by randomizing channels


disable menu items that are not available

error: pathspec 'app/assets/javascripts/menu.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/menu.js.coffee
+++ app/assets/javascripts/menu.js.coffee
@@ -0,0 +1,7 @@
+disable_menu_item = ->
+  $('ul.nav > li.dropdown > ul.dropdown-menu > li').each ->
+    if $(this).find('a').attr('href') == '#'
+      $(this).addClass('disabled')
+
+$(document).ready(disable_menu_item)
+$(window).bind('page:change', disable_menu_item)


chat: add IDEChatVideoView

chat: add IDEChatVideoView


Fixed input rebinding bug.

Fixed input rebinding bug.

--- src/NESCoffee.coffee
+++ src/NESCoffee.coffee
@@ -111,9 +111,16 @@
         @binder.bindControl srcDevice, srcButton, callback

     replaceUnbindCallback: (port, device, button, srcDevice, srcButton, callback) ->
-        @unbindCallbacks1[port]?[device]?[button] = callback
-        @unbindCallbacks2[srcDevice]?[srcButton]?()
-        @unbindCallbacks2[srcDevice]?[srcButton] = callback
+        unbindCallbacks1 = @unbindCallbacks1
+        unbindCallbacks2 = @unbindCallbacks2
+        unbindCallbacks1[port]?[device]?[button]?()
+        unbindCallbacks1[port]?[device]?[button] = ->
+            unbindCallbacks2[srcDevice]?[srcButton] = null
+            callback()
+        unbindCallbacks2[srcDevice]?[srcButton]?()
+        unbindCallbacks2[srcDevice]?[srcButton] = ->
+            unbindCallbacks1[port]?[device]?[button] = null
+            callback()

     getInputDeviceCallback: (port, device, button) ->
         if device is "joypad"


Coerce Point.add and Point.plus's argument from array to point object

--- src/app/point.coffee
+++ src/app/point.coffee
@@ -17,6 +17,7 @@
     new Point(@row, @column)

   add: (other) ->
+    other = Point.fromObject(other)
     row = @row + other.row
     if other.row == 0
       column = @column + other.column
@@ -26,6 +27,7 @@
     new Point(row, column)

   subtract: (other) ->
+    other = Point.fromObject(other)
     row = @row - other.row
     if @row == other.row
       column = @column - other.column


Permite login de usuários apenas na agencia correta

error: pathspec 'Agencia/server/lib/accounts.coffee' did not match any file(s) known to git

--- Agencia/server/lib/accounts.coffee
+++ Agencia/server/lib/accounts.coffee
@@ -0,0 +1,8 @@
+Accounts.validateLoginAttempt (data) ->
+	if data.allowed isnt true
+		return false
+
+	if data.user.agencia isnt process.env.AGENCIA
+		throw new Meteor.Error 'Agencia inválida'
+
+	return true


Allow to use space in contact name, refs #185

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/clochix/cozy-emails.git/'


Fixed: english locale

Fixed: english locale

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/clochix/cozy-home.git/'


client: home: added headerize mini util

client: home: added headerize mini util

error: pathspec 'client/home/lib/commons/headerize.coffee' did not match any file(s) known to git

--- client/home/lib/commons/headerize.coffee
+++ client/home/lib/commons/headerize.coffee
@@ -0,0 +1,8 @@
+kd = require 'kd'
+
+module.exports = sectionize = (title) ->
+
+  new kd.CustomHTMLView
+    tagName  : 'header'
+    cssClass : 'HomeAppView--sectionHeader'
+    partial  : title


Fixed problem with levels that don't have next levels in campaign editor.

--- app/views/play/CampaignView.coffee
+++ app/views/play/CampaignView.coffee
@@ -192,7 +192,7 @@
       @highlightElement '.level.next', delay: 500, duration: 60000, rotation: 0, sides: ['top']
       if @editorMode
         for level in @campaign.renderedLevels
-          for nextLevelOriginal in level.nextLevels
+          for nextLevelOriginal in level.nextLevels ? []
             if nextLevel = _.find(@campaign.renderedLevels, original: nextLevelOriginal)
               @createLine level.position, nextLevel.position
     @applyCampaignStyles()


remove shopping cart

remove shopping cart

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/stevepeak/handyjs.git/'


ignore enters from inputs

ignore enters from inputs


Add comment to sequence/display.coffee

Add comment to sequence/display.coffee

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bmedx/modulestore.git/'


inspect sessions view

inspect sessions view

error: pathspec 'views/inspect-sessions/map.coffee' did not match any file(s) known to git

--- views/inspect-sessions/map.coffee
+++ views/inspect-sessions/map.coffee
@@ -0,0 +1,6 @@
+(doc) ->
+  sep = doc._id.indexOf '-'
+  tid = doc._id.substr(0, sep)
+  date = doc._id.substr(sep+1)
+
+  emit [tid, date, doc.session, doc.event], doc.value


Using Inconsolata webfont

Using Inconsolata webfont

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/moreirayokoyama/ReactCodeEditor.git/'


bug fix

bug fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bubblegroup/bubblebot.git/'


use full paths in meta-t

use full paths in meta-t

--- src/packages/fuzzy-finder/lib/load-paths-handler.coffee
+++ src/packages/fuzzy-finder/lib/load-paths-handler.coffee
@@ -9,14 +9,13 @@

     paths = []
     isIgnored = (path) ->
+      path = path.substring(rootPath.length + 1)
       for segment in path.split('/')
         return true if _.contains(ignoredNames, segment)
       repo?.isPathIgnored(fs.join(rootPath, path))
     onFile = (path) ->
-      path = path.substring(rootPath.length + 1)
       paths.push(path) unless isIgnored(path)
     onDirectory = (path) ->
-      path = path.substring(rootPath.length + 1)
       not isIgnored(path)
     fs.traverseTree(rootPath, onFile, onDirectory)


add verification before patching

add verification before patching

--- server/init/patch.coffee
+++ server/init/patch.coffee
@@ -33,19 +33,26 @@
             if fieldValues? and unEncryptedFields.length isnt \
             Object.keys(parsedPasswords).length

-                log.info "password of #{konnector.slug} not complete"
+                # If fieldValues and model contain the same number of fields
+                # This prevents from patching when some fields are absent
+                if Object.keys(model.fields).length is \
+                Object.keys(fieldValues).length
+                    log.info "password of #{konnector.slug} not complete"

-                konnector.removeEncryptedFields model.fields
+                    konnector.removeEncryptedFields model.fields

-                log.info "#{konnector.slug} | patching password..."
+                    log.info "#{konnector.slug} | patching password..."

-                # updating fieldValues and password in database
-                konnector.save (err) ->
-                    if err
-                        log.info "#{konnector.slug} | #{err}"
-                    else
-                        log.info "#{konnector.slug} | patching succeeded"
+                    # updating fieldValues and password in database
+                    konnector.save (err) ->
+                        if err
+                            log.info "#{konnector.slug} | #{err}"
+                        else
+                            log.info "#{konnector.slug} | patching succeeded"

+                        callback()
+                else
+                    log.debug "Missing fields in #{konnector.slug}"
                     callback()

             else callback()


Add plugins that are not included in the annotator.js distribution, but are pre-requisites for the substitution project

error: pathspec 'plugins/tags.coffee' did not match any file(s) known to git

--- plugins/tags.coffee
+++ plugins/tags.coffee
@@ -0,0 +1,165 @@
+# Public: Tags plugin allows users to tag thier annotations with metadata
+# stored in an Array on the annotation as tags.
+class Annotator.Plugin.Tags extends Annotator.Plugin
+
+  options:
+    # Configurable function which accepts a string (the contents)
+    # of the tags input as an argument, and returns an array of
+    # tags.
+    parseTags: (string) ->
+      string = $.trim(string)
+
+      tags = []
+      tags = string.split(/\s+/) if string
+      tags
+
+    # Configurable function which accepts an array of tags and
+    # returns a string which will be used to fill the tags input.
+    stringifyTags: (array) ->
+      array.join(" ")
+
+  # The field element added to the Annotator.Editor wrapped in jQuery. Cached to
+  # save having to recreate it everytime the editor is displayed.
+  field: null
+
+  # The input element added to the Annotator.Editor wrapped in jQuery. Cached to
+  # save having to recreate it everytime the editor is displayed.
+  input: null
+
+  # Public: Initialises the plugin and adds custom fields to both the
+  # annotator viewer and editor. The plugin also checks if the annotator is
+  # supported by the current browser.
+  #
+  # Returns nothing.
+  pluginInit: ->
+    return unless Annotator.supported()
+
+    @field = @annotator.editor.addField({
+      label:  Annotator._t('Add some tags here') + '\u2026'
+      load:   this.updateField
+      submit: this.setAnnotationTags
+    })
+
+    @annotator.viewer.addField({
+      load: this.updateViewer
+    })
+
+    # Add a filter to the Filter plugin if loaded.
+    if @annotator.plugins.Filter
+      @annotator.plugins.Filter.addFilter
+        label: Annotator._t('Tag')
+        property: 'tags'
+        isFiltered: Annotator.Plugin.Tags.filterCallback
+
+    @input = $(@field).find(':input')
+
+  # Public: Extracts tags from the provided String.
+  #
+  # string - A String of tags seperated by spaces.
+  #
+  # Examples
+  #
+  #   plugin.parseTags('cake chocolate cabbage')
+  #   # => ['cake', 'chocolate', 'cabbage']
+  #
+  # Returns Array of parsed tags.
+  parseTags: (string) ->
+    @options.parseTags(string)
+
+  # Public: Takes an array of tags and serialises them into a String.
+  #
+  # array - An Array of tags.
+  #
+  # Examples
+  #
+  #   plugin.stringifyTags(['cake', 'chocolate', 'cabbage'])
+  #   # => 'cake chocolate cabbage'
+  #
+  # Returns Array of parsed tags.
+  stringifyTags: (array) ->
+    @options.stringifyTags(array)
+
+  # Annotator.Editor callback function. Updates the @input field with the
+  # tags attached to the provided annotation.
+  #
+  # field      - The tags field Element containing the input Element.
+  # annotation - An annotation object to be edited.
+  #
+  # Examples
+  #
+  #   field = $('
<input />
')[0]
+  #   plugin.updateField(field, {tags: ['apples', 'oranges', 'cake']})
+  #   field.value # => Returns 'apples oranges cake'
+  #
+  # Returns nothing.
+  updateField: (field, annotation) =>
+    value = ''
+    value = this.stringifyTags(annotation.tags) if annotation.tags
+
+    @input.val(value)
+
+  # Annotator.Editor callback function. Updates the annotation field with the
+  # data retrieved from the @input property.
+  #
+  # field      - The tags field Element containing the input Element.
+  # annotation - An annotation object to be updated.
+  #
+  # Examples
+  #
+  #   annotation = {}
+  #   field = $('
<input value="cake chocolate cabbage" />
')[0]
+  #
+  #   plugin.setAnnotationTags(field, annotation)
+  #   annotation.tags # => Returns ['cake', 'chocolate', 'cabbage']
+  #
+  # Returns nothing.
+  setAnnotationTags: (field, annotation) =>
+    annotation.tags = this.parseTags(@input.val())
+
+  # Annotator.Viewer callback function. Updates the annotation display with tags
+  # removes the field from the Viewer if there are no tags to display.
+  #
+  # field      - The Element to populate with tags.
+  # annotation - An annotation object to be display.
+  #
+  # Examples
+  #
+  #   field = $('
')[0]
+  #   plugin.updateField(field, {tags: ['apples']})
+  #   field.innerHTML # => Returns 'apples'
+  #
+  # Returns nothing.
+  updateViewer: (field, annotation) ->
+    field = $(field)
+
+    if annotation.tags and $.isArray(annotation.tags) and annotation.tags.length
+      field.addClass('annotator-tags').html(->
+        string = $.map(annotation.tags,(tag) ->
+            '' + Annotator.Util.escape(tag) + ''
+        ).join(' ')
+      )
+    else
+      field.remove()
+
+# Checks an input string of keywords against an array of tags. If the keywords
+# match _all_ tags the function returns true. This should be used as a callback
+# in the Filter plugin.
+#
+# input - A String of keywords from a input field.
+#
+# Examples
+#
+#   Tags.filterCallback('cat dog mouse', ['cat', 'dog', 'mouse']) //=> true
+#   Tags.filterCallback('cat dog', ['cat', 'dog', 'mouse']) //=> true
+#   Tags.filterCallback('cat dog', ['cat']) //=> false
+#
+# Returns true if the input keywords match all tags.
+Annotator.Plugin.Tags.filterCallback = (input, tags = []) ->
+  matches  = 0
+  keywords = []
+  if input
+    keywords = input.split(/\s+/g)
+    for keyword in keywords when tags.length
+      matches += 1 for tag in tags when tag.indexOf(keyword) != -1
+
+  matches == keywords.length


Don't add "Mount other VMs" button.

Don't add "Mount other VMs" button.

--- client/finder/AppController.coffee
+++ client/finder/AppController.coffee
@@ -21,7 +21,7 @@

     finderView.addSubView @getAppTitleView()  if options.addAppTitle
     finderView.addSubView @getUploader()
-    finderView.addSubView @getMountVMButton()
+    # finderView.addSubView @getMountVMButton()

     return @controller


Add table example.

Add table example.

error: pathspec 'examples/table.coffee' did not match any file(s) known to git

--- examples/table.coffee
+++ examples/table.coffee
@@ -0,0 +1,34 @@
+{Collection, Model, View} = require 'mvstar'
+
+User = Model
+  defaults:
+    name: ''
+    email: ''
+
+Users = Collection
+  model: User
+  fetch: ->
+    @models = [
+      User name: 'Zach', email: 'zach@kelling.com'
+      User name: 'David', email: 'david@tai.com'
+    ]
+
+Table = View
+  collection: Users
+  template: -> '

'
+  render: ->
+    for model in @collection
+      @el.appendChild (Row model).el
+
+Row = View
+  model: User
+  template: -> '

'
+  render: ->
+    for k,v of own @model
+      @el.appendChild (Cell @model, k)
+
+Cell = View
+  model: User
+  template: -> '	'
+  render: ->
+    @el.innerHTML = @model[@column]


JAccount: remove deprecated isAuthorized method

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -153,8 +153,6 @@
           (signature Function)
         fetchOAuthInfo:
           (signature Function)
-        isAuthorized:
-          (signature String, Function)
         fetchFromUser: [
           (signature String, Function)
           (signature [String], Function)
@@ -1296,17 +1294,6 @@
       else
         callback null, user.getAt key

-  isAuthorized: secure (client, name, callback) ->
-    @fetchOAuthInfo client, (err, response) ->
-
-      return callback err  if err
-
-      return callback null, no  unless response?[name]
-
-      return callback null, yes  if name isnt 'github'
-
-      return callback null, response[name].scope is 'repo'
-

   setLastLoginTimezoneOffset: secure (client, options, callback) ->
     { lastLoginTimezoneOffset } = options


urls might not exist

urls might not exist

--- extensions/gist/gist.coffee
+++ extensions/gist/gist.coffee
@@ -11,6 +11,7 @@
   window.resourceTypes.push this

   open: (url) ->
+    return if not url
     if match = url.match /^https?:\/\/gist\.github\.com\/([^\/]+)\/?/
       super()
       @setCode "Loading Gist..."


Use atom.config.setRawValue instead of atom.config.set

atom.config.set was writting to the user config file
Also, use _.union to preserve existing array setting values

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/douggr/atom-project-manager.git/'


opt: name

opt: name

--- src/yaku.coffee
+++ src/yaku.coffee
@@ -357,7 +357,7 @@
 	$unhandledRejection = -1

 	# These are some symbols. They won't be used to store data.
-	$circularError = 'circular promise chain'
+	$circularChain = 'promise_circular_chain'

 	$invalid_argument = 'invalid_argument'

@@ -493,7 +493,7 @@
 	settleWithX = (p, x) ->
 		# 2.3.1
 		if x == p and x
-			settlePromise p, $rejected, genTypeError($circularError)
+			settlePromise p, $rejected, genTypeError($circularChain)
 			return

 		# 2.3.2


stub in next two issue items

stub in next two issue items

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/newsdev/geoip.git/'


Fix rendering preview of slides on switched theme

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/will-hart/marp.git/'


ComputeController: move block out in ready scope

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -70,27 +70,25 @@
       groupsController.on 'StackAdminMessageCreated', @bound 'handleStackAdminMessageCreated'
       groupsController.on 'SharedStackTemplateAccessLevel', @bound 'sharedStackTemplateAccessLevel'

-      kd.singletons.mainController.ready =>
-
-        @eventListener      = new ComputeEventListener
-        @managedKiteChecker = new ManagedKiteChecker
-        @stateChecker       = new ComputeStateChecker { @storage }
-        @stateChecker.start()
-
-        @createDefaultStack()
-
-        @appStorage = kd.singletons.appStorageController.storage 'Compute', '0.0.1'
-
-        debug 'now ready'
-        @emit 'ready'
-
-        @checkGroupStackRevisions()
-        @checkGroupStacks()
-
-        if groupsController.canEditGroup()
-          @checkMachinePermissions()
-
-        @checkMachines()
+      @eventListener      = new ComputeEventListener
+      @managedKiteChecker = new ManagedKiteChecker
+      @stateChecker       = new ComputeStateChecker { @storage }
+      @stateChecker.start()
+
+      @createDefaultStack()
+
+      @appStorage = kd.singletons.appStorageController.storage 'Compute', '0.0.1'
+
+      debug 'now ready'
+      @emit 'ready'
+
+      @checkGroupStackRevisions()
+      @checkGroupStacks()
+
+      if groupsController.canEditGroup()
+        @checkMachinePermissions()
+
+      @checkMachines()

   # ComputeController internal helpers


added logout route

added logout route

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/herrkris/bbphone-app.git/'


Added history handler #77

Added history handler #77

error: pathspec 'wzk/history/base.coffee' did not match any file(s) known to git

--- wzk/history/base.coffee
+++ wzk/history/base.coffee
@@ -0,0 +1,13 @@
+goog.provide 'wzk.history'
+
+goog.require 'goog.History'
+
+###*
+  Setups history listener
+  @param {function} callback
+###
+wzk.history.historyHandler = (callback) ->
+  history = new goog.History()
+  history.setEnabled true
+  goog.events.listen history, goog.history.EventType.NAVIGATE, (event) ->
+    callback(event)


Tests: IDE: Layout: Disabled undoSplitPanesNotShowOnScreen test.

--- client/test/lib/ide/layout.coffee
+++ client/test/lib/ide/layout.coffee
@@ -33,23 +33,23 @@
     browser.end()

-  undoSplitPanesNotShowOnScreen: (browser) ->
+  # undoSplitPanesNotShowOnScreen: (browser) ->

-    helpers.beginTest(browser)
-    helpers.waitForVMRunning(browser)
-    newPaneSelector = '.kdsplitcomboview .kdsplitview-panel.panel-1 .application-tab-handle-holder'
+  #   helpers.beginTest(browser)
+  #   helpers.waitForVMRunning(browser)
+  #   newPaneSelector = '.kdsplitcomboview .kdsplitview-panel.panel-1 .application-tab-handle-holder'

-    fn = ->
-      browser.elements 'css selector', newPaneSelector, (result) =>
-        if result.value.length is 1
-          browser
-            .waitForElementPresent '.panel-1 .general-handles .close-handle.hidden', 20000 # Assertion
-            .end()
-        else
-          layoutHelpers.undoSplit(browser, no)
-          fn()
+  #   fn = ->
+  #     browser.elements 'css selector', newPaneSelector, (result) =>
+  #       if result.value.length is 1
+  #         browser
+  #           .waitForElementPresent '.panel-1 .general-handles .close-handle.hidden', 20000 # Assertion
+  #           .end()
+  #       else
+  #         layoutHelpers.undoSplit(browser, no)
+  #         fn()

-    fn()
+  #   fn()

   openDrawingBoard: (browser) ->


prevents stale state from persisting

prevents stale state from persisting

--- apps/artwork/components/commercial/view.coffee
+++ apps/artwork/components/commercial/view.coffee
@@ -22,7 +22,6 @@
     { artwork } = @data
     { @fair } = artwork

-    @user = User.instantiate()
     @artwork = new Artwork artwork

   acquire: (e) ->
@@ -49,6 +48,7 @@

     { attending } = data = form.serializer.data()

+    @user = User.instantiate()
     @user.set pick data, 'name', 'email'
     @inquiry.set data


それゴックンした？

それゴックンした？

error: pathspec 'hubot/scripts/gokkun.coffee' did not match any file(s) known to git

--- hubot/scripts/gokkun.coffee
+++ hubot/scripts/gokkun.coffee
@@ -0,0 +1,7 @@
+# Description
+#  それゴックンした？
+
+module.exports = (robot) ->
+  robot.hear /.+/i, (res) ->
+    if Math.random() < 0.01
+      res.reply 'それゴックンした？'


Fix a few more tests

Fix a few more tests

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/kevinrenaers/atom.git/'


add tests

add tests

error: pathspec 'test/log.coffee' did not match any file(s) known to git

--- test/log.coffee
+++ test/log.coffee
@@ -0,0 +1,15 @@
+chai = require "chai"
+expect = chai.expect
+
+{info, warn, fail} = require "../src/log"
+
+describe "Logger", ->
+
+  it "does not throw on level INFO", ->
+    (expect (-> info "foo")).not.to.throw /./
+
+  it "does not throw on level WARN", ->
+    (expect (-> warn "foo")).not.to.throw /./
+
+  it "throws on level FAIL", ->
+    (expect (-> fail "foo")).to.throw /foo/


hooking up with the wikipedia api

hooking up with the wikipedia api

error: pathspec 'coffee/server/personFinder.coffee' did not match any file(s) known to git

--- coffee/server/personFinder.coffee
+++ coffee/server/personFinder.coffee
@@ -0,0 +1 @@
+api.php ? action=query & list=alllinks & alprefix=API & alnamespace=1 & alprop=ids|title


Initial commit of actual code!

Initial commit of actual code!

error: pathspec 'dio.coffee' did not match any file(s) known to git

--- dio.coffee
+++ dio.coffee
@@ -0,0 +1,70 @@
+dio = {}
+
+# internal helpers
+sluggifyNameString = (str) ->
+  return str.replace(/[-+!?:*\[\]\(\)\/]/g, '').trim().replace(/\s/g, '_').toLowerCase()
+
+sanitizeLayerName = (layer) ->
+  return sluggifyNameString layer.name
+
+
+dio.normalizeImportedLayers = (layers) ->
+  for layer_name, layer in layers
+    delete layers[layer_name]
+    layers[sluggifyNameString layer_name] = layer
+
+dio.initialize = (layers) ->
+  layers = Framer.CurrentContext._layerList if not layers
+  dio.normalizeImportedLayers layers
+
+
+dio.clone = clone = (obj) ->
+  copy = undefined
+  # Handle the 3 simple types, and null or undefined
+  if null == obj or 'object' != typeof obj
+    return obj
+  # Handle Date
+  if obj instanceof Date
+    copy = new Date
+    copy.setTime obj.getTime()
+    return copy
+  # Handle Array
+  if obj instanceof Array
+    copy = []
+    len = obj.length
+    for i in [0..len-1]
+      copy[i] = clone(obj[i])
+    return copy
+  # Handle Object
+  if obj instanceof Object
+    copy = {}
+    for attr of obj
+      if obj.hasOwnProperty(attr)
+        copy[attr] = clone(obj[attr])
+    return copy
+
+  throw new Error('Unable to copy obj! Its type isn\'t supported.')
+
+dio.setVisibilityWhenAnimating = (layer, showStateName = 'showing', hideStateName = 'hidden') ->
+  layer.on Events.StateWillSwitch, (from, to) ->
+    layer.visible = true  if to is showStateName or to is 'default'
+
+  layer.on Events.StateDidSwitch, (from, to) ->
+    return  if to is from # Workaround for https://github.com/koenbok/Framer/issues/173
+    layer.visible = false  if to is hideStateName
+
+dio.switchLayerStates = (layer_names, state_name, animation_options) ->
+  for layer_name in layer_names
+    do (layer_name) ->
+      layer = l[layer_name]
+      layer.states.switch state_name, animation_options
+
+dio.eachLayer = (fn, filter) ->
+  if typeof filter is string
+    filter = new RegExp(str, 'i')
+
+  for layer of window.Layers
+    _layer = window.Layers[layer]
+    fn _layer if !filter or layer.name.match filter
+
+_.extend(exports, dio)


Update utilities.coffee

Update utilities.coffee

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/heiskr/subvoko.git/'


Fixed the typeError on single tab. (#2353)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


from_date and to_date fix

from_date and to_date fix


Made URL title link to new window

Made URL title link to new window


finished gulp rebuild and cleanup

finished gulp rebuild and cleanup

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Bit18/cyoab_modular_repo.git/'


Add last line to gulpfile.coffee

Add last line to gulpfile.coffee

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Hiroto-K/HkApps.git/'


get commit not branch

get commit not branch

--- src/coffee/github.coffee
+++ src/coffee/github.coffee
@@ -27,7 +27,7 @@
       return $('.commit-id:last').text()

     else if @page is 'tree'
-      return $('.file-navigation .repo-root a:first').attr('data-branch')
+      return $('.commit-meta .sha-block').attr('href').split('/').pop()

     else
       # no coverage overlay


...sigh.

...sigh.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/damianb/crimson.git/'


WIP re #21.

WIP re #21.

error: pathspec 'App.dev.coffee' did not match any file(s) known to git

--- App.dev.coffee
+++ App.dev.coffee
@@ -0,0 +1,477 @@
+Ext.define 'RallyPokerApp', {
+  extend: 'Rally.app.App'
+  id: 'RallyPokerApp'
+  componentCls: 'app'
+  models: []
+  layout: 'card'
+  items: [{
+    id: 'storypicker'
+    layout:
+      # type: 'vbox'
+      reserveScrollbar: true
+    autoScroll: true
+    dockedItems: [{
+      items: [{
+        id: 'iterationfilter'
+        xtype: 'toolbar'
+        # cls: 'header'
+      }]
+    }]
+  }, {
+    id: 'storyview'
+    layout:
+      reserveScrollbar: true
+    autoScroll: true
+    dockedItems: [{
+      items: [{
+        id: 'storyheader'
+        xtype: 'toolbar'
+        # cls: 'header'
+        # tpl: '
{FormattedID}: {Name}
'
+        items: [{
+          id: 'storyback'
+          xtype: 'button'
+          html: 'Back',
+          # scale: 'small'
+          # ui: 'back'
+        }, {
+          id: 'storytitle'
+          xtype: 'component'
+        }]
+      }]
+    }]
+  }]
+
+  Base62: do () ->
+    # Adapted from Javascript Base62 encode/decoder
+    # Copyright (c) 2013 Andrew Nesbitt
+    # See LICENSE at https://github.com/andrew/base62.js
+
+    # Library that obfuscates numeric strings as case-sensitive,
+    # alphanumeric strings
+    chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
+
+    {
+      encode: (i) ->
+        return if i == 0
+        s = ''
+        while i > 0
+          s = chars[i % 62] + s
+          i = Math.floor(i / 62)
+        s
+      decode: (a,b,c,d) ->
+        `for (
+          b = c = (a === (/\W|_|^$/.test(a += "") || a)) - 1;
+          d = a.charCodeAt(c++);
+        ) {
+          b = b * 62 + d - [, 48, 29, 87][d >> 5];
+        }
+        return b`
+        return
+    }
+
+  PokerMessage: do () ->
+    # helper fn to escape RegEx-reserved strings
+    esc = (str) -> str.replace /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"
+    # [strings] ==> encoded message + custom delimiters
+    sep = ['/', '&']
+    msg = new RegExp "^" + sep[0] + "\\w+(?:" + sep[1] + "\\w+)+$"
+    env = ['[[', ']]']
+    pkg = new RegExp esc(env[0]) + "(" + sep[0] + ".+?)" + esc(env[1])
+
+    {
+      compile: (M) ->
+        fn = arguments[1] || (x) -> x
+        a = Ext.clone M
+        a[0] = sep[0] + fn M[0]
+        s = if a.length == 1 then a[0] else a.reduce (p, c, i) -> p + sep[1] + fn c
+        env[0] + s + env[1]
+      extract: (s) ->
+        if s and a = s.match pkg then a.pop() else false
+      parse: (s) ->
+        return false if not msg.test s
+        M = s.slice(1).split sep[1]
+        if not arguments[1]? then M else arguments[1] i for i in M by 1
+    }
+
+  launch: () ->
+    @IterationsStore = Ext.create 'Rally.data.WsapiDataStore', {
+      # id: 'iterationsStore'
+      model: 'Iteration'
+      fetch: ['Name']
+      sorters: [{
+        property: 'Name'
+        direction: 'DESC'
+      }]
+      autoLoad: true
+      listeners:
+        load: (store, result, success) =>
+          # debugger
+          @IterationFilter.setValue 'Deprecated' if success
+          return
+    }
+    @IterationFilter = Ext.create 'Ext.form.ComboBox', {
+      fieldLabel: 'Iteration'
+      store: @IterationsStore
+      queryMode: 'local'
+      displayField: 'Name'
+      valueField: 'Name'
+      listeners:
+        change: (field, newValue, oldValue, options) =>
+          @StoriesStore.load {
+            filters: [{
+              property: 'Iteration.Name'
+              value: newValue
+            }]
+          }
+          return
+    }
+    @down('#iterationfilter').add @IterationFilter
+
+    @StoriesStore = Ext.create 'Rally.data.WsapiDataStore', {
+      model: 'User Story'
+      fetch: ['ObjectID', 'FormattedID', 'Name']
+      sorters: [{
+        property: 'Name'
+        direction: 'DESC'
+      }]
+      # listeners:
+      #   load: (store, result, success) ->
+      #     debugger
+      #     return
+    }
+    @StoryList = Ext.create 'Ext.view.View', {
+      store: @StoriesStore
+      tpl: new Ext.XTemplate(
+        '<tpl for=".">',
+          '
',
+            '{FormattedID}: {Name}',
+          '
',
+        '</tpl>'
+      )
+      itemSelector: 'div.storylistitem'
+      emptyText: 'No stories available'
+      listeners:
+        click:
+          element: 'el'
+          fn: (e, t) =>
+            StoryListItem = Ext.get(Ext.get(t).findParent '.storylistitem')
+
+            storyListItemName = StoryListItem.child('.storylistitem-id').getHTML()
+            Ext.get('storytitle').update storyListItemName
+
+            storyListItemId = StoryListItem.getAttribute 'data-id'
+            @CurrentStory.load {
+              filters: [{
+                property: 'ObjectID'
+                value: storyListItemId
+              }]
+            }
+            # always load the store so that its view is reprocessed.
+            @DiscussionsStore.load {
+              filters: [{
+                property: 'Artifact.ObjectID'
+                value: storyListItemId
+              }]
+            }
+            @getLayout().setActiveItem 'storyview'
+            return
+    }
+    @down('#storypicker').add @StoryList
+
+    Ext.getCmp('storyback').on 'click', () =>
+      @getLayout().setActiveItem 'storypicker'
+      return
+
+    @CurrentStory = Ext.create 'Rally.data.WsapiDataStore', {
+      model: 'userstory'
+      limit: 1,
+      fetch: ['ObjectID', 'LastUpdateDate', 'Description', 'Attachments', 'Notes', 'Discussion']
+    }
+    @StoryPage = Ext.create 'Ext.view.View', {
+      store: @CurrentStory
+      tpl: new Ext.XTemplate(
+        '<tpl for=".">',
+        '
',
+          'Last Updated: {[this.prettyDate(values.LastUpdateDate)]}',
+          '
',
+            '{Description}',
+          '
',
+          '
',
+            '
Attachments
{Attachments}',
+          '
',
+          '
',
+            '
Notes
{Notes}',
+          '
',
+        '
',
+        '</tpl>',
+        {
+          # Adapted from JavaScript Pretty Date
+          # Copyright (c) 2011 John Resig (ejohn.org)
+          # Licensed under the MIT and GPL licenses.
+
+          # Takes an ISO time and returns a string representing how
+          # long ago the date represents.
+          prettyDate: (date) ->
+            diff = (((new Date()).getTime() - date.getTime()) / 1000)
+            day_diff = Math.floor(diff / 86400)
+            return if isNaN(day_diff) || day_diff < 0 || day_diff >= 31
+            day_diff == 0 && (diff < 60 && "just now" || diff < 120 && "1 minute ago" || diff < 3600 && Math.floor(diff / 60) + " minutes ago" || diff < 7200 && "1 hour ago" || diff < 86400 && Math.floor(diff / 3600) + " hours ago") || day_diff == 1 && "Yesterday" || day_diff < 7 && day_diff + " days ago" || day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago"
+        }
+      )
+      itemSelector: 'div.storydetail'
+    }
+    @down('#storyview').add @StoryPage
+
+    # custom field definition to parse poker messages from discussion items.
+    @DiscussionMessageField = new Ext.data.Field {
+      name: 'Message'
+      type: 'string'
+      convert: (v, rec) =>
+        if message = @PokerMessage.extract rec.get 'Text'
+          # Expected message contents: UserID + 4-bit point-selection value
+          (@PokerMessage.parse message, @Base62.decode).pop()
+        else
+          false
+    }
+    Rally.data.ModelFactory.getModel {
+      type: 'conversationpost'
+      success: (Model) =>
+        @models['conversationpost'] = Ext.clone Model
+        Model.prototype.fields.items.push @DiscussionMessageField
+        Model.setFields Model.prototype.fields.items
+        return
+    }
+    @DiscussionsStore = Ext.create 'Rally.data.WsapiDataStore', {
+      model: 'conversationpost'
+      fetch: ['User', 'CreationDate', 'Text', 'Message']
+    }
+    @DiscussionThread = Ext.create 'Ext.view.View', {
+      store: @DiscussionsStore
+      tpl: new Ext.XTemplate(
+        '<tpl for=".">',
+          '<tpl if="Message !== false">',
+            '<tpl if="!this.shownMessages">{% this.shownMessages = true %}',
+              '
',
+                '
Who\'s Voted
',
+                '
',
+            '</tpl>',
+          '</tpl>',
+          '<tpl if="xindex == xcount && this.shownMessages">',
+            '<tpl for="whoVoted">',
+                  '
{name} at {when}
',
+            '</tpl>'
+                '
',
+              '
',
+          '</tpl>',
+        '</tpl>',
+        '

'
+        '<tpl for=".">',
+          '<tpl if="Message === false">',
+            '<tpl if="!this.shownDiscussion">{% this.shownDiscussion = true %}',
+              '
',
+                '
Discussion
',
+            '</tpl>'
+                '
',
+                  '{User._refObjectName}: {CreationDate}',
+                  '
{Text}
',
+                '
',
+          '</tpl>',
+          '<tpl if="xindex == xcount && this.shownDiscussion">',
+              '
',
+          '</tpl>',
+        '</tpl>',
+        {
+          accountRef: "/user/" + Rally.environment.getContext().getUser().ObjectID
+          accountVoted: false
+          shownMessages: false
+          shownDiscussion: false
+          whoVoted: {}
+        }
+      )
+      itemSelector: 'div.discussionitem'
+      prepareData: (data, index, record) ->
+        if data.Message
+          # debugger
+          `var timestamp = data.CreationDate.getTime()`
+          if not @tpl.whoVoted[data.User._ref]? or timestamp > @tpl.whoVoted[data.User._ref].when
+            @tpl.whoVoted[data.User._ref] =
+              post: data.ObjectID
+              when: timestamp
+              user: data.User._ref
+              name: data.User._refObjectName
+              vote: data.Message
+        if index == @store.data.length - 1
+          `var whenVoted = [], voteMap = {}`
+          data.whoVoted = []
+
+          for k, V of @tpl.whoVoted
+            @tpl.accountVoted = V if k == @tpl.accountRef
+            if @tpl.whoVoted.hasOwnProperty k
+              whenVoted.push V.when
+              voteMap[V.when] = V
+
+          whenVoted.sort()
+          for k in whenVoted
+            D = new Date voteMap[k].when
+            voteMap[k].when = Ext.util.Format.date(D, 'g:iA') + ' on ' + Ext.util.Format.date(D, 'm-d-Y')
+            data.whoVoted.push voteMap[k]
+        # console.log 'prepareData. accountVoted = ' + @tpl.accountVoted
+        data
+      listeners:
+        scope: @
+        refresh: (view) ->
+          StoryEstimator = Ext.create 'EstimateSelector',
+            ParentApp: @
+            accountId: Rally.environment.getContext().getUser().ObjectID
+            renderTo: Ext.query('.estimateselector')[0]
+          # console.log 'refresh. accountVoted = ' + view.tpl.accountVoted
+          StoryEstimator.update view.tpl.accountVoted
+          return
+    }
+    @down('#storyview').add @DiscussionThread
+
+    return
+}
+
+Ext.define 'EstimateSelector', {
+  extend: 'Ext.Container'
+  # cls: 'estimateselector'
+  # constructor uses config to populate items.
+  # items: []
+  config:
+    accountId: 0
+    cipher: 0
+    # @cfg {Array} (required)
+    # a list of values that can be used as story estimates
+    deck: [
+      { value: `00`, label: '?' }
+      { value: `01`, label: '0' }
+      { value: `02`, label: '½' } # "½"
+      { value: `03`, label: '1' }
+      { value: `04`, label: '2' }
+      { value: `05`, label: '3' }
+      { value: `06`, label: '5' }
+      { value: `07`, label: '8' }
+      { value: `010`, label: '13' }
+      { value: `011`, label: '20' }
+      { value: `012`, label: '40' }
+      { value: `013`, label: '100' }
+      # { value: `014`, label: '' }
+      # { value: `015`, label: '' }
+      # { value: `016`, label: '' }
+      # { value: `017`, label: '' }
+    ]
+
+  constructor: (config) ->
+    @mergeConfig config
+    @config.cipher = config.accountId % 10 if config.accountId?
+    @callParent [config]
+    return
+
+  # update gets called before the template is processed.
+  update: (data) ->
+    if data.vote
+      # console.log 'update. vote = ' + data.vote
+      # values in 'data' passed by reference and later used by template.
+      data.vote = @_decipher(data.vote)
+      @callParent [data]
+
+      # add control to delete previous vote
+      Ext.create 'Ext.Component',
+          data: data
+          tpl: new Ext.XTemplate(
+            '<tpl for=".">',
+                'select a new estimate',
+            '</tpl>'
+          )
+          listeners:
+            click:
+              element: 'el'
+              scope: @
+              fn: @_onReselect
+          renderTo: @.getEl()
+    else
+      # console.log 'update. no vote'
+      @callParent [data]
+      # initialize cards.
+      # @todo any way to create these on initComponent and show/hide instead?
+      for C in @config.deck
+        Ext.create 'Ext.Component',
+          id: 'pokercard-' + C.value
+          cls: 'pokercard'
+          html: C.label
+          config: C
+          listeners:
+            click:
+              element: 'el'
+              scope: @
+              fn: @_onCardClick
+          renderTo: @.getEl()
+    return
+
+  tpl: new Ext.XTemplate(
+    '<tpl for=".">',
+      '<tpl if="vote">',
+        '
Your estimate: {vote}
',
+      '<tpl else>',
+        '
Select an estimate
',
+      '</tpl>',
+    '</tpl>',
+  )
+
+  # listeners:
+  #   beforerender: () ->
+  #     # debugger
+  #     console.log("beforerender. cipher = " + @config.cipher)
+  #     return
+
+  # simple caesar cipher to obfuscate card values using last digit of user id.
+  _encipher: (v) -> (v + @config.cipher) % @config.deck.length
+  _decipher: (v) -> @config.deck[if (v = (v - @config.cipher) % @config.deck.length) < 0 then @config.deck.length + v else v].label
+
+  # helper function bound to card's click event.
+  _onCardClick: (e, t) ->
+    selectedValue = @_encipher Ext.getCmp(t.id).config.value
+    Message = [new Date().getTime(), @config.accountId, selectedValue]
+    pokerMessage = @ParentApp.PokerMessage.compile Message, @ParentApp.Base62.encode
+    Record = Ext.create @ParentApp.models['conversationpost']
+    Record.set
+      Artifact: @ParentApp.CurrentStory.data.keys[0]
+      User: @config.accountId
+      Text: 'Pointed this story with RallyPoker. ' + encodeURIComponent(pokerMessage) + '<\/span>'
+    Record.save
+      success: (b, o) =>
+        @ParentApp.DiscussionsStore.reload()
+        return
+      failure: (b, o) ->
+        # debugger
+        alert 'Error submitting your estimate. Please try again.'
+        return
+    return
+
+  # helper functions bound to the "reselect" link.
+  _onReselect: (e, t) ->
+    EstimateStore = Ext.create 'Rally.data.WsapiDataStore',
+      model: 'conversationpost'
+      autoLoad: true
+      filters: [{
+        property: 'ObjectID'
+        value: t.getAttribute 'data-id'
+      }]
+      limit: 1
+      listeners:
+        scope: @
+        load: @_onEstimateStoreLoad
+    return
+  _onEstimateStoreLoad: (store, result, success) ->
+    if success
+      store.data.items[0].destroy
+        success: () =>
+          @ParentApp.DiscussionsStore.reload()
+          return
+        failure: () ->
+          alert 'Error deleting your estimate. Please try again.'
+          return
+    return
+}


fix #23

fix #23

error: pathspec 'project.coffee' did not match any file(s) known to git

--- project.coffee
+++ project.coffee
@@ -0,0 +1,7 @@
+module.exports =
+  'C:\\Users\\Administrator\\.atom\\packages\\text-transform':
+    url: 'http://localhost:8000/'
+    public: 'public'
+  'C:\\wn':
+    url: 'http://localhost:8000/'
+    public: 'public'


use attachments for help screen

use attachments for help screen

closes #12

--- lib/bot.coffee
+++ lib/bot.coffee
@@ -185,40 +185,59 @@
       runner.start()

     else
-      help = ""
+      helpAttachments = []

       groups = _.groupBy(customCommands, 'category')

       for groupName, groupCommmands of groups
-        help += "\n *#{groupName}*\n"
+        groupText = ""
         for command in _.sortBy(_.values(groupCommmands), "name")
-          help += "• *<#{command.looker.url}/dashboards/#{command.dashboard.id}|#{command.name}>* #{command.helptext}"
+          groupText += "• *<#{command.looker.url}/dashboards/#{command.dashboard.id}|#{command.name}>* #{command.helptext}"
           if command.description
-            help += " — _#{command.description}_"
-          help += "\n"
-        help += "\n"
-
-      help += """
-      *Built-in Commands*\n
+            groupText += " — _#{command.description}_"
+          groupText += "\n"
+
+        helpAttachments.push(
+          title: groupName
+          text: groupText
+          color: "#64518A"
+          mrkdwn_in: ["text"]
+        )
+
+      defaultText = """
       • *find* <look search term> — _Shows the top five Looks matching the search._
       """

       if enableQueryCli
-        help += "• *q* <model_name>/<view_name>/<field>[<filter>] — _Runs a custom query._\n"
-
-      help += "\n"
+        defaultText += "• *q* <model_name>/<view_name>/<field>[<filter>] — _Runs a custom query._\n"
+
+      helpAttachments.push(
+        title: "Built-in Commands"
+        text: defaultText
+        color: "#64518A"
+        mrkdwn_in: ["text"]
+      )
+

       spaces = lookers.filter((l) -> l.customCommandSpaceId ).map((l) ->
         "<#{l.url}/spaces/#{l.customCommandSpaceId}|this space>"
       ).join(" or ")
       if spaces
-        help += "\n_To add your own commands, add a dashboard to #{spaces}._"
+        helpAttachments.push(
+          text: "\n_To add your own commands, add a dashboard to #{spaces}._"
+          color: "#64518A"
+          mrkdwn_in: ["text"]
+        )

       if newVersion
-        help += "\n\n:scream: *<#{newVersion.html_url}|The Looker Slack integration is out of date! Version #{newVersion.tag_name} is now available.>* :scream:"
+        helpAttachments.push(
+          text: "\n\n:scream: *<#{newVersion.html_url}|The Looker Slack integration is out of date! Version #{newVersion.tag_name} is now available.>* :scream:"
+          color: "warning"
+          mrkdwn_in: ["text"]
+        )

       if !isDM || message.text.toLowerCase() == "help"
-        context.replyPrivate({text: help, parse: "none", attachments: []})
+        context.replyPrivate({attachments: helpAttachments})

     refreshCommands()


Simplifies authed calls into getFromJira helper. Fixes sort bug and adds summary to display.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/usermindinc/hubot-jira-reporter.git/'


improved Navbar

improved Navbar

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Arilas/krona.git/'


Switch to continuation-passing style

Switch to continuation-passing style

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/sstephenson/eve.git/'


bug fix

bug fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bubblegroup/bubblebot.git/'


PostieSender class

PostieSender class

error: pathspec 'src/postie_sender.coffee' did not match any file(s) known to git

--- src/postie_sender.coffee
+++ src/postie_sender.coffee
@@ -0,0 +1,11 @@
+class PostieSender
+
+  constructor: (frames, data, callback) ->
+    @parseFrames(frames)
+    @prepareData
+    @dispatch
+    callback()
+
+  parseFrames: (frames) ->
+    _.each frames, (frame) ->
+      if typeof(frame) is ''


Change mention of default behavior in documentation.

--- src/scripts/emoji.coffee
+++ src/scripts/emoji.coffee
@@ -12,8 +12,8 @@
 #   "put a bird on it" - Prints "put a 🐦  on it" in 'more' emoji mode.
 #   "put a :bird: on it" - Prints "put a 🐦  on it" in 'less' emoji mode.
 #   hubot list emoji - Print a list of available emojis
-#   hubot more emoji - (default) Try to substitute all words - no :colons: required.
-#   hubot less emoji - Require :colons: to substitute emojis.
+#   hubot more emoji - Try to substitute all words - no :colons: required.
+#   hubot less emoji - Require :colons: to substitute emojis (default).
 #
 # Notes:
 #   Emoji/unicode pairing data from https://github.com/github/gemoji


client: add connectCompute HOC

client: add connectCompute HOC

connectCompute can be used as a component creating function
to connect compute storage as well as computeController events.

```
ConnectedComponent = connectCompute { ... }, OriginalComponent
```

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

error: pathspec 'client/app/lib/providers/connectcompute.coffee' did not match any file(s) known to git

--- client/app/lib/providers/connectcompute.coffee
+++ client/app/lib/providers/connectcompute.coffee
@@ -0,0 +1,65 @@
+React = require 'app/react'
+kd = require 'kd'
+
+# FIXME: so naive, but works for now.
+makeSingular = (plural) -> plural.slice 0, -1
+
+
+module.exports = connectCompute = (config) -> (WrappedComponent) ->
+
+  class ConnectedCompute extends React.Component
+
+    constructor: (props) ->
+      super props
+
+      @handlers = null
+      @events = {}
+
+      { storage } = kd.singletons.computeController
+
+      state = config.require.reduce (acc, pluralName) ->
+        singularName = makeSingular pluralName
+        # if we pass stackId, machineId or templateId our wrapped component will
+        # receive a prop named stack, machine, template.
+        if resourceId = props["#{singularName}Id"]
+          acc[singularName] = storage.get(pluralName, '_id', resourceId)
+
+        # no matter what, return the full resource just incase the component
+        # wants to use all items for some calculation.
+        acc[pluralName] = storage.get(pluralName)
+
+        return acc
+
+      , {}
+
+      @state = Object.assign(state, props)
+
+    componentDidMount: ->
+
+      { computeController } = kd.singletons
+      { controllerEvents } = config
+
+      Object.keys(controllerEvents).forEach (resource) =>
+        return  unless resourceId = @props["#{resource}Id"]
+
+        handlers = controllerEvents[resource]
+        Object.keys(handlers).forEach (eventName) =>
+          eventId = "#{eventName}-#{resourceId}"
+          return  if @events[eventId]
+
+          @events[eventId] = (event) =>
+            newState = handlers[eventName](event)
+            @setState newState
+
+          computeController.on eventId, @events[eventId]
+
+    componentWillUnmount: ->
+
+      { computeController } = kd.singletons
+
+      Object.keys(@events).forEach (eventId) =>
+        computeController.off eventId, @events[eventId]
+        delete @events[eventId]
+
+    render: ->
+      <WrappedComponent {...@state} />


Update socket.service.coffee

Update socket.service.coffee

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/BennySamir/Tinkerforge-Home.git/'


Fix instance variable use in Begin.coffee template

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/calpath/xsd2bb.git/'


fixed Tutorial.coffee path for Linux

fixed Tutorial.coffee path for Linux

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/steroids.git/'


Post: Add Edit Post button

Post: Add Edit Post button

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Implement getter of "BaseSplit" in IDELayoutManager.


Pricing: Plans: Update some plan descriptions.

--- client/pricing/lib/views/pricingplansview.coffee
+++ client/pricing/lib/views/pricingplansview.coffee
@@ -106,7 +106,7 @@
     reducedMonth : '0'
     yearPrice    : '0'
     discount     : '0'
-    description  : 'Best for tinkering with and learning new technologies'
+    description  : 'Great for tinkering with and learning new technologies'
     cssClass     : 'free'
     planFeatures : [
       { partial: '1 VM'           , cssClass: 'vm-count' }
@@ -124,7 +124,7 @@
     reducedMonth : '9.95'
     yearPrice    : '119.40'
     discount     : 255
-    description  : 'Best for expanded learning or for running a small blog/website'
+    description  : 'Great for expanded learning or running a small blog/site'
     cssClass     : 'hobbyist'
     planFeatures : [
       { partial: '1 VM '           , cssClass: 'vm-count' }


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

error: pathspec 'src/engine_camera.coffee' did not match any file(s) known to git

--- src/engine_camera.coffee
+++ src/engine_camera.coffee
@@ -0,0 +1,17 @@
+Engine.Camera = (I, self) ->
+  currentType = "centered"
+  currentOptions = {}
+  currentObject = null
+
+  followTypes =
+    centered: (object, options) ->
+      Matrix.translation(App.width / 2 - object.I.x, App.height / 2 - object.I.y)
+
+  self.bind "afterUpdate", ->
+    if currentObject
+      I.cameraTransform = followTypes[currentType](currentObject, currentOptions)
+
+  follow: (object, type, options) ->
+    currentObject = object
+    currentType = type
+    currentOptions = options


Fix error message padding when overflowing

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/nathan/lemma.git/'


:lipstick:

:lipstick:

--- src/app/edit-session.coffee
+++ src/app/edit-session.coffee
@@ -843,11 +843,10 @@
   getGrammar: -> @languageMode.grammar

   reloadGrammar: ->
-    grammarChanged = @languageMode.reloadGrammar()
-    if grammarChanged
+    if @languageMode.reloadGrammar()
       @unfoldAll()
       @displayBuffer.tokenizedBuffer.resetScreenLines()
-    grammarChanged
+      true

   getDebugSnapshot: ->
     [


Resolve paths to open in constructor

Resolve paths to open in constructor

--- src/atom-application.coffee
+++ src/atom-application.coffee
@@ -26,7 +26,12 @@
   socketPath: '/tmp/atom.sock'

   constructor: ({@resourcePath, @executedFrom, @pathsToOpen, @testMode, @version}) ->
-    @pathsToOpen ?= [@executedFrom] if @executedFrom
+    if @pathsToOpen?
+      @pathsToOpen = @pathsToOpen.map (pathToOpen) =>
+          path.resolve(@executedFrom, pathToOpen)
+    else
+      @pathsToOpen = [@executedFrom] if @executedFrom
+
     @executedFrom ?= process.cwd()
     atomApplication = this
     @windows = []
@@ -75,9 +80,7 @@

   sendArgumentsToExistingProcess: (callback) ->
     client = net.connect {path: @socketPath}, (args...) =>
-      pathsToOpen = (@pathsToOpen ? []).map (pathToOpen) =>
-        path.resolve(@executedFrom, pathToOpen)
-      output = JSON.stringify({pathsToOpen})
+      output = JSON.stringify({@pathsToOpen})
       client.write(output)
       callback(true)

@@ -188,15 +191,19 @@
     null

   open: (pathsToOpen) ->
-    pathsToOpen ?= [null]
-    for pathToOpen in pathsToOpen
-      pathToOpen = path.resolve(@executedFrom, pathToOpen) if @executedFrom and pathToOpen
-      if existingWindow = @windowForPath(pathToOpen)
-        existingWindow.focus()
-        existingWindow.sendCommand('window:open-path', pathToOpen)
-      else
-        atomWindow = new AtomWindow
-          pathToOpen: pathToOpen
+    if pathsToOpen?
+      for pathToOpen in pathsToOpen
+        pathToOpen = path.resolve(@executedFrom, pathToOpen) if @executedFrom and pathToOpen
+        if existingWindow = @windowForPath(pathToOpen)
+          existingWindow.focus()
+          existingWindow.sendCommand('window:open-path', pathToOpen)
+        else
+          atomWindow = new AtomWindow
+            pathToOpen: pathToOpen
+            bootstrapScript: 'window-bootstrap'
+            resourcePath: @resourcePath
+    else
+      atomWindow = new AtomWindow
           bootstrapScript: 'window-bootstrap'
           resourcePath: @resourcePath


:lipstick: Reorganize option param

:lipstick: Reorganize option param

--- src/atom-application.coffee
+++ src/atom-application.coffee
@@ -269,8 +269,8 @@
       PackageManager = require './package-manager'
       fsUtils = require './fs-utils'
       @packages = new PackageManager
+        configDirPath: fsUtils.absolute('~/.atom')
         devMode: devMode
-        configDirPath: fsUtils.absolute('~/.atom')
         resourcePath: @resourcePath
         urlToOpen: urlToOpen


Fix navbar link test

Fix navbar link test

[#97185164]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/review.git/'


Fix error introduced in 5c155d5eab6632fda9b71713e11af299726d5204.

--- content_scripts/vimium_frontend.coffee
+++ content_scripts/vimium_frontend.coffee
@@ -512,7 +512,8 @@
   chrome.runtime.sendMessage { handler: "isEnabledForUrl", url: url }, (response) ->
     isEnabledForUrl = response.isEnabledForUrl
     passKeys = response.passKeys
-    initializeWhenEnabled() if isEnabledForUrl
+    if isEnabledForUrl
+      initializeWhenEnabled()
     else if (HUD.isReady())
       # Quickly hide any HUD we might already be showing, e.g. if we entered insert mode on page load.
       HUD.hide()


Remove debug statements from script

Remove debug statements from script

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/startae/hub.git/'


Semantic updates to the Slider component.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lonelyplanet/rizzo.git/'


Add cssmask feature detection.

Add cssmask feature detection.


Initial spec for supersonic.ui.drawer

Initial spec for supersonic.ui.drawer

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/supersonic.git/'


Fix json-format module reference

Fix json-format module reference

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


Forgotten file

Forgotten file

error: pathspec 'server/api/register.coffee' did not match any file(s) known to git

--- server/api/register.coffee
+++ server/api/register.coffee
@@ -0,0 +1,69 @@
+import User from '../models/user'
+import RegisteredUser from '../models/registeredUser'
+import InformaticsUser from '../informatics/InformaticsUser'
+
+import logger from '../log'
+
+UNKNOWN_GROUP = '7647'
+
+addUserToUnknownGroup = (uid) ->
+    admin = await RegisteredUser.findAdmin()
+    adminUser = new InformaticsUser(admin.informaticsUsername, admin.informaticsPassword)
+    await adminUser.doLogin()
+
+    href = "http://informatics.mccme.ru/moodle/ajax/ajax.php?sid=&objectName=group&objectId=#{UNKNOWN_GROUP}&selectedName=users&action=add"
+    body = 'addParam={"id":"' + uid + '"}&group_id=&session_sid='
+    await adminUser.download(href, {
+        method: 'POST',
+        headers: {'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8"},
+        body: body,
+        followAllRedirects: true
+    })
+
+export default register = (req, res, next) ->
+    logger.info("Try register user", req.body.username)
+    {username, password, informaticsUsername, informaticsPassword, aboutme, cfLogin} = req.body
+
+    informaticsUser = new InformaticsUser(informaticsUsername, informaticsPassword)
+    informaticsData = await informaticsUser.getData()
+
+    oldUser = await User.findById(informaticsData.id)
+    if not oldUser
+        logger.info "Register new Table User", informaticsData.id
+        newUser = new User(
+            _id: informaticsData.id,
+            name: informaticsData.name,
+            userList: "unknown",
+        )
+        if cfLogin
+            newUser.cf =
+                login: cfLogin
+        await newUser.upsert()
+        if cfLogin
+            await newUser.updateCfRating()
+        await newUser.updateLevel()
+        await newUser.updateRatingEtc()
+
+        # do not await, this can happen asynchronously
+        addUserToUnknownGroup(informaticsData.id)
+    else
+        logger.info "Table User already registered"
+
+    newRegisteredUser = new RegisteredUser({
+        username,
+        informaticsId: informaticsData.id,
+        informaticsUsername,
+        informaticsPassword,
+        aboutme,
+        admin: false
+    })
+    RegisteredUser.register newRegisteredUser, req.body.password, (err) ->
+        if (err)
+            logger.error("Cant register user", err)
+            res.json
+                registered:
+                    error: true
+                    message: if err.name == "UserExistsError" then "Пользователь с таким логином уже сущестует" else "Неопознанная ошибка"
+        else
+            logger.info("Registered user")
+            res.json({registered: {success: true}})


:ok_woman: divide gulpfile to gulpfiles by require-dir

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/naru0504/vccw-gulp.git/'


adds free agent command. Guards configuration on all robot responses.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/usermindinc/hubot-jira-reporter.git/'


[driver] Fix error messages

[driver] Fix error messages

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/demhydraz/cafe.git/'


Updated api for Collections

Updated api for Collections

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/philpl/node-medium.git/'


debug console.log

debug console.log

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/0xenvision/negotiator-inator.git/'


Various atom config changes

Various atom config changes

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/adamalbrecht/dotfiles.git/'


social: only confirm emails whose user status is 'unconfirmed'

--- workers/social/lib/social/models/user/index.coffee
+++ workers/social/lib/social/models/user/index.coffee
@@ -1324,6 +1324,10 @@

   confirmEmail: (callback)->
+
+    if (@getAt 'status') isnt 'unconfirmed'
+      return callback null
+
     @update {$set: status: 'confirmed'}, (err, res)=>
       return callback err if err
       JUser.emit "EmailConfirmed", @


removed convertHelper object

removed convertHelper object

--- workers/social/lib/social/models/user/index.coffee
+++ workers/social/lib/social/models/user/index.coffee
@@ -1213,217 +1213,221 @@
       callback()

-  convertHelper =
-
-    verifyUser : (options, queue, callback) ->
-
-      { slug
-        email
-        recaptcha
-        userFormData
-        foreignAuthType } = options
-
-      invitation = null
-
-      _queue = [
-
-        ->
-          # verifying recaptcha if enabled
-          return _queue.next()  unless KONFIG.recaptcha.enabled
-
-          JUser.verifyRecaptcha recaptcha, { foreignAuthType, slug }, (err) ->
-            return callback err  if err
+  verifyUser = (options, queue, callback) ->
+
+    { slug
+      email
+      recaptcha
+      userFormData
+      foreignAuthType } = options
+
+    invitation = null
+
+    _queue = [
+
+      ->
+        # verifying recaptcha if enabled
+        return _queue.next()  unless KONFIG.recaptcha.enabled
+
+        JUser.verifyRecaptcha recaptcha, { foreignAuthType, slug }, (err) ->
+          return callback err  if err
+          _queue.next()
+
+      ->
+        JUser.validateAll userFormData, (err) ->
+          return callback err  if err
+          _queue.next()
+
+      ->
+        JUser.emailAvailable email, (err, res) ->
+          if err
+            return callback new KodingError 'Something went wrong'
+
+          if res is no
+            return callback new KodingError 'Email is already in use!'
+
+          _queue.next()
+
+      ->
+        queue.next()
+
+    ]
+
+    daisy _queue
+
+
+  verifyEnrollmentEligibility = (options, queue, callback, fetchData) ->
+
+    { email, client, invitationToken } = options
+
+    # check if user can register to regarding group
+    _options =
+      email           : email
+      groupName       : client.context.group
+      invitationToken : invitationToken
+
+    JUser.verifyEnrollmentEligibility _options, (err, res) ->
+      return callback err  if err
+
+      { isEligible, invitation } = res
+
+      if not isEligible
+        return callback new Error "you can not register to #{client.context.group}"
+
+      fetchData invitation
+      queue.next()
+
+
+  createUser = (options, queue, callback, fetchData) ->
+
+    { userInfo } = options
+
+    # creating a new user
+    JUser.createUser userInfo, (err, user_, account_) ->
+      return callback err  if err
+
+      unless user_? and account_?
+        return callback new KodingError 'Failed to create user!'
+
+      fetchData account_, user_
+      queue.next()
+
+
+  updateUserInfo = (options, queue, callback, fetchData) ->
+
+    { user, ip, country, region, username, client, account, clientId } = options
+
+    _queue = [
+
+      ->
+        # updating user's location related info
+        return _queue.next()  unless ip? and country? and region?
+
+        locationModifier =
+          $set                       :
+            'registeredFrom.ip'      : ip
+            'registeredFrom.region'  : region
+            'registeredFrom.country' : country
+
+        user.update locationModifier, ->
+          _queue.next()
+
+      ->
+        JUser.persistOauthInfo username, client.sessionToken, (err) ->
+          return callback err  if err
+          _queue.next()
+
+      ->
+        return _queue.next()  unless username?
+
+        _options =
+          account        : account
+          username       : username
+          clientId       : clientId
+          groupName      : client.context.group
+          isRegistration : yes
+
+        JUser.changeUsernameByAccount _options, (err, newToken_) ->
+          return callback err  if err
+          fetchData newToken_
+          _queue.next()
+
+      ->
+        queue.next()
+
+    ]
+
+    daisy _queue
+
+
+  updateAccountInfo = (options, queue, callback) ->
+
+    { account, referrer, username } = options
+
+    _queue = [
+
+      ->
+        account.update { $set: { type: 'registered' } }, (err) ->
+          return callback err  if err?
+          _queue.next()
+
+      ->
+        account.createSocialApiId (err) ->
+          return callback err  if err
+          _queue.next()
+
+      ->
+        # setting referrer
+        return _queue.next()  unless referrer
+
+        if username is referrer
+          console.error "User (#{username}) tried to refer themself."
+          return _queue.next()
+
+        JUser.count { username: referrer }, (err, count) ->
+          if err? or count < 1
+            console.error 'Provided referrer not valid:', err
+            return _queue.next()
+
+          account.update { $set: { referrerUsername: referrer } }, (err) ->
+
+            if err?
+            then console.error err
+            else console.log "#{referrer} referred #{username}"
+
             _queue.next()

-        ->
-          JUser.validateAll userFormData, (err) ->
-            return callback err  if err
-            _queue.next()
-
-        ->
-          JUser.emailAvailable email, (err, res) ->
-            if err
-              return callback new KodingError 'Something went wrong'
-
-            if res is no
-              return callback new KodingError 'Email is already in use!'
-
-            _queue.next()
-
-        ->
-          queue.next()
-
-      ]
-
-      daisy _queue
-
-    verifyEnrollmentEligibility : (options, queue, callback, fetchData) ->
-
-      { email, client, invitationToken } = options
-
-      # check if user can register to regarding group
+      -> queue.next()
+
+    ]
+
+    daisy _queue
+
+
+  createDefaultStackForKodingGroup = (options, queue) ->
+
+    { account } = options
+
+    # create default stack for koding group, when a user joins this is only
+    # required for koding group, not neeed for other teams
+    _client =
+      connection : delegate : account
+      context    : group    : 'koding'
+
+    ComputeProvider.createGroupStack _client, (err) ->
+      if err?
+        console.warn "Failed to create group stack
+                      for #{account.profile.nickname}:#{err}"
+
+      # We are not returning error here on purpose, even stack template
+      # not created for a user we don't want to break registration process
+      # at all ~ GG
+      queue.next()
+
+
+  confirmDevAccount = (options, queue, callback) ->
+
+    { user, email, username } = options
+
+    if KONFIG.autoConfirmAccounts
+      user.confirmEmail (err) ->
+        console.warn err  if err?
+        queue.next()
+
+    else
       _options =
-        email           : email
-        groupName       : client.context.group
-        invitationToken : invitationToken
-
-      JUser.verifyEnrollmentEligibility _options, (err, res) ->
-        return callback err  if err
-
-        { isEligible, invitation } = res
-
-        if not isEligible
-          return callback new Error "you can not register to #{client.context.group}"
-
-        fetchData invitation
+        email    : email
+        action   : 'verify-account'
+        username : username
+
+      JVerificationToken = require '../verificationtoken'
+      JVerificationToken.createNewPin _options, (err, confirmation) ->
+        if err
+          console.warn 'Failed to send verification token:', err
+        else
+          pin = confirmation.pin
+
         queue.next()
-
-    createUser : (options, queue, callback, fetchData) ->
-
-      { userInfo } = options
-
-      # creating a new user
-      JUser.createUser userInfo, (err, user_, account_) ->
-        return callback err  if err
-
-        unless user_? and account_?
-          return callback new KodingError 'Failed to create user!'
-
-        fetchData account_, user_
-        queue.next()
-
-    updateUserInfo : (options, queue, callback, fetchData) ->
-
-      { user, ip, country, region, username, client, account, clientId } = options
-
-      _queue = [
-
-        ->
-          # updating user's location related info
-          return _queue.next()  unless ip? and country? and region?
-
-          locationModifier =
-            $set                       :
-              'registeredFrom.ip'      : ip
-              'registeredFrom.region'  : region
-              'registeredFrom.country' : country
-
-          user.update locationModifier, ->
-            _queue.next()
-
-        ->
-          JUser.persistOauthInfo username, client.sessionToken, (err) ->
-            return callback err  if err
-            _queue.next()
-
-        ->
-          return _queue.next()  unless username?
-
-          _options =
-            account        : account
-            username       : username
-            clientId       : clientId
-            groupName      : client.context.group
-            isRegistration : yes
-
-          JUser.changeUsernameByAccount _options, (err, newToken_) ->
-            return callback err  if err
-            fetchData newToken_
-            _queue.next()
-
-        ->
-          queue.next()
-
-      ]
-
-      daisy _queue
-
-    updateAccountInfo : (options, queue, callback) ->
-
-      { account, referrer, username } = options
-
-      _queue = [
-
-        ->
-          account.update { $set: { type: 'registered' } }, (err) ->
-            return callback err  if err?
-            _queue.next()
-
-        ->
-          account.createSocialApiId (err) ->
-            return callback err  if err
-            _queue.next()
-
-        ->
-          # setting referrer
-          return _queue.next()  unless referrer
-
-          if username is referrer
-            console.error "User (#{username}) tried to refer themself."
-            return _queue.next()
-
-          JUser.count { username: referrer }, (err, count) ->
-            if err? or count < 1
-              console.error 'Provided referrer not valid:', err
-              return _queue.next()
-
-            account.update { $set: { referrerUsername: referrer } }, (err) ->
-
-              if err?
-              then console.error err
-              else console.log "#{referrer} referred #{username}"
-
-              _queue.next()
-
-        -> queue.next()
-
-      ]
-
-      daisy _queue
-
-    createDefaultStackForKodingGroup : (options, queue) ->
-
-      { account } = options
-
-      # create default stack for koding group, when a user joins this is only
-      # required for koding group, not neeed for other teams
-      _client =
-        connection : delegate : account
-        context    : group    : 'koding'
-
-      ComputeProvider.createGroupStack _client, (err) ->
-        if err?
-          console.warn "Failed to create group stack
-                        for #{account.profile.nickname}:#{err}"
-
-        # We are not returning error here on purpose, even stack template
-        # not created for a user we don't want to break registration process
-        # at all ~ GG
-        queue.next()
-
-    confirmDevAccount : (options, queue, callback) ->
-
-      { user, email, username } = options
-
-      if KONFIG.autoConfirmAccounts
-        user.confirmEmail (err) ->
-          console.warn err  if err?
-          queue.next()
-
-      else
-        _options =
-          email    : email
-          action   : 'verify-account'
-          username : username
-
-        JVerificationToken = require '../verificationtoken'
-        JVerificationToken.createNewPin _options, (err, confirmation) ->
-          if err
-            console.warn 'Failed to send verification token:', err
-          else
-            pin = confirmation.pin
-
-          queue.next()

@@ -1475,7 +1479,7 @@
           queue.next()

       ->
-        convertHelper.verifyUser {
+        verifyUser {
           slug
           email
           recaptcha
@@ -1484,7 +1488,7 @@
         }, queue, callback

       ->
-        convertHelper.verifyEnrollmentEligibility {
+        verifyEnrollmentEligibility {
           email
           client
           invitationToken
@@ -1499,16 +1503,16 @@
           firstName      : firstName
           emailFrequency : emailFrequency

-        convertHelper.createUser { userInfo }, queue, callback, (account_, user_) ->
+        createUser { userInfo }, queue, callback, (account_, user_) ->
           [account, user] = [account_, user_]

       ->
-        convertHelper.updateUserInfo {
+        updateUserInfo {
           user, ip, country, region, username, client, account, clientId
         }, queue, callback, (newToken_) -> newToken = newToken_

       ->
-        convertHelper.updateAccountInfo { account, referrer, username }, queue, callback
+        updateAccountInfo { account, referrer, username }, queue, callback

       =>
         groupNames = [client.context.group, 'koding']
@@ -1518,7 +1522,7 @@
           queue.next()

       ->
-        convertHelper.createDefaultStackForKodingGroup { account }, queue
+        createDefaultStackForKodingGroup { account }, queue

       ->
         user.setPassword password, (err) ->
@@ -1532,7 +1536,7 @@
       ->
         # Auto confirm accounts for development environment
         # This config should be no for production! ~ GG
-        convertHelper.confirmDevAccount {
+        confirmDevAccount {
           user, email, username
         }, queue, callback


Fix the refactoring

Fix the refactoring

--- client/landing/app/Applications/Activity.kdapplication/ListItems/ActivityListItemCodeSnippet.coffee
+++ client/landing/app/Applications/Activity.kdapplication/ListItems/ActivityListItemCodeSnippet.coffee
@@ -101,7 +101,7 @@

     @syntaxMode = new KDCustomHTMLView
       tagName  : "strong"
-      partial  : __aceSettings.syntaxAssociations[syntax][0] or syntax
+      partial  : __aceSettings.syntaxAssociations[syntax]?[0] or syntax

     @saveButton = new KDButtonView
       title     : ""


Removed scoreboard from anonymous navbar.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/cganas/picoCTF-web.git/'


Resetting send as email to false

Resetting send as email to false

--- app/assets/javascripts/query_report.js.coffee
+++ app/assets/javascripts/query_report.js.coffee
@@ -5,4 +5,5 @@
     searchForm.find("#email_to").val(email_to)
     searchForm.find("#subject").val(subject)
     searchForm.find("#message").val(message)
-    searchForm.submit()+    searchForm.submit()
+    searchForm.find("#send_as_email").val(0) #reseting the email back to false


groupcustomization : group logo and cover photo url fix.

--- client/Main/CommonViews/uploadimagemodalview.coffee
+++ client/Main/CommonViews/uploadimagemodalview.coffee
@@ -68,9 +68,9 @@
         group   = KD.singletons.groupsController.getCurrentGroup()

         if @getOptions().image.type is "coverPhoto"
-          group.modify "customize.coverPhoto" : "#{url}?#{Date.now()}", callback
+          group.modify "customize.coverPhoto" : "#{resized}?#{Date.now()}", callback
         else
-          group.modify "customize.logo" : "#{url}?#{Date.now()}", callback
+          group.modify "customize.logo" : "#{resized}?#{Date.now()}", callback

   upload:(callback)->


Client: Activity: Test: Updated CommentList component path


Panel: Resized split view after transition end.


Update spec pattern on meta_spec

Update spec pattern on meta_spec


testrunner: add client test runner socket connector

error: pathspec 'client/testrunner/lib/runnersocketconnector.coffee' did not match any file(s) known to git

--- client/testrunner/lib/runnersocketconnector.coffee
+++ client/testrunner/lib/runnersocketconnector.coffee
@@ -0,0 +1,51 @@
+module.exports = class RunnerSocketConnector
+
+  constructor: (runner, socket) ->
+
+    @_runner = runner
+    @_socket = socket
+
+    @connectRunnerToSocket()
+
+
+  simulateRunnerStartEvent: ->
+
+    @_runner.$events.start.forEach (handler) -> handler?()
+
+
+  connectRunnerToSocket: ->
+
+    @_runner.on 'start', =>
+      @emitToSocket 'start'
+
+    @_runner.on 'suite', (suite) =>
+      @emitToSocket 'suite', suite.title
+
+    @_runner.on 'suite end', =>
+      @emitToSocket 'suite end'
+
+    @_runner.on 'pending', (test) =>
+      @emitToSocket 'pending', test.title
+
+    @_runner.on 'test end', (test) =>
+      @emitToSocket 'test end', test.title
+
+    @_runner.on 'end', =>
+      @emitToSocket 'end'
+
+    @_runner.on 'pass', (test) =>
+      { speed, title, duration } = test
+      slowResult = test.slow()
+      payload = JSON.stringify { speed, title, duration, slowResult }
+      @emitToSocket 'pass', payload
+
+    @_runner.on 'fail', (test, err) =>
+      { title } = test
+      fullTitleResult = test.fullTitle()
+      payload = JSON.stringify { title, err, fullTitleResult }
+      @emitToSocket 'fail', payload
+
+
+  emitToSocket: (args...) -> @_socket.emit args...
+
+


Address style fixes in app.coffee

Address style fixes in app.coffee

--- src/app.coffee
+++ src/app.coffee
@@ -57,11 +57,10 @@
 		updateIpAddr = ->
 			callback = (error, response, body ) ->
 				if !error && response.statusCode == 200
-					api_response = JSON.parse(body)
 					device.updateState(
-						ip_address: api_response.Status
+						ip_address: body.Status
 					)
-			request.get(config.gosuperAddress + '/v1/ipaddr', callback )
+			request.get({ url: "#{config.gosuperAddress}/v1/ipaddr", json: true }, callback )

 		console.log('Starting periodic check for IP addresses..')
 		setInterval(updateIpAddr, 30 * 1000) # Every 30s


added entries.coffee

added entries.coffee

error: pathspec 'app/coffee/entries.coffee' did not match any file(s) known to git

--- app/coffee/entries.coffee
+++ app/coffee/entries.coffee
@@ -0,0 +1,11 @@
+# stretch textarea size - originally from alpha site for text area expansion
+# dr. J's first coffee script!
+window.fitToContent = (id, maxHeight) ->
+  text = if id and id.style then id else document.getElementById(id)
+  return 0 if not text
+  adjustedHeight = text.clientHeight
+  if not maxHeight or maxHeight > adjustedHeight
+    adjustedHeight = Math.max(text.scrollHeight, adjustedHeight)
+    adjustedHeight = Math.min(maxHeight, adjustedHeight) if maxHeight
+    text.style.height = adjustedHeight + 80 + 'px' if adjustedHeight > text.clientHeight
+


refine skip_tutorial

refine skip_tutorial

refine skip_tutorial
using Chinese （）

--- app/locale/zh-HANS.coffee
+++ app/locale/zh-HANS.coffee
@@ -200,7 +200,7 @@
     tome_available_spells: "可用的法术"
     hud_continue: "继续（按 Shift-空格）"
     spell_saved: "咒语已保存"
-    skip_tutorial: "跳过(esc)"
+    skip_tutorial: "跳过（esc）"

   admin:
     av_title: "管理员视图"


Standard things for file CORS

Standard things for file CORS

--- app/assets/javascripts/uploadcare/files/event.js.coffee
+++ app/assets/javascripts/uploadcare/files/event.js.coffee
@@ -26,10 +26,11 @@

         # Naked XHR for progress tracking
         xhr = new XMLHttpRequest()
-        xhr.open 'POST', "#{@settings.urlBase}/iframe/?jsonerrors=1"
+        xhr.open('POST', "#{@settings.urlBase}/iframe/?jsonerrors=1", true)
         xhr.withCredentials = true
         xhr.setRequestHeader('X-PINGOTHER', 'pingpong')
-        xhr.addEventListener 'error timeout abort', fail
+        xhr.addEventListener('error', fail)
+        xhr.addEventListener('abort', fail)
         xhr.addEventListener 'load', =>
           @__uploadDf.resolve(this)
         xhr.addEventListener 'loadend', =>