Admin dashboard perf work

Admin dashboard perf work

Cache invoices on app server, assume they are always fetched most
recent to least.

--- server/payments/subscription_handler.coffee
+++ server/payments/subscription_handler.coffee
@@ -30,6 +30,7 @@
     super(arguments...)

   getCancellations: (req, res) =>
+    # console.log 'subscription_handler getCancellations'
     return @sendForbiddenError(res) unless req.user and req.user.isAdmin()
     @cancellations = []
     nextBatch = (starting_after, done) =>
@@ -72,6 +73,7 @@
       @sendSuccess(res, @cancellations)

   getSubscribers: (req, res) ->
+    # console.log 'subscription_handler getSubscribers'
     return @sendForbiddenError(res) unless req.user and req.user.isAdmin()

     maxReturnCount = req.body.maxCount or 20
@@ -132,6 +134,7 @@
         @sendSuccess(res, @subscribers)

   getSubscriptions: (req, res) ->
+    # console.log 'subscription_handler getSubscriptions'
     # Returns a list of active subscriptions
     # TODO: does not track sponsored subs, only basic
     # TODO: does not return free subs
@@ -142,8 +145,8 @@

     return @sendForbiddenError(res) unless req.user and req.user.isAdmin()

-    # return @sendSuccess(res, @subs) unless _.isEmpty(@subs)
-    @subMap = {}
+    @invoices ?= [] # Keep sorted newest to oldest
+    newInvoices = []

     processInvoices = (starting_after, done) =>
       options = limit: 100
@@ -151,41 +154,49 @@
       stripe.invoices.list options, (err, invoices) =>
         return done(err) if err
         for invoice in invoices.data
+          return done() if invoice.id is @invoices[0]?.invoiceID
           continue unless invoice.paid
           continue unless invoice.subscription
           continue unless invoice.total > 0
           continue unless invoice.lines?.data?[0]?.plan?.id is 'basic'
-          subID = invoice.subscription
-          invoiceDate = new Date(invoice.date * 1000)
-          if subID of @subMap
-            @subMap[subID].first = invoiceDate
-          else
-            @subMap[subID] =
-              first: invoiceDate
-              last: invoiceDate
-              customerID: invoice.customer
+          newInvoices.push
+            customerID: invoice.customer
+            invoiceID: invoice.id
+            subscriptionID: invoice.subscription
+            date: new Date(invoice.date * 1000)
         if invoices.has_more
-          # console.log 'Fetching more invoices', Object.keys(@subMap).length
+          # console.log 'Fetching more invoices', @invoices.length, newInvoices.length
           return processInvoices(invoices.data[invoices.data.length - 1].id, done)
         else
           return done()

     processInvoices null, (err) =>
       return @sendDatabaseError(res, err) if err
-      @subs = []
-      for subID of @subMap
+      @invoices = newInvoices.concat(@invoices)
+      subMap = {}
+      for invoice in @invoices
+        subID = invoice.subscriptionID
+        if subID of subMap
+          subMap[subID].first = invoice.date
+        else
+          subMap[subID] =
+            first: invoice.date
+            last: invoice.date
+            customerID: invoice.customerID
+      subs = []
+      for subID of subMap
         sub =
-          start: @subMap[subID].first
+          start: subMap[subID].first
           subID: subID
-          customerID: @subMap[subID].customerID
-        sub.cancel = @subMap[subID].cancel if @subMap[subID].cancel
+          customerID: subMap[subID].customerID
+        sub.cancel = subMap[subID].cancel if subMap[subID].cancel
         oneMonthAgo = new Date()
         oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1)
-        if @subMap[subID].last < oneMonthAgo
-          sub.end = new Date(@subMap[subID].last)
+        if subMap[subID].last < oneMonthAgo
+          sub.end = new Date(subMap[subID].last)
           sub.end.setUTCMonth(sub.end.getUTCMonth() + 1)
-        @subs.push sub
-      @sendSuccess(res, @subs)
+        subs.push sub
+      @sendSuccess(res, subs)

   subscribeUser: (req, user, done) ->
     if (not req.user) or req.user.isAnonymous() or user.isAnonymous()


bug:Fix subscriptions API variable naming collision

--- server/payments/subscription_handler.coffee
+++ server/payments/subscription_handler.coffee
@@ -14,6 +14,8 @@
 {getSponsoredSubsAmount} = require '../../app/core/utils'

 recipientCouponID = 'free'
+
+# TODO: rename this to avoid collisions with 'subscriptions' variables
 subscriptions = {
   basic: {
     gems: 3500
@@ -71,19 +73,19 @@
   getStripeSubscriptions: (req, res) ->
     # console.log 'subscription_handler getStripeSubscriptions'
     return @sendForbiddenError(res) unless req.user?.isAdmin()
-    subscriptions = []
+    stripeSubscriptions = []
     createGetSubFn = (customerID, subscriptionID) =>
       (done) =>
         stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) =>
           # TODO: return error instead of ignore?
-          subscriptions.push(subscription) unless err
+          stripeSubscriptions.push(subscription) unless err
           done()
     tasks = []
     for subscription in req.body.subscriptions
       tasks.push createGetSubFn(subscription.customerID, subscription.subscriptionID)
     async.parallel tasks, (err, results) =>
       return @sendDatabaseError(res, err) if err
-      @sendSuccess(res, subscriptions)
+      @sendSuccess(res, stripeSubscriptions)

   getSubscribers: (req, res) ->
     # console.log 'subscription_handler getSubscribers'


actually drop the hotel marker for hotel maps

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/'


Check if map is expanded or not before toggling resize


Extended page state to make testable window.location functions


Snap to integer meters in the level editor when holding shift.

--- app/views/editor/level/thangs/ThangsTabView.coffee
+++ app/views/editor/level/thangs/ThangsTabView.coffee
@@ -399,9 +399,14 @@
     thang

   adjustThangPos: (sprite, thang, pos) ->
-    snap = sprite?.data?.snap or sprite?.thangType?.get('snap') or {x: 0.01, y: 0.01}  # Centimeter resolution by default
-    pos.x = Math.round((pos.x - (thang.width ? 1) / 2) / snap.x) * snap.x + (thang.width ? 1) / 2
-    pos.y = Math.round((pos.y - (thang.height ? 1) / 2) / snap.y) * snap.y + (thang.height ? 1) / 2
+    if key.shift
+      # Meter resolution when holding shift, not caring about thang size.
+      pos.x = Math.round pos.x
+      pos.y = Math.round pos.y
+    else
+      snap = sprite?.data?.snap or sprite?.thangType?.get('snap') or x: 0.01, y: 0.01  # Centimeter resolution by default
+      pos.x = Math.round((pos.x - (thang.width ? 1) / 2) / snap.x) * snap.x + (thang.width ? 1) / 2
+      pos.y = Math.round((pos.y - (thang.height ? 1) / 2) / snap.y) * snap.y + (thang.height ? 1) / 2
     pos.z = thang.depth / 2
     thang.pos = pos
     thang.stateChanged = true


slack password protection

slack password protection

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/'


fix to padding

fix to padding


make iframe width 100%

make iframe width 100%

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/CivicCommons/CivicCommons.git/'


Use undefined to clear preference.

Use undefined to clear preference.

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/TeffenEllis/local-preferences.git/'


dont use old compound.io

dont use old compound.io

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/'


[codegen] Wrap name in parenthesis in self_calls

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/'


simplify base scenario for views

simplify base scenario for views

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/'


include student info in badge service call

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/UM-USElab/gradecraft-development.git/'


Add clean task

Add clean task

error: pathspec 'gulp/tasks/clean.coffee' did not match any file(s) known to git

--- gulp/tasks/clean.coffee
+++ gulp/tasks/clean.coffee
@@ -0,0 +1,17 @@
+gulp   = require("gulp")
+del    = require("del")
+config = require("../config")
+
+gulp.task("clean", ["clean:js", "clean:css", "clean:font", "clean:map"])
+
+gulp.task "clean:js", ->
+  del(["#{config.dist.js}/**/*"])
+
+gulp.task "clean:css", ->
+  del(["#{config.dist.css}/**/*"])
+
+gulp.task "clean:font", ->
+  del(["#{config.dist.fonts}/**/*"])
+
+gulp.task "clean:map", ->
+  del(["./assets/**/.map"])


commit

commit

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/Romaboy/awesomeadmin.git/'


Call uses deref_properties

Call uses deref_properties

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/showell/CoffeeCoffee.git/'


fixed coffeelint errors on workers/social/lib/social/models/tag.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/andrewjcasal/koding.git/'


Lots of hackish code to set up calendar UI

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/ESWAT/ottawa.git/'


NotificationCollection: pass isClicable option when creating notification

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/rremizov/github-notifier.git/'


Admin: Resource Management: ResourceListController

error: pathspec 'client/admin/lib/views/resources/resourcelistcontroller.coffee' did not match any file(s) known to git

--- client/admin/lib/views/resources/resourcelistcontroller.coffee
+++ client/admin/lib/views/resources/resourcelistcontroller.coffee
@@ -0,0 +1,80 @@
+kd        = require 'kd'
+remote    = require('app/remote').getInstance()
+showError = require 'app/util/showError'
+
+AccountListViewController = require 'account/controllers/accountlistviewcontroller'
+
+
+module.exports = class ResourceListController extends AccountListViewController
+
+
+  constructor: (options = {}, data) ->
+
+    options = kd.utils.extend {}, options,
+      limit               : 30
+      noItemFoundText     : 'No resource found!'
+      useCustomScrollView : yes
+      startWithLazyLoader : yes
+      lazyLoadThreshold   : .99
+      lazyLoaderOptions   :
+        spinnerOptions    :
+          size            : width: 28
+
+    super options, data
+
+    @states =
+      skip  : 0
+      busy  : no
+      query : {}
+
+
+  followLazyLoad: ->
+
+    @on 'LazyLoadThresholdReached', kd.utils.debounce 300, =>
+
+      return  @hideLazyLoader()  if @states.busy
+
+      @states.busy  = yes
+      @states.skip += @getOption 'limit'
+
+      @fetch @states.query, (err, resources) =>
+
+        @hideLazyLoader()
+
+        if err or not resources
+          return @states.busy = no
+
+        @instantiateListItems resources
+        @states.busy = no
+
+      , { skip : @states.skip }
+
+
+  fetch: (query, callback, options = {}) ->
+
+    callback null, [
+      {title: 'WIP Resource'}
+    ]
+
+
+  loadItems: (query) ->
+
+    @removeAllItems()
+    @showLazyLoader()
+
+    @states.skip = 0
+
+    @states.query = query
+
+    @fetch @states.query, (err, resources) =>
+
+      @hideLazyLoader()
+      @instantiateListItems resources
+
+
+  loadView: ->
+
+    super
+
+    @loadItems()
+    @followLazyLoad()


Add user.isReady in toggleSequence

Add user.isReady in toggleSequence

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/GregDesplaces/classe-1914.git/'


remove tests for refactored elements

remove tests for refactored elements

--- apps/auction/test/templates.coffee
+++ apps/auction/test/templates.coffee
@@ -63,12 +63,9 @@
       it 'renders correctly', ->
         $('.auction-sub-header').text().should.equal 'Sale Preview'
         $('.auction-title').text().should.equal 'An Auction Promo'
-        $('.js-register-button').should.have.lengthOf 0
         $('.auction-grid-artwork').should.have.lengthOf 2
         $('.garamond-tab').should.have.lengthOf 4
         $('.auction-associated-sale').should.have.lengthOf 0
-        $('.auction-header-metadata-cell')
-          .text().should.containEql 'This is a sale preview. Bidding for this auction does not take place on Artsy'

   describe 'with associated sale', ->
     before (done) ->


Add a logging mode that is not too verbose

--- server.coffee
+++ server.coffee
@@ -12,18 +12,22 @@
 logging_enabled = process.env.CAMO_LOGGING_ENABLED || "disabled"
 connect_timeout = process.env.CAMO_CONNECT_TIMEOUT || 10

-log = (msg) ->
-  unless logging_enabled == "disabled"
+debug_log = (msg) ->
+  if logging_enabled == "debug"
     console.log("--------------------------------------------")
     console.log(msg)
     console.log("--------------------------------------------")
+
+error_log = (msg) ->
+  unless logging_enabled == "disabled"
+    console.error("[#{new Date().toISOString()}] #{msg}")

 total_connections   = 0
 current_connections = 0
 started_at          = new Date

-four_oh_four = (resp, msg) ->
-  log msg
+four_oh_four = (resp, msg, url) ->
+  error_log "#{msg}: #{url?.format() or 'unknown'}"
   resp.writeHead 404
   finish resp, "Not Found"

@@ -37,7 +41,7 @@
     src = Http.createClient url.port || 80, url.hostname

     src.on 'error', (error) ->
-      four_oh_four(resp, "Client Request error #{error.stack}")
+      four_oh_four(resp, "Client Request error #{error.stack}", url)

     query_path = url.pathname
     if url.query?
@@ -45,7 +49,7 @@

     transferred_headers.host = url.host

-    log transferred_headers
+    debug_log transferred_headers

     srcReq = src.request 'GET', query_path, transferred_headers

@@ -56,12 +60,12 @@
     srcReq.on 'response', (srcResp) ->
       is_finished = true

-      log srcResp.headers
+      debug_log srcResp.headers

       content_length = srcResp.headers['content-length']

       if content_length > 5242880
-        four_oh_four(resp, "Content-Length exceeded")
+        four_oh_four(resp, "Content-Length exceeded", url)
       else
         newHeaders =
           'content-type'           : srcResp.headers['content-type']
@@ -87,17 +91,17 @@
         switch srcResp.statusCode
           when 200
             if newHeaders['content-type'] && newHeaders['content-type'].slice(0, 5) != 'image'
-              four_oh_four(resp, "Non-Image content-type returned")
+              four_oh_four(resp, "Non-Image content-type returned", url)

-            log newHeaders
+            debug_log newHeaders

             resp.writeHead srcResp.statusCode, newHeaders
             srcResp.pipe resp
           when 301, 302, 303, 307
             if remaining_redirects <= 0
-              four_oh_four(resp, "Exceeded max depth")
+              four_oh_four(resp, "Exceeded max depth", url)
             else if !srcResp.headers['location']
-              four_oh_four(resp, "Redirect with no location")
+              four_oh_four(resp, "Redirect with no location", url)
             else
               is_finished = false
               newUrl = Url.parse srcResp.headers['location']
@@ -105,18 +109,18 @@
                 newUrl.host = newUrl.hostname = url.hostname
                 newUrl.protocol = url.protocol

-              console.log newUrl
+              debug_log "Redirected to #{newUrl.format()}"
               process_url newUrl, transferred_headers, resp, remaining_redirects - 1
           when 304
             resp.writeHead srcResp.statusCode, newHeaders
           else
-            four_oh_four(resp, "Responded with " + srcResp.statusCode + ":" + srcResp.headers)
+            four_oh_four(resp, "Origin responded with #{srcResp.statusCode}", url)
     srcReq.on 'error', ->
       finish resp

     srcReq.end()
   else
-    four_oh_four(resp, "No host found " + url.host)
+    four_oh_four(resp, "No host found " + url.host, url)

 # decode a string of two char hex digits
 hexdec = (str) ->
@@ -160,7 +164,7 @@
       url_type = 'query'
       dest_url = QueryString.parse(url.query).url

-    log({
+    debug_log({
       type:     url_type
       url:      req.url
       headers:  req.headers


Do not log secret key

Do not log secret key

--- server.coffee
+++ server.coffee
@@ -215,6 +215,5 @@
       four_oh_four(resp, "No pathname provided on the server")

 console.log "SSL-Proxy running on #{port} with pid:#{process.pid}."
-console.log "Using the secret key #{shared_key}"

 server.listen port


:: added on classes without new

:: added on classes without new

--- lib/php-class-provider.coffee
+++ lib/php-class-provider.coffee
@@ -23,20 +23,12 @@
     return unless suggestions.length
     return suggestions

-  confirm: (suggestion) ->
-    selection = @editor.getSelection()
-    startPosition = selection.getBufferRange().start
-    buffer = @editor.getBuffer()
-
-    # if some args (even empty) => instanciation
-    if suggestion.data?.args?
-      @showSnippet(suggestion)
+  onDidInsertSuggestion: ({editor, triggerPosition, suggestion}) ->
+    buffer = editor.getBuffer()

     # Static methods on classes
-    else
-      cursorPosition = @editor.getCursorBufferPosition()
-      buffer.delete Range.fromPointWithDelta(cursorPosition, 0, -suggestion.prefix.length)
-      @editor.insertText suggestion.word + "::"
+    if suggestion.data.kind == 'static'
+      editor.insertText "::"

     return false # Don't fall back to the default behavior

@@ -62,10 +54,18 @@
         suggestions.push
           text: word,
           snippet: @getFunctionSnippet(word, @classes.methods[word].constructor.args),
+          data:
+            kind: 'instanciation',
+            prefix: prefix
+
 #          rightLabel: "(#{params})"

       # Not instanciation => not printing constructor params
       else if not instanciation
-        suggestions.push {word: word, prefix: prefix}
+        suggestions.push
+          text: word,
+          data:
+            kind: 'static',
+            prefix: prefix

     return suggestions


Change the default CSS template.

Change the default CSS template.

'background-color' is no longer sufficient to override our default
styling. Refs #626.

--- background_scripts/settings.coffee
+++ background_scripts/settings.coffee
@@ -27,7 +27,7 @@
       """
       div > .vimiumHintMarker {
       /* linkhint boxes */
-      background-color: yellow;
+      background: yellow;
       border: 1px solid #E3BE23;
       }


require handled by CLI now

require handled by CLI now


Elastic search driven autocompleter class

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

--- client/suggestion_completer.coffee
+++ client/suggestion_completer.coffee
@@ -0,0 +1,73 @@
+EventEmitter = require("events").EventEmitter
+
+class SuggestionCompleter extends EventEmitter
+
+  constructor: (@inputEl, @listEl, @options={}) ->
+    @host = @options.host || 'localhost'
+    @port = @options.port || '9200'
+    @suggestionField = @options.suggestionField || "suggest"
+    @suggestionName = @options.suggestionName || "placesuggest"
+    @indexName = @options.indexName || "places"
+    @inputEl.on('input', (e) =>
+      q = $("#q").val()
+      @listEl.empty()
+      if q.length > 2
+        @getAutoCompleteResults(q).then (result) =>
+          @emit('result', result)
+          completions = result[@suggestionName][0].options
+          $.map(completions, (completion) =>
+            @listEl.append("
"+completion.text+"
")
+          )
+    )
+    @index = 0
+    @payload = null
+    @inputEl.on('keyup', (e) =>
+      suggestionEls = $("##{@listEl.attr('id')} li")
+      keycode = event.which || event.keyCode
+      @index = suggestionEls.index($("##{@listEl.attr('id')} li.selected"))
+      switch keycode
+        when 40 # Down
+          if @index == -1 or @index > suggestionEls.length-2
+            @index = 0
+          else
+            @index++
+          console.log @index
+          suggestionEls.removeClass('selected')
+          $(suggestionEls[@index]).addClass('selected')
+          @emit('arrowdown', $("##{@listEl.attr('id')} li.selected").first())
+        when 38 # Up
+          if @index < 0
+            @index = suggestionEls.length-1
+          else
+            @index--
+          suggestionEls.removeClass('selected')
+          $(suggestionEls[@index]).addClass('selected')
+          @emit('arrowup', $("##{@listEl.attr('id')} li.selected").first())
+        when 13 # Enter
+          $("##{@listEl.attr('id')} li").removeClass("current")
+          @payload = $("##{@listEl.attr('id')} li.selected").first().data("payload")
+          @emit('submit', {el: $("##{@listEl.attr('id')} li.selected").first(), payload: @payload})
+          $("##{@listEl.attr('id')} li.selected").first().addClass("current")
+      false
+    )
+    @inputEl.on('submit', (e) =>
+      e.preventDefault()
+      @emit('submit', {el: $("##{@listEl.attr('id')} li.selected").first(), payload: @payload})
+      false
+    )
+
+  getAutoCompleteResults: (q) ->
+    params = '{"' +
+      @suggestionName + '": {"text": "' +
+        q + '", "completion": {"field": "' +
+          @suggestionField +
+            '"}}}'
+    $.post('http://'+@host + ':' +
+        @port +
+          '/'+@indexName+'/_suggest', params
+    )
+
+
+module.exports = SuggestionCompleter


Initialise repository

Initialise repository

--- grammars/roff.cson
+++ grammars/roff.cson
@@ -0,0 +1,3 @@
+name: "Roff"
+scopeName: "source.roff"
+fileTypes: ["1"]


Bump specified ES version from 1.4 to 1.7

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/StreamMachine/StreamMachine.git/'


cleanup

cleanup

--- apps/articles/client/gallery_insights.coffee
+++ apps/articles/client/gallery_insights.coffee
@@ -17,7 +17,6 @@
     sd.SECTION?.id is sd.GALLERY_INSIGHTS_SECTION_ID

   eligibleToSignUp: ->
-    console.log 'moo', @inGIArticlePage(), @inGIVerticalPage(), sd.MAILCHIMP_SUBSCRIBED
     (@inGIArticlePage() or @inGIVerticalPage()) and not sd.MAILCHIMP_SUBSCRIBED

   createAndShowCTAForm: ->


add res parsing to throw error when pretty print styling is present

--- lib/adapters/toffee.coffee
+++ lib/adapters/toffee.coffee
@@ -10,7 +10,11 @@
     @output = 'html'

   _render: (str, options) ->
-    compile => @compiler.str_render(str, options, (err, res) -> res)
+    compile => @compiler.str_render(str, options, (err, res) ->
+      if res.indexOf("<div style=\"font-family:courier new;font-size:12px;color:#900;width:100%;\">") isnt -1
+        throw res
+      else res
+      )

   _compile: (str, options) ->
     compile => @compiler.compileStr(str).toString()


template: edit directive for ide

template: edit directive for ide

error: pathspec 'lib/directives/edit.coffee' did not match any file(s) known to git

--- lib/directives/edit.coffee
+++ lib/directives/edit.coffee
@@ -0,0 +1,62 @@
+path = require 'path'
+fs = require 'fs'
+async = require 'async'
+
+module.exports = class Edit
+  constructor: (@options) ->
+    @hbs = @options.hbs
+
+  # Specifies file or files to show in Editor for edit and evaluation.
+  # If a runner command is given via the `run` option, that is used
+  # to carry out the evaluation.
+  #
+  # In the case that a single file is given, the run command may
+  # be ommitted, and a default is use to exec the given type of file.
+  #
+  # @param filePath (String) the path of the source file to edit.
+  # @option run (String) command to run.
+  #
+  # Outputs a JSON object that the IDE uses to show the file and configure
+  # the runner.
+  #
+  # Example:
+  #
+  # {type: "edit"
+  #  files: [{path: "hello.rb",content: "..."}]
+  #  test: ...
+  #  run: "ruby hello.rb"}
+  process: (@filePath,@options,cb) ->
+    @fullPath = path.join(@options.root,@filePath)
+
+    async.waterfall [
+      (cb) => fs.readFile @fullPath,{encoding: "utf8"}, cb
+      (content,cb) =>
+        data = {
+          type: "edit"
+          file: {path: @filePath, content: content}
+          run: @options.run
+        }
+        cb(null,@ideActionTag(data))
+    ], cb
+
+  # TODO Pull these methods into a base class.
+  #
+  # Escapes a string to make it HTML safe. See note on `safe` about marking
+  # a string as safe.
+  escape: (str) ->
+    @hbs.escape(str)
+
+  # Marks a string as HTML safe.
+  #
+  # NOTE hbs tests if a string needs escaping by testing whether it is an instance of
+  # a SafeString specific the the current instance of handlebars. This is why we need
+  # to proxy the safe string factory via the particular instance of handlebars we are using
+  # instead of the default handlebars instance.
+  safe: (str) ->
+    @hbs.safe(str)
+
+  # Builds a script tag that embeds a json data.
+  # @return (String) a html safe string
+  ideActionTag: (data) ->
+    json = @escape JSON.stringify(data)
+    @safe "<script class='ide-action' type='text/json'>#{json}</script>"


Only hide on close when focused

Only hide on close when focused

--- src/window-event-handler.coffee
+++ src/window-event-handler.coffee
@@ -25,7 +25,7 @@
       rootView?.open(pathToOpen, {initialLine}) unless fsUtils.isDirectorySync(pathToOpen)
     @subscribe $(window), 'beforeunload', =>
       confirmed = rootView?.confirmClose()
-      atom.hide() if confirmed and not @reloadRequested
+      atom.hide() if confirmed and not @reloadRequested and remote.getCurrentWindow().isWebViewFocused()
       @reloadRequested = false
       confirmed
     @subscribeToCommand $(window), 'window:toggle-full-screen', => atom.toggleFullScreen()


add timeout before poller start

add timeout before poller start

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/xaun/impac-angular.git/'


Fix broken benchmark

Fix broken benchmark

--- benchmark/benchmark-suite.coffee
+++ benchmark/benchmark-suite.coffee
@@ -99,6 +99,6 @@
     line = "  l.comment_matcher = new RegExp('^\\s*' + l.symbol + '\\s?')"
     regex = TextMateBundle.grammarForFileName('medium.coffee').initialRule.regex

-  benchmark ".getCaptureTree", 10000, ->
-    regex.getCaptureTree(line, 22)
+  fbenchmark ".getCaptureTree", 10000, ->
+    regex.getCaptureIndices(line, 22)


Don't load user configuration for benchmark, since it changes the performance curve

--- benchmark/benchmark-suite.coffee
+++ benchmark/benchmark-suite.coffee
@@ -8,6 +8,7 @@

   beforeEach ->
     window.rootViewParentSelector = '#jasmine-content'
+    spyOn(window, 'loadUserConfiguration')
     window.startup()
     editor = rootView.activeEditor()


improved Chinese Localization

improved Chinese Localization

Signed-off-by: iAladdin <679e1abc26a0ea5d010d9e2ef227195b64a25a15@me.com>

--- app/locale/zh-HANS.coffee
+++ app/locale/zh-HANS.coffee
@@ -12,7 +12,7 @@
     for_developers: "适合开发者" # Not currently shown on home page.

   nav:
-    play: "开始游戏" # The top nav bar entry where players choose which levels to play
+    play: "关卡选择" # The top nav bar entry where players choose which levels to play
     community: "社区"
     editor: "编辑器"
     blog: "博客"
@@ -249,7 +249,7 @@
     skip_tutorial: "跳过（esc）"
     keyboard_shortcuts: "快捷键"
     loading_ready: "载入完成!"
-    loading_start: "关卡开始"
+    loading_start: "开战"
     problem_alert_title: "修正你的代码"
     time_current: "现在:"
     time_total: "最大:"
@@ -315,7 +315,7 @@
     equip: "装备"
     unequip: "取消装备"

-    buy_gems: "购买宝石"
+  buy_gems:
     few_gems: "几个宝石"
     pile_gems: "一堆宝石"
     chest_gems: "一箱宝石"


Update expected callback name

Update expected callback name

--- build/tasks/codesign-task.coffee
+++ build/tasks/codesign-task.coffee
@@ -22,4 +22,4 @@
   signApp = (callback) ->
     cmd = 'codesign'
     args = ['-f', '-v', '-s', 'Developer ID Application: GitHub', grunt.config.get('atom.shellAppDir')]
-    spawn {cmd, args}, (error) -> done(error)
+    spawn {cmd, args}, (error) -> callback(error)


remove some leftover code

remove some leftover code

--- desktop/apps/partnerships/client/view.coffee
+++ desktop/apps/partnerships/client/view.coffee
@@ -4,7 +4,6 @@
 mediator = require '../../../lib/mediator.coffee'
 { resize } = require '../../../components/resizer/index.coffee'
 { jump } = require '../../../components/jump/view.coffee'
-analyticsHooks = require '../../../lib/analytics_hooks.coffee'

 module.exports = class PartnershipsView extends Backbone.View
   events:


Use standard coffee script syntax.

Use standard coffee script syntax.

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/'


Added giFocus Directive

Added giFocus Directive

error: pathspec 'client/directives/giFocus.coffee' did not match any file(s) known to git

--- client/directives/giFocus.coffee
+++ client/directives/giFocus.coffee
@@ -0,0 +1,17 @@
+angular.module('gi.ui').directive 'giFocus'
+, ['$parse'
+, ($parse) ->
+  restrict: "A"
+  link: (scope, element, attrs) ->
+
+    attrGetter = $parse attrs.giFocus
+
+    checkForChangeInEvaluatedValue = () ->
+      attrGetter(scope)
+
+    scope.$watch(checkForChangeInEvaluatedValue, (newVal) ->
+      if newVal?
+        element[0].focus()
+    )
+
+]


Admin: Plan & Billing: Create sub tabs

Admin: Plan & Billing: Create sub tabs

error: pathspec 'client/admin/lib/views/plan-billing/groupplanbillingview.coffee' did not match any file(s) known to git

--- client/admin/lib/views/plan-billing/groupplanbillingview.coffee
+++ client/admin/lib/views/plan-billing/groupplanbillingview.coffee
@@ -0,0 +1,54 @@
+kd              = require 'kd'
+KDView          = kd.View
+KDTabView       = kd.TabView
+KDTabPaneView   = kd.TabPaneView
+
+GroupTeamsPlan    = require './groupteamsplan'
+GroupBillingInfo  = require './groupbillinginfo'
+GroupUsage        = require './groupusage'
+
+AdminSubTabHandleView = require 'admin/views/customviews/adminsubtabhandleview'
+
+
+module.exports = class GroupPlanBillingView extends KDView
+
+  PANE_NAMES_BY_ROUTE =
+    'Teams-Plan'    : 'Teams Plan'
+    'Billing-Info'  : 'Billing Info'
+    'Usage'         : 'Usage'
+
+
+  constructor: (options = {}, data) ->
+
+    options.cssClass = kd.utils.curry 'plan-biling-view', options.cssClass
+
+    super options, data
+
+    @createTabView()
+
+
+  createTabView: ->
+
+    rootPath = '/Admin/Plan-Billing'
+
+    @addSubView @tabView = new KDTabView
+      hideHandleCloseIcons : yes
+      tabHandleClass       : AdminSubTabHandleView
+
+    @tabView.addPane teamsTabView   = new KDTabPaneView
+      name    : PANE_NAMES_BY_ROUTE['Teams-Plan']
+      route   : "#{rootPath}/Teams-Plan"
+    @tabView.addPane billingView    = new KDTabPaneView
+      name    : PANE_NAMES_BY_ROUTE['Billing-Info']
+      route   : "#{rootPath}/Billing-Info"
+    @tabView.addPane usageView      = new KDTabPaneView
+      name    : PANE_NAMES_BY_ROUTE['Usage']
+      route   : "#{rootPath}/Usage"
+
+    teamsTabView.addSubView @teamsPlan    = new GroupTeamsPlan
+    billingView.addSubView  @billingInfo  = new GroupBillingInfo
+    billingView.addSubView  @usage        = new GroupUsage
+
+    @tabView.showPaneByIndex 0
+
+    @on 'SubTabRequested', (action, identifier) => @tabView.showPaneByName PANE_NAMES_BY_ROUTE[action]


Add coffeelint junit reporter.

Add coffeelint junit reporter.

error: pathspec 'coffeelint-junit-reporter.coffee' did not match any file(s) known to git

--- coffeelint-junit-reporter.coffee
+++ coffeelint-junit-reporter.coffee
@@ -0,0 +1,38 @@
+_ = require 'lodash'
+fs = require 'fs'
+mkdirp = require 'mkdirp'
+path = require 'path'
+xml = require 'xml'
+
+summarize = (errors, filename) ->
+  data = [
+    _attr:
+      name: filename,
+      file: filename
+      timestamp: new Date().toISOString().slice(0, -5)
+      tests: errors.length
+      errors: errors.length
+      time: 0
+  ]
+  if errors.length
+    errors.forEach (error) ->
+      data.push
+        _attr:
+          name: "#{filename}:#{error.lineNumber} #{error.description}"
+          classname: ""
+          time: 0
+      data.push
+        failure:
+          _cdata:
+            error.description
+  {testsuite: data}
+
+module.exports = class CheckstyleReporter
+    constructor: (@errorReport, @options = {}) ->
+      @options.outFile = @options.outFile || process.env.COFFEELINT_JUNIT || 'lint-results.xml';
+
+    publish: =>
+      testsuites = _.map @errorReport.paths, summarize
+      xmlData = xml({testsuites}, {declaration: true, indent: '  '})
+      mkdirp.sync path.dirname(@options.outFile)
+      fs.writeFileSync @options.outFile, xmlData, 'utf-8'


Coffeescript dummy bot

Coffeescript dummy bot

error: pathspec 'bots/dummy/dummy-bot.coffee' did not match any file(s) known to git

--- bots/dummy/dummy-bot.coffee
+++ bots/dummy/dummy-bot.coffee
@@ -0,0 +1,123 @@
+# DUMMY BOT FOR DWARVEN TAVERN
+net = require "net"
+
+# Global variables
+simulationId = if process.argv[2]? then process.argv[2] else null
+server = null
+disconnected = false
+targetY = 0
+deffendingY = 0
+myTeam = ""
+opponentTeam = ""
+
+
+# Auxiliary functions
+getWantedBarrelPos = (barrelPos, wantedY)->
+    x: barrelPos.x;
+    y: if barrelPos.y > wantedY then barrelPos.y+1 else barrelPos.y-1
+
+isEqualPos = (pos1, pos2) ->
+    pos1.x == pos2.x && pos1.y == pos2.y
+
+createActionMoveTo = (bot, toPosition, toEvit) ->
+    direction = "SOUTH" if bot.coords.y < toPosition.y and !isEqualPos(toEvit, x: bot.coords.x, y: bot.coords.y+1)
+    direction = "NORTH" if bot.coords.y > toPosition.y and !isEqualPos(toEvit, x: bot.coords.x, y: bot.coords.y-1)
+    direction = "EAST"  if bot.coords.x < toPosition.x and !isEqualPos(toEvit, x: bot.coords.x+1, y: bot.coords.y)
+    direction = "WEST"  if bot.coords.x > toPosition.x and !isEqualPos(toEvit, x: bot.coords.x-1, y: bot.coords.y)
+
+    if direction?
+        botId: bot.id, type: "MOVE", direction: direction
+    else
+        botId: bot.id, type: "PASS"
+
+
+runTurn = (state) ->
+    # Variables to hold the current state of the simulation
+    myTeamBarrel = state["barrels"][myTeam]["coords"]
+    opponentBarrel = state["barrels"][opponentTeam]["coords"]
+
+    # Bot configuration
+    attackers = []
+    defenders = []
+
+    # Array of actions to send to the server
+    actions = []
+
+    # Attacker Logic
+    attackerBotLogic = (bot) ->
+        wantedPos = getWantedBarrelPos opponentBarrel, targetY
+        if isEqualPos bot.coords, wantedPos
+            actions.push createActionMoveTo(bot, { x: bot.coords.x, y: targetY }, { x: -1, y: -1 })
+        else
+            actions.push createActionMoveTo(bot, wantedPos, opponentBarrel)
+
+    # Defender Logic
+    defenderBotLogic = (bot) ->
+        wantedPos = getWantedBarrelPos myTeamBarrel, deffendingY
+        if isEqualPos bot.coords, wantedPos
+            actions.push createActionMoveTo(bot, {x: bot.coords.x, y: deffendingY}, {x:-1,y:-1})
+        else
+            actions.push createActionMoveTo(bot, wantedPos,myTeamBarrel)
+
+    # We define 3 bots to "attack"..
+    attackers = [ state[myTeam][0], state[myTeam][2], state[myTeam][4]]
+
+    # ... 2 defenders
+    defenders = [ state[myTeam][1], state[myTeam][3]]
+
+    # We create the actions related to the bots
+    attackerBotLogic bot for bot in attackers
+    defenderBotLogic bot for bot in defenders
+
+    turnMessage =
+        type :   "player-turn",
+        actions: actions
+
+    server.write JSON.stringify(turnMessage) unless disconnected
+
+
+joinSimulation = ->
+    server.write JSON.stringify(
+        simulationId : simulationId,
+        type : "join-simulation",
+        nick : "Dummy",
+        names : [
+            "Carawebo",
+            "Pantuflo",
+            "Chistaburras",
+            "Pontato",
+            "Jhonny Tablas"
+        ])
+
+server = net.connect port: 9000, joinSimulation
+
+server.on "data", (data) ->
+    message = JSON.parse data
+
+    switch message["type"]
+        when "game-info"
+            myTeam = message["team"]
+            if myTeam == "team1"
+                targetY = message["height"]
+                deffendingY = message["height"]
+                opponentTeam = "team2"
+            else
+                targetY = 0
+                deffendingY = 0
+                opponentTeam = "team1"
+        when "ready"
+            simulationId = message["simulationId"]
+            joinSimulation()
+
+        when "turn" then runTurn message["state"]
+        when "score" then console.log "SCORE"
+        when "error"
+            console.log if message["message"] == "Player disconnected"
+            server.write JSON.stringify(type: "create-simulation") if message["message"] == "Wrong simulation ID"
+
+        else server.end()
+
+server.on "end", ->
+    disconnected = true
+    console.log "END"
+


removing calculations of ratios from league since new format lets you do that

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/Mikuia/Mikuia.git/'


Fix navigation to use spine routes

Fix navigation to use spine routes

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

--- app/controllers/interactive/navigator.coffee
+++ app/controllers/interactive/navigator.coffee
@@ -0,0 +1,21 @@
+Spine = require 'spine'
+MyGalaxies = require 'controllers/interactive/my_galaxies'
+Graph = require 'controllers/interactive/graph'
+Home = require 'controllers/interactive/interactive'
+
+class Navigator extends Spine.Stack
+  el: '#navigator'
+
+  controllers:
+    myGalaxies: MyGalaxies
+    graph: Graph
+    home: Home
+
+  default: 'home'
+
+  routes:
+    '/navigator' : 'home'
+    '/navigator/graph' : 'graph'
+    '/navigator/my_galaxies' : 'myGalaxies'
+
+module.exports = Navigator


no message

no message

error: pathspec 'lib/utils/progress-bar-view.coffee' did not match any file(s) known to git

--- lib/utils/progress-bar-view.coffee
+++ lib/utils/progress-bar-view.coffee
@@ -0,0 +1,9 @@
+{$, View} = require 'atom-space-pen-views'
+
+module.exports =
+class ProgressBarView extends View
+
+	@content: ->
+    @div class: 'block', =>
+    	@progress class: 'inline-block', =>
+		  	@span 'Indeterminate', class: 'inline-block'


Turkish locale support

Turkish locale support

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

--- pivot.tr.coffee
+++ pivot.tr.coffee
@@ -0,0 +1,57 @@
+callWithJQuery = (pivotModule) ->
+    if typeof exports is "object" and typeof module is "object" # CommonJS
+        pivotModule require("jquery")
+    else if typeof define is "function" and define.amd # AMD
+        define ["jquery"], pivotModule
+    # Plain browser env
+    else
+        pivotModule jQuery
+
+callWithJQuery ($) ->
+    nf = $.pivotUtilities.numberFormat
+    tpl = $.pivotUtilities.aggregatorTemplates
+
+    frFmt =    nf(thousandsSep: ".", decimalSep: ",")
+    frFmtInt = nf(digitsAfterDecimal: 0, thousandsSep: ".", decimalSep: ",")
+    frFmtPct = nf(digitsAfterDecimal: 1, scaler: 100, suffix: "%", thousandsSep: ".", decimalSep: ",")
+
+    $.pivotUtilities.locales.tr =
+
+        localeStrings:
+            renderError: "PivotTable sonuçlarını oluştuturken hata oluştu"
+            computeError: "PivotTable sonuçlarını işlerken hata oluştu"
+            uiRenderError: "PivotTable UI sonuçlarını oluştuturken hata oluştu"
+            selectAll: "Tümünü Seç"
+            selectNone: "Tümünü Bırak"
+            tooMany: "(listelemek için fazla)"
+            filterResults: "Sonuçları filtrele"
+            totals: "Toplam"
+            vs: "vs"
+            by: "ile"
+        aggregators:
+            "Sayı":                             tpl.count(frFmtInt)
+            "Benzersiz değerler sayısı":          tpl.countUnique(frFmtInt)
+            "Benzersiz değerler listesi":           tpl.listUnique(", ")
+            "Toplam":                              tpl.sum(frFmt)
+            "Toplam (tam sayı)":                   tpl.sum(frFmtInt)
+            "Ortalama":                            tpl.average(frFmt)
+            "Min":                                       tpl.min(frFmt)
+            "Maks":                                       tpl.max(frFmt)
+            "Miktarların toplamı":                    tpl.sumOverSum(frFmt)
+            "%80 daha yüksek":        tpl.sumOverSumBound80(true, frFmt)
+            "%80 daha düşük":        tpl.sumOverSumBound80(false, frFmt)
+            "Toplam oranı (toplam)":      tpl.fractionOf(tpl.sum(),   "total", frFmtPct)
+            "Satır oranı (toplam)":    tpl.fractionOf(tpl.sum(),   "row",   frFmtPct)
+            "Sütunun oranı (toplam)":  tpl.fractionOf(tpl.sum(),   "col",   frFmtPct)
+            "Toplam oranı (sayı)":     tpl.fractionOf(tpl.count(), "total", frFmtPct)
+            "Satır oranı (sayı)":   tpl.fractionOf(tpl.count(), "row",   frFmtPct)
+            "Sütunun oranı (sayı)": tpl.fractionOf(tpl.count(), "col",   frFmtPct)
+
+        renderers:
+            "Tablo":                           $.pivotUtilities.renderers["Table"]
+            "Tablo (Çubuklar)":               $.pivotUtilities.renderers["Table Barchart"]
+            "İlgi haritası":                $.pivotUtilities.renderers["Heatmap"]
+            "Satır ilgi haritası":      $.pivotUtilities.renderers["Row Heatmap"]
+            "Sütun ilgi haritası":    $.pivotUtilities.renderers["Col Heatmap"]
+
+


Modes; when exiting on Escape, also grab keyup event.

Fixes #1416.

--- content_scripts/mode.coffee
+++ content_scripts/mode.coffee
@@ -151,6 +151,11 @@
         @exit
           source: ExitOnEscapeMode
           event: event
+        # Suppress the corresponding keyup event too.
+        handlerStack.push
+          keyup: (event) ->
+            @remove() if KeyboardUtils.isEscape event
+            @suppressEvent
         @suppressEvent

 # This mode exits when element (if defined) loses the focus.


fixed share issue

fixed share issue

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/CO-OPEN/Mangos.git/'


Fix command interpreter spec

Fix command interpreter spec

--- src/packages/command-panel/spec/command-interpreter-spec.coffee
+++ src/packages/command-panel/spec/command-interpreter-spec.coffee
@@ -161,6 +161,7 @@
           expect(editSession.getSelection().getBufferRange()).toEqual [[6,16], [6,21]]
           expect(editSession.lineForScreenRow(5).fold).toBeUndefined()
           expect(editSession.lineForScreenRow(10).fold).toBeDefined()
+          editSession.unfoldAll() # cleanup fold marker for after assertion

       it "is case-insentive when the pattern contains no non-escaped uppercase letters (behavior copied from vim)", ->
         waitsForPromise ->


Added the missing script.

Added the missing script.

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

--- scripts/whitelist_room.coffee
+++ scripts/whitelist_room.coffee
@@ -0,0 +1,29 @@
+# Configuration:
+#   HUBOT_ROOM_WHITELIST
+
+reach = require('hoek').reach
+path = require('path')
+
+module.exports = (robot) ->
+
+  # Establish whitelist
+  whitelist = []
+  if process.env.HUBOT_ROOM_WHITELIST
+    whitelist = process.env.HUBOT_ROOM_WHITELIST.split(',')
+  else
+    robot.logger.warning 'no rooms whitelisted'
+
+  unless Array.isArray(whitelist)
+    robot.logger.error 'whitelist is not an array!'
+
+  robot.receiveMiddleware (context, next, done) ->
+    # Unless the room is in the whitelist
+    room = reach(context, 'response.message.room')
+    unless room in whitelist
+      # We're done
+      robot.logger.debug 'Received message from non-whitelisted room: ' + room
+      context.response.message.finish()
+      done()
+    else
+      robot.logger.debug 'Received message from whitelisted room.'
+      next(done)


seed the list of location synonyms -- saint ≈ st

error: pathspec 'apps/galleries_institutions/components/filter_facet/locationSynonyms.coffee' did not match any file(s) known to git

--- apps/galleries_institutions/components/filter_facet/locationSynonyms.coffee
+++ apps/galleries_institutions/components/filter_facet/locationSynonyms.coffee
@@ -0,0 +1,4 @@
+module.exports = [
+  ['st', 'saint']
+]
+


Added hooks

Added hooks

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/threehv/kolo.git/'


Stop stripping mainFiles extension before build

--- lib/builder.coffee
+++ lib/builder.coffee
@@ -151,7 +151,7 @@
       cmd = cmd.split('%BIB').join(bibCompiler)
       cmd = cmd.split('%ARG').join(args)
       cmd = cmd.split('%DOC').join(
-        @escapeFileName(path.basename(@latex.mainFile).replace(/\.[^/.]+$/,""))
+        @escapeFileName(path.basename(@latex.mainFile))
       )
       @cmds.push cmd


Don't bundle nodegit's include headers

Don't bundle nodegit's include headers

--- build/tasks/build-task.coffee
+++ build/tasks/build-task.coffee
@@ -124,6 +124,7 @@
     ignoredPaths.push "#{_.escapeRegExp(path.join('git-utils', 'src') + path.sep)}.*\\.(cc|h)*"
     ignoredPaths.push "#{_.escapeRegExp(path.join('nodegit', 'src') + path.sep)}.*\\.(cc|h)?"
     ignoredPaths.push "#{_.escapeRegExp(path.join('nodegit', 'generate') + path.sep)}.*\\.(cc|h)?"
+    ignoredPaths.push "#{_.escapeRegExp(path.join('nodegit', 'include') + path.sep)}.*\\.(cc|h)?"
     ignoredPaths.push "#{_.escapeRegExp(path.join('keytar', 'src') + path.sep)}.*\\.(cc|h)*"
     ignoredPaths.push "#{_.escapeRegExp(path.join('nslog', 'src') + path.sep)}.*\\.(cc|h)*"
     ignoredPaths.push "#{_.escapeRegExp(path.join('oniguruma', 'src') + path.sep)}.*\\.(cc|h)*"


Abort task when view is created

Abort task when view is created

--- lib/fuzzy-finder.coffee
+++ lib/fuzzy-finder.coffee
@@ -35,6 +35,7 @@

   createView:  ->
     unless @fuzzyFinderView
+      @loadPathsTask?.abort()
       FuzzyFinderView  = require 'fuzzy-finder/lib/fuzzy-finder-view'
       @fuzzyFinderView = new FuzzyFinderView()
       if @projectPaths?.length > 0 and not @fuzzyFinderView.projectPaths?


Create primary.coffee

Create primary.coffee

error: pathspec 'ui/tests/routers/primary.coffee' did not match any file(s) known to git

--- ui/tests/routers/primary.coffee
+++ ui/tests/routers/primary.coffee
@@ -0,0 +1 @@
+describe.skip('PrimaryRouter', ->)


test for #1234

test for #1234

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/maowug/coffeescript.git/'


BF-46 Save user settings

BF-46 Save user settings

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

--- app/assets/javascripts/model/user.coffee
+++ app/assets/javascripts/model/user.coffee
@@ -0,0 +1,64 @@
+### define
+libs/request : request
+###
+
+# This takes care of the userdate.
+User ?= {}
+
+
+User.Configuration =
+
+	#default userdata
+	moveValue : 1
+	rotateValue : 0.01
+	scaleValue : 0.05
+	mouseRotateValue : 0.004
+	mouseInversionX : 1
+	mouseInversionY : 1
+	mouseActive : true
+	keyboardActive : true
+	gamepadActive : false
+	motionsensorActive : false
+
+
+	initialize : ->
+		unless @configDeferred
+
+			@configDeferred = $.Deferred()
+
+			@configDeferred.fail =>
+				@configDeferred = null
+
+			request(url : '/user/configuration').then(
+
+				(data) =>
+					try
+						data = JSON.parse data
+
+
+					catch ex
+						@configDeferred.reject(ex)
+
+					@configDeferred.resolve(data)
+
+				(err) =>
+					@configDeferred.reject(err)
+			)
+
+			@configDeferred.promise()
+
+	push : ->
+		deferred = $.Deferred()
+
+		request(
+			url    : "/user/configuration"
+			method : 'POST'
+			contentType : "application/json"
+			data   : { mouseActive : "false", moveValue : "2" }
+		).fail( =>
+
+			console.log "could'nt save userdata"
+
+		).always(-> deferred.resolve())
+
+		deferred.promise()


add f5 point

add f5 point

error: pathspec 'data/points/f5.coffee' did not match any file(s) known to git

--- data/points/f5.coffee
+++ data/points/f5.coffee
@@ -0,0 +1,6 @@
+id: "f5"
+title: "F5 网页开发调试工具"
+function: [ "debug-tools" ]
+language: [ "html", "javascript" , "CSS"]
+homepage: "http://www.getf5.com/"
+desc: "[F5] 是支持所有编辑器和浏览器的网页开发免刷工具,让你在保存代码的同时，自动刷新页面"


added simple sample

added simple sample

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

--- documentation/coffee/type_annotations.coffee
+++ documentation/coffee/type_annotations.coffee
@@ -0,0 +1,5 @@
+foo <: String = "Hey"
+if foo == "Hey"
+  console.log "Worked!"
+else
+  console.log "Failed! Foo is #{foo}"


Adding examples in CS

Adding examples in CS

Adding topics_extraction and user_profiling Endpoints examples in CoffeeScript.

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

--- examples.coffee
+++ examples.coffee
@@ -0,0 +1,46 @@
+'use strict'
+
+MeaningCloud = require('./index.js')
+meaning      = new MeaningCloud( key: process.env.API_KEY )
+
+# USER PROFILING : CALLBACK MODE
+
+meaning.user_profiling {
+  mode       : 'th'
+  login_name : '@Kikobeats'
+  lang       : 'en'
+}, (err, body, res) ->
+  console.log body
+  return
+
+# USER PROFILING : PROMISE MODE
+
+meaning.user_profiling(
+  mode       : 'th'
+  login_name : '@Kikobeats'
+  lang       : 'en'
+).then (res)->
+  console.log res.body
+
+# TOPICS EXTRACTION | CALLBACK MODE
+
+txt = "Robert Downey Jr has topped Forbes magazine's annual list of the highest paid actors for the second year in a row. The 49-year-old star of the Iron Man and Avengers films made an estimated $75m over the past year, beating rivals Dwayne Johnson, Bradley Cooper, Chris Hemsworth and Leonardo DiCaprio."
+
+meaning.topics_extraction(
+    lang : 'en'
+    txt  : txt
+    tt   : 'a'
+    uw   : 'y'
+, (err, body, res)->
+    console.log body
+)
+
+# TOPICS EXTRACTION | PROMISE MODE
+
+meaning.topics_extraction(
+    lang : 'en'
+    txt  : txt
+    tt   : 'a'
+    uw   : 'y'
+).then (res)->
+    console.log res.body


Use space pen to create inner node HTML

Use space pen to create inner node HTML

--- src/packages/command-logger/src/command-logger.coffee
+++ src/packages/command-logger/src/command-logger.coffee
@@ -63,6 +63,11 @@
         name: "#{_.humanizeEventName(eventName.substring(categoryStart + 1))} (#{details.count})"
         size: details.count
     _.toArray(categories)
+
+  createNodeContent: (node) ->
+    $$$ ->
+      @div style: "height:#{node.dy - 1}px;width:#{node.dx - 1}px", =>
+        @span "#{node.name}"

   addTreeMap: ->
     root =
@@ -145,7 +150,7 @@
         .attr('class', 'foreign-object')
         .append("xhtml:body")
         .attr('class', 'command-logger-node-text')
-        .html((d) -> "
#{d.name}
")
+        .html((d) => @createNodeContent(d))

     d3.select('.command-logger').on('click', -> zoom(root))


[optimise] Fix tables being visited

[optimise] Fix tables being visited

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/'


Explicitly assert for file contained in traversed symlink directory

--- spec/fuzzy-finder-spec.coffee
+++ spec/fuzzy-finder-spec.coffee
@@ -139,6 +139,7 @@

             runs ->
               expect(projectView.list.find("li:contains(symlink-to-dir)")).not.toExist()
+              expect(projectView.list.find("li:contains(symlink-to-dir/a)")).not.toExist()

           it "includes symlinked folder paths if traverseIntoSymlinkDirectories is true", ->
             atom.config.set('fuzzy-finder.traverseIntoSymlinkDirectories', true)
@@ -151,7 +152,7 @@
               projectView.paths?.length > 0

             runs ->
-              expect(projectView.list.find("li:contains(symlink-to-dir)")).toExist()
+              expect(projectView.list.find("li:contains(symlink-to-dir/a)")).toExist()

       describe "when root view's project has no path", ->
         beforeEach ->


Add more specs

Add more specs

--- spec/onig-reg-exp-spec.coffee
+++ spec/onig-reg-exp-spec.coffee
@@ -1,14 +1,31 @@
 {OnigRegExp} = require '../lib/oniguruma'

 describe 'OnigRegExp', ->
-  describe 'when the string being searched contains a unicode character', ->
-    it "returns correct indices and lengths", ->
-      regex = new OnigRegExp('a')
+  describe 'search(string, index)', ->
+    it 'returns an array of the match and all capture groups', ->
+      regex = new OnigRegExp('\\w(\\d+)')
+      result = regex.search('----a123----')
+      expect(result.length).toBe 2
+      expect(result[0]).toBe 'a123'
+      expect(result[1]).toBe '123'
+      expect(result.index).toBe 4
+      expect(result.indices.length).toBe 2
+      expect(result.indices[0]).toBe 4
+      expect(result.indices[1]).toBe 5

-      firstMatch = regex.search('ç√Ωa', 0)
-      expect(firstMatch.index).toBe 3
-      expect(firstMatch[0]).toBe 'a'
+    it 'returns null if it does not match', ->
+      regex = new OnigRegExp('\\w(\\d+)')
+      result = regex.search('--------')
+      expect(result).toBeNull()

-      secondMatch = regex.search('ç√Ωabcd≈ßåabcd', 5)
-      expect(secondMatch.index).toBe 10
-      expect(secondMatch[0]).toBe 'a'
+    describe 'when the string being searched contains a unicode character', ->
+      it 'returns correct indices and lengths', ->
+        regex = new OnigRegExp('a')
+
+        firstMatch = regex.search('ç√Ωa', 0)
+        expect(firstMatch.index).toBe 3
+        expect(firstMatch[0]).toBe 'a'
+
+        secondMatch = regex.search('ç√Ωabcd≈ßåabcd', 5)
+        expect(secondMatch.index).toBe 10
+        expect(secondMatch[0]).toBe 'a'


forgot one

forgot one

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/'


Null guard container in Pane::makeActive

Panes can exist outside of containers, albeit only briefly. If
::makeActive is called when the pane is in this state, consider it a
no-op.

--- src/pane-model.coffee
+++ src/pane-model.coffee
@@ -62,7 +62,7 @@

   isActive: -> @active

-  makeActive: -> @container.activePane = this
+  makeActive: -> @container?.activePane = this

   getPanes: -> [this]


fix comments

fix comments

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/showell/CoffeeCoffee.git/'


:bug:Fix subscribe prevented by no preferredLanguage

--- app/views/core/SubscribeModal.coffee
+++ app/views/core/SubscribeModal.coffee
@@ -112,7 +112,7 @@
     options = {
       description: $.i18n.t('subscribe.stripe_description')
       amount: @product.amount
-      alipay: if me.get('chinaVersion') or me.get('preferredLanguage')[...2] is 'zh' then true else 'auto'
+      alipay: if me.get('chinaVersion') or me.get('preferredLanguage')?[...2] is 'zh' then true else 'auto'
       alipayReusable: true
     }


Create new global Coffee file

Create new global Coffee file

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/Margatroid/Anilytics.git/'


Bug fix for no tags.

Bug fix for no tags.

--- app/assets/javascripts/groups.js.coffee
+++ app/assets/javascripts/groups.js.coffee
@@ -33,7 +33,8 @@

       # Prepopulate token inputs with tags
       $($("#user-existing-tags-#{$(user_list_element).attr("id")}").val().split(",")).each (index, element) =>
-        token_input_object.tokenInput("add", {id: element, name: element})
+        if (element != "")
+          token_input_object.tokenInput("add", {id: element, name: element})

     if window.location.href.split("#")[1] == "users"
       $(".tabs a:last").click()


Add atom packages list

Add atom packages list

error: pathspec 'public/.atom/packages.cson' did not match any file(s) known to git

--- public/.atom/packages.cson
+++ public/.atom/packages.cson
@@ -0,0 +1,25 @@
+packages: [
+  "docblockr"
+  "editorconfig"
+  "emmet"
+  "emmet-jsx-css-modules"
+  "file-type-icons"
+  "git-time-machine"
+  "hyperclick"
+  "js-hyperclick"
+  "language-babel"
+  "language-docker"
+  "language-postcss"
+  "linter"
+  "linter-eslint"
+  "linter-js-standard"
+  "linter-xo"
+  "merge-conflicts"
+  "minimap"
+  "node_modules"
+  "package-sync"
+  "pigments"
+  "regex-railroad-diagram-fork"
+  "sort-lines"
+  "svg-preview"
+]


Improve archive:darwin task

Improve archive:darwin task

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/'


Tab recency; eliminate potential memory leak.

--- background_scripts/completion.coffee
+++ background_scripts/completion.coffee
@@ -266,6 +266,7 @@
     @timestamp = 1
     @current = -1
     @cache = {}
+    @removed = []

     chrome.tabs.onActivated.addListener (activeInfo) => @add activeInfo.tabId
     chrome.tabs.onRemoved.addListener (tabId) => @remove tabId
@@ -276,21 +277,24 @@

   add: (tabId) ->
     @current = tabId
-    @registerTabSoon tabId
+    @registerVisitSoon tabId

   remove: (tabId) ->
+    @removed.push tabId
     delete @cache[tabId]

-  # Call callback in 750ms time; unless we're pre-empted by another call before then.  The idea is that tabs
-  # which are visited only for a very-short time (e.g. with `3J`) shouldn't register as visited at all.
-  registerTabSoon: do ->
+  # Register tabId in 500ms time, unless another tab is visited before then.  Tabs which are visited only for
+  # a very-short time (e.g. those passed through with `5J`) shouldn't be registered as visited at all.
+  registerVisitSoon: do ->
     timer = null
     (tabId) ->
       clearTimeout timer if timer
       timer = setTimeout (=>
         timer = null
-        @cache[tabId] = ++@timestamp)
-      , 750
+        # Register visit, except if tabId has already been removed (note: tab IDs are unique).
+        @cache[tabId] = ++@timestamp unless tabId in @removed
+        @removed = [])
+      , 500

   # Recently-visited tabs get a higher score (except the current tab, which gets a low score).
   recencyScore: (tabId) ->


Search completion; promote the top completion.

This puts the first (top) completion suggestion at the top of the list:
either one or two <Tab>s away, depending upon whether a domain-completer
suggestion is present or not.

--- background_scripts/completion.coffee
+++ background_scripts/completion.coffee
@@ -10,7 +10,7 @@
 #  - refresh(): (optional) refreshes the completer's data source (e.g. refetches the list of bookmarks).
 #  - cancel(): (optional) cancels any pending, cancelable action.
 class Suggestion
-  showRelevancy: true # Set this to true to render relevancy when debugging the ranking scores.
+  showRelevancy: false # Set this to true to render relevancy when debugging the ranking scores.

   constructor: (@options) ->
     # Required options.
@@ -281,7 +281,7 @@
         queryTerms: queryTerms
         type: "domain"
         url: domains[0]?[0] ? "" # This is the URL or an empty string, but not null.
-        relevancy: 1
+        relevancy: 2
       ].filter (s) -> 0 < s.url.length

   # Returns a list of domains of the form: [ [domain, relevancy], ... ]
@@ -477,22 +477,28 @@
       type: description
       url: Utils.createSearchUrl queryTerms, searchUrl
       title: queryTerms.join " "
-      relevancy: 1
+      relevancy: 2
       autoSelect: custom
       forceAutoSelect: custom
       highlightTerms: not haveCompletionEngine

-    mkSuggestion = (suggestion) =>
-      new Suggestion
-        queryTerms: queryTerms
-        type: description
-        url: Utils.createSearchUrl suggestion, searchUrl
-        title: suggestion
-        insertText: suggestion
-        highlightTerms: false
-        isCustomSearch: custom
-        relevancyFunction: @computeRelevancy
-        relevancyData: factor
+    mkSuggestion = do =>
+      count = 0
+      (suggestion) =>
+        console.log count
+        new Suggestion
+          queryTerms: queryTerms
+          type: description
+          url: Utils.createSearchUrl suggestion, searchUrl
+          title: suggestion
+          insertText: suggestion
+          highlightTerms: false
+          isCustomSearch: custom
+          # The first (top) suggestion gets a score of 1.  This puts it two <Tab>s away if a domain completion
+          # is present (which has a score of 2), and one <Tab> away otherwise.
+          relevancy: if 0 < count++ then null else 1
+          relevancyFunction: @computeRelevancy
+          relevancyData: factor

     cachedSuggestions =
       if haveCompletionEngine then CompletionSearch.complete searchUrl, queryTerms else null


fix: initRecipeValues does not activate save 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/keboola/kbc-ui-doctool-recipes.git/'


Updated time service to mark either the held item or current items time slot as available [BOOK-680]

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/Bogdan-p/bookingbug-angular.git/'


More work in the animate function

More work in the animate 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/chapelaria/readerly.git/'


fix(run recipe): do not force _blank in notification message


test/dashboard: add myteam test file with sendInvites function

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

--- client/test/lib/dashboard/myteam.coffee
+++ client/test/lib/dashboard/myteam.coffee
@@ -0,0 +1,15 @@
+utils = require '../utils/utils.js'
+helpers = require '../helpers/helpers.js'
+teamsHelpers = require '../helpers/teamshelpers.js'
+utils = require '../utils/utils.js'
+myteamhelpers = require '../helpers/myteamhelpers.js'
+myTeamLink = "#{helpers.getUrl(yes)}/Home/my-team"
+
+module.exports =
+
+  sendInvites: (browser) ->
+
+    user = teamsHelpers.loginTeam browser
+    browser.url myTeamLink
+    myteamhelpers.inviteUser browser
+    browser.end()


fix routing

fix routing

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

--- server/initializers.coffee
+++ server/initializers.coffee
@@ -0,0 +1,4 @@
+Accounts.onCreateUser (options, user) ->
+  user.profile = {} if user.profile is undefined
+  _.extend user.profile, {"credits": 300}
+  user


NPM download manifest: handle the no response case

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/'


Emulate selectable with mouseup and down

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/josh/transit.git/'


Fix variable name

Fix variable name

[#99863370]

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/'


Remove ,

Remove ,

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/MP3-Downloader.git/'


Throw err if connection to mongodb fails

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/ronaldcurtis/express-starter-app.git/'


coffee scriptバージョンbinary search

coffee scriptバージョンbinary search

楽しくて書いちゃった。
でもcoffeeのfor..inとfor..ofとfor..fromはjsの動作と違うから、coffeeちょっとあきらめた

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

--- lib/coffee/binary_search.coffee
+++ lib/coffee/binary_search.coffee
@@ -0,0 +1,14 @@
+
+"use strict";
+
+binary_search = (low, high, value, list) ->
+  mid = parseInt( (parseInt(high) + parseInt low) / 2 )
+  # console.log low + " " + high
+  # console.log "mid: " + (parseInt(high) + parseInt low)/2
+  if value is list[mid] then return mid;
+  if high - low <= 1 then return -1;
+  if value < list[mid]
+    return binary_search(low, mid, value, list);
+  else if value > list[mid]
+    return binary_search(mid+1, high, value, list);
+


add src, source folder and defaul in foo.coffee in folder

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

--- src/foo.coffee
+++ src/foo.coffee
@@ -0,0 +1 @@
+console.log "hello world"


Update font specs for windows

Update font specs for windows

--- spec/editor-spec.coffee
+++ spec/editor-spec.coffee
@@ -296,20 +296,28 @@
       expect(editor.css('font-family')).toBe ''

     describe "when the font family changes", ->
+      [fontFamily] = []
+
+      beforeEach ->
+        if process.platform is 'darwin'
+          fontFamily = "PCMyungjo"
+        else
+          fontFamily = "Consolas"
+
       it "updates the font family of editors and recalculates dimensions critical to cursor positioning", ->
         editor.attachToDom(12)
         lineHeightBefore = editor.lineHeight
         charWidthBefore = editor.charWidth
         editor.setCursorScreenPosition [5, 6]

-        config.set("editor.fontFamily", "PCMyungjo")
-        expect(editor.css('font-family')).toBe 'PCMyungjo'
+        config.set("editor.fontFamily", fontFamily)
+        expect(editor.css('font-family')).toBe fontFamily
         expect(editor.charWidth).not.toBe charWidthBefore
         expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 6 * editor.charWidth }

         newEditor = new Editor(editor.activeEditSession.copy())
         newEditor.attachToDom()
-        expect(newEditor.css('font-family')).toBe 'PCMyungjo'
+        expect(newEditor.css('font-family')).toBe fontFamily

   describe "font size", ->
     beforeEach ->
@@ -911,11 +919,19 @@
         beforeEach ->
           editor.setFontFamily('sans-serif')

-        it "correctly positions the cursor", ->
-          editor.setCursorBufferPosition([3, 30])
-          expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 178}
-          editor.setCursorBufferPosition([3, Infinity])
-          expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 353}
+        describe "on #darwin or #linux", ->
+          it "correctly positions the cursor", ->
+            editor.setCursorBufferPosition([3, 30])
+            expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 178}
+            editor.setCursorBufferPosition([3, Infinity])
+            expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 353}
+
+        describe "on #win32", ->
+          it "correctly positions the cursor", ->
+            editor.setCursorBufferPosition([3, 30])
+            expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 175}
+            editor.setCursorBufferPosition([3, Infinity])
+            expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 346}

       describe "autoscrolling", ->
         it "only autoscrolls when the last cursor is moved", ->


Add new event method for unhandled errors.

--- src/atom.coffee
+++ src/atom.coffee
@@ -177,6 +177,7 @@
       @executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
       @lastUncaughtError = Array::slice.call(arguments)
       @emit 'uncaught-error', arguments...
+      @emitter.emit 'did-throw-error', arguments...

     @unsubscribe()
     @setBodyPlatformClass()
@@ -247,6 +248,15 @@
   onDidBeep: (callback) ->
     @emitter.on 'did-beep', callback

+  # Extended: Invoke the given callback whenever there is an unhandled error.
+  #
+  # * `callback` {Function} to be called whenever there is an unhandled error
+  #   * `errorMessage` {String}
+  #
+  # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
+  onDidThrowError: (callback) ->
+    @emitter.on 'did-throw-error', callback
+
   ###
   Section: Atom Details
   ###


Ad script that spits out the Shake Shack Cam photo

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

--- src/scripts/shakeshack.coffee
+++ src/scripts/shakeshack.coffee
@@ -0,0 +1,12 @@
+# Description:
+#   A command that shows us a photo of the current line at Shake Shack
+#
+# Commands:
+#   hubot shake cam - Returns an image of the line at Shake Shack
+#
+# Author:
+#   desmondmorris
+
+module.exports = (robot) ->
+  robot.respond /shake cam/i, (msg) ->
+    msg.send 'http://www.shakeshack.com/camera.jpg'


Create My Bot

Create My Bot

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

--- src/cron.coffee
+++ src/cron.coffee
@@ -0,0 +1,15 @@
+cron = require('cron').CronJob
+
+module.exports = (robot) ->
+
+ new cron('0 45 11 * * 1-5',
+   () -> robot.messageRoom(process.env.HUBOT_HIPCHAT_ROOMS, "そろそろお昼の時間です。やったことをまとめてください")
+ , null, true, "Asia/Tokyo")
+
+ new cron('0 45 15 * * 1-5',
+   () -> robot.messageRoom(process.env.HUBOT_HIPCHAT_ROOMS, "そろそろおやつの時間です。やったことをまとめてください")
+ , null, true, "Asia/Tokyo")
+
+ new cron('0 45 18 * * 1-5',
+   () -> robot.messageRoom(process.env.HUBOT_HIPCHAT_ROOMS, "そろそろ終業時間です。やったことをまとめてください")
+ , null, true, "Asia/Tokyo")


Actually store the cached contents of a file.

Big Beautiful Arrows

--- src/file.coffee
+++ src/file.coffee
@@ -95,7 +95,7 @@
     else
       promise = Q(@cachedContents)

-    promise.then (contents) ->
+    promise.then (contents) =>
       @cachedContents = contents

   # Public: Returns whether a file exists.


Replace default menu with custom built menu.

--- src/main.coffee
+++ src/main.coffee
@@ -2,6 +2,7 @@
 delegate = require 'atom_delegate'
 path = require 'path'
 BrowserWindow = require 'browser_window'
+Menu = require 'menu'
 ipc = require 'ipc'
 dialog = require 'dialog'
 optimist = require 'optimist'
@@ -15,6 +16,7 @@

     @setupJavaScriptArguments()
     @parseCommandLine()
+    @buildApplicationmenu()
     @setupNodePaths()
     @handleEvents()

@@ -25,6 +27,63 @@
     modifiedArgv = ['node'].concat(process.argv) # optimist assumes the first arg will be node
     args = optimist(modifiedArgv).argv
     @resourcePath = args['resource-path']
+
+  buildApplicationmenu: ->
+    template = [
+      label: 'Atom'
+      submenu: [
+        label: 'About Atom'
+        selector: 'orderFrontStandardAboutPanel:'
+      ,
+        type: 'separator'
+      ,
+        label: 'Hide Atom Shell'
+        accelerator: 'Command+H'
+        selector: 'hide:'
+      ,
+        label: 'Hide Others'
+        accelerator: 'Command+Shift+H'
+        selector: 'hideOtherApplications:'
+      ,
+        label: 'Show All'
+        selector: 'unhideAllApplications:'
+      ,
+        type: 'separator'
+      ,
+        label: 'Quit'
+        accelerator: 'Command+Q'
+        click: -> app.quit()
+      ]
+    ,
+      label: 'View'
+      submenu: [
+        label: 'Reload'
+        accelerator: 'Command+R'
+        click: -> BrowserWindow.getFocusedWindow()?.reloadIgnoringCache()
+      ,
+        label: 'Toggle DevTools',
+        accelerator: 'Alt+Command+I',
+        click: -> BrowserWindow.getFocusedWindow()?.toggleDevTools()
+      ]
+    ,
+      label: 'Window'
+      submenu: [
+        label: 'Minimize'
+        accelerator: 'Command+M'
+        selector: 'performMiniaturize:'
+      ,
+        label: 'Close'
+        accelerator: 'Command+W'
+        selector: 'performClose:'
+      ,
+        type: 'separator'
+      ,
+        label: 'Bring All to Front'
+        selector: 'arrangeInFront:'
+      ]
+    ]
+
+    @menu = Menu.buildFromTemplate template

   setupNodePaths: ->
     resourcePaths = [
@@ -100,6 +159,8 @@
 browserMain = new BrowserMain

 delegate.browserMainParts.preMainMessageLoopRun = ->
+  Menu.setApplicationMenu browserMain.menu
+
   new AtomWindow
     bootstrapScript: 'window-bootstrap',
     resourcePath: browserMain.resourcePath


Removed bindMeteor().

Removed bindMeteor().

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/urbanetic/meteor-aurin-acs.git/'


can now type chars and hit enter!

can now type chars and hit enter!

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/robey/carrot16.git/'


commented #99, adding multiline description to a method, for testing

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/gilt/groc.git/'


Removed another redundant function and cleaned up code. Oh, and actually made the XHR send...

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/'


Remove call to removed function

Remove call to removed function

--- src/module-cache.coffee
+++ src/module-cache.coffee
@@ -215,7 +215,6 @@
   cache.registered = true
   cache.resourcePath = resourcePath
   registerBuiltins(devMode)
-  requireDependencies()

   return


fix font task not working

fix font task not working

--- app/templates/gulpfile.coffee
+++ app/templates/gulpfile.coffee
@@ -194,10 +194,10 @@
 #     $FONT REV
 #*------------------------------------*/
 gulp.task "font", () ->
-  files = ['eot', 'woff', 'ttf', 'svg'].map (ext) ->
-    "#{conf.path.dev.img}/**/*.#{ext}"
-
-  gulp.src(["#{conf.path.dev.fnt}/**/*.#{exts[key]}"])
+  files = ['eot', 'woff', 'ttf', 'svg'].map (curr) ->
+    "#{conf.path.dev.fnt}/**/*#{curr}"
+
+  gulp.src(files)
     .pipe cache(rev())
     .pipe remember()
     .pipe gulp.dest(conf.path.prod.fnt)


Consolidate 'Returns' to one line per comments

--- src/notification.coffee
+++ src/notification.coffee
@@ -45,14 +45,10 @@
   Section: Methods
   ###

-  # Public: Retrieves the {String} type.
-  #
-  # Returns a {String}.
+  # Public: Returns the {String} type.
   getType: -> @type

-  # Public: Retrieves the {String} message.
-  #
-  # Returns a {String}.
+  # Public: Returns the {String} message.
   getMessage: -> @message

   getTimestamp: -> @timestamp


refactor popup code

refactor popup code

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-chrome-extension.git/'


Show table can provide now.

Show table can provide now.

error: pathspec 'resources/tools/show-table/provider.coffee' did not match any file(s) known to git

--- resources/tools/show-table/provider.coffee
+++ resources/tools/show-table/provider.coffee
@@ -0,0 +1,17 @@
+define [], ->
+
+  Array '$q', '$log', (Q, console) -> handleRequest = (previousStep, data) ->
+
+    {request, service} = data
+
+    step =
+      title: "Ran query"
+      tool: "show-table"
+      data:
+        query: request.query
+        service: service
+
+    console.debug step, data
+
+    return Q.when(step)
+


debug statement no longer needed

debug statement no longer needed

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/davepwsmith/zotero-better-bibtex.git/'


standalone doesn't have extension version -- it's not an extension

--- chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
+++ chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
@@ -56,10 +56,7 @@
 Zotero.BetterBibTeX.extensionConflicts = ->
   AddonManager.getAddonByID('{359f0058-a6ca-443e-8dd8-09868141bebc}', (recoll) ->
     return unless recoll
-    version = recoll.version.split('.')
-    return if parseInt(version[0]) > 1
-    return if parseInt(version[1]) > 2
-    return if parseInt(version[2]) > 3
+    return if Services.vc.compare('1.2.3', recoll.version) > 0
     Zotero.BetterBibTeX.removeTranslators()
     Zotero.BetterBibTeX.disabled = '''
       Better BibTeX has been disabled because it has detected conflicting extension "recoll-firefox" 1.2.3 or
@@ -74,16 +71,11 @@
     '''
     Zotero.BetterBibTeX.flash('Better BibTeX has been disabled', Zotero.BetterBibTeX.disabled)
   )
-  AddonManager.getAddonByID('zotero@chnm.gmu.edu', (zotero) ->
-    zotero = {version: '0.0.0'} unless zotero
-    version = zotero.version.split('.')
-    return if parseInt(version[0]) > 4
-    return if parseInt(version[1]) > 0
-    return if parseInt(version[2]) > 26
+
+  if Services.vc.compare('4.0.27', ZOTERO_CONFIG.VERSION) < 0
     Zotero.BetterBibTeX.removeTranslators()
-    Zotero.BetterBibTeX.disabled = 'Better BibTeX has been disabled because it did not find Zotero 4.0.27 or later.'
+    Zotero.BetterBibTeX.disabled = "Better BibTeX has been disabled because it found Zotero #{zotero.version}, but requires 4.0.27 or later."
     Zotero.BetterBibTeX.flash('Better BibTeX has been disabled', Zotero.BetterBibTeX.disabled)
-  )

 Zotero.BetterBibTeX.flash = (title, body) ->
   Zotero.BetterBibTeX.debug('flash:', title)


Added the Exo namespace

Added the Exo namespace

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

--- exo.coffee
+++ exo.coffee
@@ -0,0 +1,7 @@
+# Globals
+Exo = @Exo = {}
+module?.exports  = Exo
+
+Exo.Model = require('lib/exo/model')
+Exo.List = require('lib/exo/list')
+Exo.Controller = require('lib/exo/controller')


Add menu item for soft-wrap

Add menu item for soft-wrap

--- menus/base.cson
+++ menus/base.cson
@@ -62,6 +62,7 @@
         ]
       }
       { type: 'separator' }
+      { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrap' }
     ]
   }


clean linkedin connectors (first step)

clean linkedin connectors (first step)

* Lint most of the code
* Improve comments
* Improve logging
* Improve function names

--- server/konnectors/linkedin.coffee
+++ server/konnectors/linkedin.coffee
@@ -1,17 +1,17 @@
-
 request = require 'request'
 https = require 'https'
 url = require 'url'
 async = require 'async'
 cheerio = require 'cheerio'
+log = require('printit')
+    prefix: "Linkedin"
+    date: true
+
 fetcher = require '../lib/fetcher'
 Contact = require '../models/contact'
 Tag = require '../models/tag'
 ContactHelper = require '../lib/contact_helper'
 CompareContacts = require '../lib/compare_contacts'
-log = require('printit')
-    prefix: "Linkedin"
-    date: true

 ACCOUNT_TYPE = 'com.linkedin'

@@ -33,9 +33,9 @@
         fetcher.new()
             .use(retrieveTokens)
             .use(logIn)
-            .use(retrieveListContact)
+            .use(retrieveContactList)
             .use(prepareCozyContacts)
-            .use(retrieveContacts)
+            .use(saveContacts)
             .args(requiredFields, {}, {})
             .fetch (err, fields, entries) ->
                 return callback err if err
@@ -47,13 +47,15 @@
 # Load landing page to retrieve the csrf token needed in login request.
 # More info on csrf -> https://en.wikipedia.org/wiki/Cross-site_request_forgery
 #
-# The html parsing is done with cheerio, a "jquery like" server side
+# The html parsing is done with cheerio, a "jquery like" that can be run on
+# the server side.
 retrieveTokens = (requiredFields, entries, data, next) ->
     log.info 'Retrieve Tokens'
     opts =
         url: 'https://linkedin.com'
         jar: true

+    log.info 'Retrieving CSRF Token...'
     request.get opts, (err, res, body) ->
         return next err if err

@@ -63,14 +65,13 @@
             $ = cheerio.load body
             entries.csrfToken = $('#loginCsrfParam-login').val()
             entries.accountName = requiredFields.login
-            log.info 'Tokens retrieved'
+            log.info 'CSRF Token retrieved successfully'
             next()

-# Make the login request with the user inputs (login/password) and the csrf
-# token retrieved above.
+# Make the login request with the user inputs (login/password) and the CSRF
+# token retrieved in the previous step.
 logIn = (requiredFields, entries, data, next) ->
-    log.info 'Attempt login'
     opts =
         url: 'https://www.linkedin.com/uas/login-submit'
         jar: true
@@ -80,46 +81,57 @@
             loginCsrfParam: entries.csrfToken
             submit: "Sign+in"

+    log.info 'Signing in...'
     request.post opts, (err, res, body) ->
         return next err if err

         if body is ""
-            log.info 'Login success'
+            log.info 'Login succeeded!'
             next()
         else
-            log.error 'Bad login / password'
-            next new Error("Bad login/Password")
-
-
-# Retrieve a list of all contacts id available in the count. The id will be
-# use to retrieve his personnal data.
-retrieveListContact = (requiredFields, entries, data, next) ->
+            log.error 'Wrong login or password.'
+            next new Error("Wrong login or password.")
+
+
+# Retrieve a list of all Linkedin ID contacts available. The linkedin ID will
+# be used to retrieve additional data about the contact.
+retrieveContactList = (requiredFields, entries, data, next) ->
     log.info 'Retrieve list contact'

-    contacts = "https://www.linkedin.com/contacts/api/contacts/?start=0&count=10000&fields=id"
+    contactsUrl = "https://www.linkedin.com/contacts/api/contacts/"
+    contactsUrl += "?start=0&count=10000&fields=id"
     opts =
-        url: contacts
+        url: contactsUrl
         jar: true
         json: true

+    log.info 'Retrieve contact list...'
     request.get opts, (err, res, body) ->
         return next err if err
+
         if body.status? and body.status is 'error'
-            return next new Error(body.status_details)
-
-        entries.listContacts = body.contacts
-        if not entries.listContacts?
-            next new Error("Error retrieving contacts from request")
+            next new Error body.status_details
         else
-            log.info 'List contact OK'
-            next()
-
-
-# Retrieve a list of all Cozy contacts, find all the contacts linked to the
-# current Linkedin account an put them in a list by id
+            entries.listContacts = body.contacts
+            if not entries.listContacts?
+                next new Error "Error retrieving contacts from request"
+            else
+                log.info 'Contact list retrieved.'
+                next()
+
+
+# Load all Cozy contacts, then perform several operations:
+#
+# * Keep only contacts linked to the current LinkedinAccount
+# * Order them in a map where the LinkedIn account ID is the key
+# * Order them in a map where the contact full name is the key.
+#
+# That way we will be able to check if the contact should be updated (because
+# it already exists) or if it should be created.
+#
 prepareCozyContacts = (requiredFields, entries, data, next) ->
-    log.info 'Prepare Cozy contacts'
-
+
+    log.info 'Load Cozy contacts...'
     Contact.all (err, contacts) ->
         return next err if err

@@ -128,19 +140,19 @@
         for contact in contacts
             entries.cozyContactsByFn[contact.fn] = contact
             account = contact.getAccount ACCOUNT_TYPE, entries.accountName
-            if account?
-                entries.ofAccountByIds[account.id] = contact
+            entries.ofAccountByIds[account.id] = contact if account?
+
+        log.info 'Cozy contacts contacts loaded.'
         next()

 # Create or retrieve a specific to Linkedin, then
-#
 # make a request for each contact retrieved in the previous request
 # (retrieveListContact) with all data needed.
 #
 # In order to reduce the waiting betwen each request an async queue
 # is create. It process the 10 first contacts. (see Async lib)
-retrieveContacts = (requiredFields, entries, data, next) ->
+saveContacts = (requiredFields, entries, data, next) ->

     processRetrievingContactData = (contactId, done) ->
         contacts = """https://www.linkedin.com/contacts/api/contacts/\
@@ -208,6 +220,7 @@
                 saveContact finalContact, entries

+# Extract numbers from given linkedin data structure.
 getPhoneNumber = (data) ->
     listPhones = []

@@ -219,6 +232,7 @@
     listPhones

+# Extract emails from given linkedin data structure.
 getEmails = (data) ->
     listEmails = []

@@ -231,6 +245,7 @@
     listEmails

+# Extract urls from given linkedin data structure.
 getUrls = (data) ->
     listUrls = []

@@ -239,11 +254,13 @@
             name: 'url'
             value: site.url
             type: site.name
+
     data.profiles?.forEach (profile) ->
         listUrls.push
             name: 'url'
             value: profile.url
             type: 'linkedin'
+
     data.twitter?.forEach (twitter) ->
         listUrls.push
             name: 'url'
@@ -253,9 +270,9 @@
     listUrls

-# Currently there isn't an address parser so all the address is set in the
+# Currently there isn't an address parser so all the addresses are set in the
 # locality fields. The Linkedin API allow us to define some fields precisely but
-# that can lead to a duplicat so only the country is specify in the right fields
+# that can lead to a duplicate so only the country is specify in the right fields
 # and we should wait an address parser before use them
 getAddresses = (data) ->
     listAddresses = []
@@ -328,9 +345,12 @@
             log.debug "LContact #{linkContact.n}already synced and uptodate"

     else
-        if entries.cozyContactsByFn[linkContact.fn]?
-            log.info "Link #{cozyContact.fn} to linkedin account"
-            updateContact cozyContact, linkContact
-        else
-            log.info "Create #{linkContact.fn} contact"
-            Contact.create linkContact, endSavePicture
+        if linkContact?
+            if entries.cozyContactsByFn[linkContact.fn]?
+                if cozyContact?
+                    log.info "Link #{cozyContact.fn} to linkedin account"
+                    updateContact cozyContact, linkContact
+            else
+                log.info "Create #{linkContact.fn} contact"
+                Contact.create linkContact, endSavePicture
+


fix for show/hide accepted and pagination [#97186346]

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/'


test dir

test dir

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

--- test/start-server-test.coffee
+++ test/start-server-test.coffee
@@ -0,0 +1,3 @@
+assert    = require "assert"
+request   = require "request"
+


add inline comment/note for mail middleware

 On branch chap-sessions
	modified:   nodejs_server/middleware/sendmail.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/FireworksProject/platform.y.git/'


Add material property in kdocks

Add material property in kdocks

--- views/components/main/parts/kdock-panel.cjsx
+++ views/components/main/parts/kdock-panel.cjsx
@@ -7,18 +7,23 @@
   getInitialState: ->
     docks: [
         name: '未使用'
+        material: []
         countdown: -1
       ,
         name: '未使用'
+        material: []
         countdown: -1
       ,
         name: '未使用'
+        material: []
         countdown: -1
       ,
         name: '未使用'
+        material: []
         countdown: -1
       ,
         name: '未使用'
+        material: []
         countdown: -1
     ]
     notified: []
@@ -34,19 +39,35 @@
             when -1
               docks[id] =
                 name: '未解锁'
+                material: []
                 countdown: -1
             when 0
               docks[id] =
                 name: '未使用'
+                material: []
                 countdown: -1
               notified[id] = false
             when 2
               docks[id] =
                 name: $ships[kdock.api_created_ship_id].api_name
+                material: [
+                  kdock.api_item1
+                  kdock.api_item2
+                  kdock.api_item3
+                  kdock.api_item4
+                  kdock.api_item5
+                ]
                 countdown: Math.floor((kdock.api_complete_time - new Date()) / 1000)
             when 3
               docks[id] =
                 name: $ships[kdock.api_created_ship_id].api_name
+                material: [
+                  kdock.api_item1
+                  kdock.api_item2
+                  kdock.api_item3
+                  kdock.api_item4
+                  kdock.api_item5
+                ]
                 countdown: 0
         @setState
           docks: docks
@@ -58,19 +79,35 @@
             when -1
               docks[id] =
                 name: '未解锁'
+                material: []
                 countdown: -1
             when 0
               docks[id] =
                 name: '未使用'
+                material: []
                 countdown: -1
               notified[id] = false
             when 2
               docks[id] =
                 name: $ships[kdock.api_created_ship_id].api_name
+                material: [
+                  kdock.api_item1
+                  kdock.api_item2
+                  kdock.api_item3
+                  kdock.api_item4
+                  kdock.api_item5
+                ]
                 countdown: Math.floor((kdock.api_complete_time - new Date()) / 1000)
             when 3
               docks[id] =
                 name: $ships[kdock.api_created_ship_id].api_name
+                material: [
+                  kdock.api_item1
+                  kdock.api_item2
+                  kdock.api_item3
+                  kdock.api_item4
+                  kdock.api_item5
+                ]
                 countdown: 0
         @setState
           docks: docks