ComputeController: fetchStackTemplate{,s} with caching on storage

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -955,8 +955,18 @@

   fetchStackTemplate: (id, callback = kd.noop) ->

-    remote.api.JStackTemplate.one { _id: id }, (err, template) ->
+    debug 'fetchStackTemplate called for', id
+
+    if template = @storage.get 'templates', '_id', id
+      debug 'found on cache returning', template
+      return callback null, template
+
+    debug 'not found on cache fetching'
+
+    remote.api.JStackTemplate.one { _id: id }, (err, template) =>
       return callback { message: "Stack template doesn't exist." }  if err or not template
+
+      @storage.push { template }

       # Follow update events to get change set from remote-extensions
       # This is not required but we will need a huge set of changes
@@ -964,6 +974,20 @@
       template.on 'update', kd.noop

       return callback null, template
+
+
+  fetchStackTemplates: (callback) ->
+
+    if (templates = @storage.get 'templates').length
+      callback null, templates
+
+    query   = { group: getGroup().slug }
+    options = { limit: 60 }
+
+    remote.api.JStackTemplate.some query, options, (err, templates) =>
+      return callback err  if err
+      @storage.set 'templates', templates
+      callback null, templates

   showBuildLogs: (machine, tailOffset) ->


Streamlines slightly CS

Streamlines slightly CS

--- caravel/js/caravel.coffee
+++ caravel/js/caravel.coffee
@@ -45,7 +45,7 @@
       e.callback(name, parsedData) if e.name == name

   @getDefault: ->
-    if not Caravel.default?
+    unless Caravel.default?
       Caravel.default = new Caravel("default")
       Caravel.default.post "CaravelInit"
     Caravel.default


Fix: new Lodash Function

Fix: new Lodash 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/BennySamir/Tinkerforge-Home.git/'


Implement a DockerRunner module.

Implement a DockerRunner module.

Implement a docker based compilation runner module, with support for
timeouts and with added isolation and security compared to the
default CommandRunner module

Signed-off-by: Xavier Trochu <6e31b7ccf43b2544cf440401f1df8a297d62b254@edpsciences.org>

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

--- app/coffee/DockerRunner.coffee
+++ app/coffee/DockerRunner.coffee
@@ -0,0 +1,26 @@
+spawn = require("child_process").spawn
+exec  = require("child_process").exec
+logger = require "logger-sharelatex"
+
+module.exports = DockerRunner =
+  _docker: 'docker'
+  _baseCommand: ['run', '--rm=true', '-t', '-v', '$COMPILE_DIR:/source', '--name=texlive-$PROJECT_ID', 'texlive']
+
+  run: (project_id, command, directory, timeout, callback = (error) ->) ->
+    logger.log project_id: project_id, command: command, directory: directory, "running docker command"
+
+    if command[0] != 'latexmk'
+      throw 'Invalid command'
+
+    docker_cmd = (arg.replace('$COMPILE_DIR', directory).replace('$PROJECT_ID', project_id) \
+      for arg in DockerRunner._baseCommand)
+    docker_cmd = docker_cmd.concat (arg.replace('$COMPILE_DIR', '/source') for arg in command.slice(1))
+
+    proc = spawn DockerRunner._docker, docker_cmd, stdio: "inherit", cwd: directory
+    timer = setTimeout timeout, () ->
+      logger.warn "timeout achieved, stopping docker instance"
+      exec 'docker', ['stop', "texlive-#{project_id}"]
+      callback 'Compilation failed, timeout'
+    proc.on "close", () ->
+      clearTimeout timer
+      callback()


Add spreadsheet utils service

Add spreadsheet utils service

error: pathspec 'client/src/indicators/services/GoogleSpreadsheetUtils.coffee' did not match any file(s) known to git

--- client/src/indicators/services/GoogleSpreadsheetUtils.coffee
+++ client/src/indicators/services/GoogleSpreadsheetUtils.coffee
@@ -0,0 +1,78 @@
+angular.module 'Scrumble.indicators'
+.service 'GoogleSpreadsheetUtils', (Sprint) ->
+
+  CLIENT_ID = '947504094757-jahn1uethbjdfp8n8ekk5d43k2dtjjvr.apps.googleusercontent.com'
+  SCOPES = [ 'https://www.googleapis.com/auth/spreadsheets' ]
+
+  ###*
+  # Check if current user has authorized this application.
+  ###
+  checkAuth = ->
+    window.gapi.auth.authorize {
+      'client_id': CLIENT_ID
+      'scope': SCOPES.join(' ')
+      'immediate': true
+    }, handleAuthResult
+    return
+
+  ###*
+  # Handle response from authorization server.
+  #
+  # param {Object} authResult Authorization result.
+  ###
+  handleAuthResult = (authResult) ->
+    if authResult and !authResult.error
+      # Hide auth UI, then load client library.
+      loadSheetsApi()
+    else
+      # Show auth UI, allowing the user to initiate authorization by
+      # clicking authorize button.
+    return
+
+  ###*
+  # Initiate auth flow in response to user clicking authorize button.
+  #
+  ###
+  handleAuthClick = ->
+    window.gapi.auth.authorize {
+      client_id: CLIENT_ID
+      scope: SCOPES
+      immediate: false
+    }, handleAuthResult
+    false
+
+  ###*
+  # Load Sheets API client library.
+  ###
+  loadSheetsApi = ->
+    discoveryUrl = 'https://sheets.googleapis.com/$discovery/rest?version=v4'
+    window.gapi.client.load(discoveryUrl).then processData
+    return
+
+  ###*
+  # Print the names and majors of students in a sample spreadsheet:
+  # https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
+  ###
+  processData = ->
+    window.gapi.client.sheets.spreadsheets.values.update(
+      spreadsheetId: '1qeRBk1TMi9zoaQUz9Zqlasb_w0w2_ehcYk5zApdzefU'
+      range: 'Sheet1!A1:A1'
+      majorDimension: 'ROWS'
+      valueInputOption: 'RAW'
+      values: [['Hello world']]).then ((response) ->
+    ), (response) ->
+      appendPre 'Error: ' + response.result.error.message
+      return
+    return
+
+  ###*
+  # Append a pre element to the body containing the given message
+  # as its text node.
+  #
+  # param {string} message Text to be placed in pre element.
+  ###
+  appendPre = (message) ->
+    console.log(message)
+    return
+
+  handleAuthClick: handleAuthClick


Updated core

Updated core

error: pathspec 'source/micro.core.coffee' did not match any file(s) known to git

--- source/micro.core.coffee
+++ source/micro.core.coffee
@@ -0,0 +1,35 @@
+'use strict'
+
+forEach = Array::forEach
+push    = Array::push
+slice   = Array::slice
+
+u = (selector) ->
+  if !(this instanceof u)
+    return new u(selector)
+
+  if !selector
+    return this
+
+  if selector instanceof u
+    return selector
+
+  if typeof selector is 'string'
+    return push.apply this, slice.call(document.querySelectorAll(selector))
+
+  if typeof selector is 'function'
+    u(document).ready selector
+
+u:: =
+  length: 0
+
+u.VERSION = '0.0.1'
+
+if typeof module isnt 'undefined'
+  if module.exports
+    exports = module.exports = u
+  exports.u = u
+
+window.u = u if typeof window isnt 'undefined'
+
+module.exports = u


found a better idiom to deal with 404s

found a better idiom to deal with 404s

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


imageoptim works, remove comments and add db dump

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/jmartsch/generator-fixate-pw.git/'


migration script for dochistory packing

migration script for dochistory packing

error: pathspec 'server-ce/migrations/3_pack_docHistory_collection.coffee' did not match any file(s) known to git

--- server-ce/migrations/3_pack_docHistory_collection.coffee
+++ server-ce/migrations/3_pack_docHistory_collection.coffee
@@ -0,0 +1,291 @@
+Settings = require "settings-sharelatex"
+fs = require("fs")
+mongojs = require("mongojs")
+ObjectId = mongojs.ObjectId
+db = mongojs(Settings.mongo.url, ['docs','docHistory', 'docHistoryStats'])
+_ = require("lodash")
+async = require("async")
+exec = require("child_process").exec
+BSON = db.bson.BSON
+
+logger = {
+	log: ->
+	err: ->
+}
+
+finished_docs_path = "/tmp/finished-docs-3"
+all_docs_path = "/tmp/all-docs-3"
+unmigrated_docs_path = "/tmp/unmigrated-docs-3"
+
+finished_docs = {}
+if fs.existsSync(finished_docs_path)
+	for id in fs.readFileSync(finished_docs_path,'utf-8').split("\n")
+		finished_docs[id] = true
+
+getAndWriteDocids = (callback)->
+	console.log "finding all doc id's - #{new Date().toString()}"
+	db.docs.find {}, {_id:1}, (err, ids)->
+		console.log "total found docs in mongo #{ids.length} - #{new Date().toString()}"
+		ids = _.pluck ids, '_id'
+		ids = _.filter ids, (id)-> id?
+		fileData = ids.join("\n")
+		fs.writeFileSync all_docs_path + ".tmp", fileData
+		fs.renameSync all_docs_path + ".tmp", all_docs_path
+		callback(err, ids)
+
+loadDocIds = (callback)->
+	console.log "loading doc ids from #{all_docs_path}"
+	data = fs.readFileSync all_docs_path, "utf-8"
+	ids = data.split("\n")
+	console.log "loaded #{ids.length} doc ids from #{all_docs_path}"
+	callback null, ids
+
+getDocIds = (callback)->
+	exists = fs.existsSync all_docs_path
+	if exists
+		loadDocIds callback
+	else
+		getAndWriteDocids callback
+
+markDocAsProcessed = (doc_id, callback)->
+	finished_docs[doc_id] = true
+	fs.appendFile finished_docs_path, "#{doc_id}\n", callback
+
+markDocAsUnmigrated = (doc_id, callback)->
+	console.log "#{doc_id} unmigrated"
+	markDocAsProcessed doc_id, (err)->
+		fs.appendFile unmigrated_docs_path, "#{doc_id}\n", callback
+
+printProgress = ->
+	count = Object.keys(finished_docs).length
+	console.log "completed", count
+
+checkIfDocHasBeenProccessed = (doc_id, callback)->
+	callback(null, finished_docs[doc_id])
+
+processNext = (doc_id, callback)->
+	if !doc_id? or doc_id.length == 0
+		return callback()
+	checkIfDocHasBeenProccessed doc_id, (err, hasBeenProcessed)->
+		if hasBeenProcessed
+			console.log "#{doc_id} already processed, skipping"
+			return callback()
+		console.log "#{doc_id} processing"
+		PackManager._packDocHistory doc_id, {}, (err) ->
+			markDocAsProcessed doc_id, callback
+
+exports.migrate = (client, done = ->)->
+	getDocIds (err, ids)->
+		interval = setInterval printProgress, 3*1000
+		jobs = _.map ids, (id)->
+			return (cb)->
+				processNext(id, cb)
+		async.series jobs, (err)->
+			if err?
+				console.error err, "at end of jobs"
+			else
+				console.log "finished"
+			clearInterval interval
+			done(err)
+
+exports.rollback = (client, done)->
+	done()
+
+DAYS = 24 * 3600 * 1000 # one day in milliseconds
+
+# copied from track-changes/app/coffee/PackManager.coffee
+
+PackManager =
+	MAX_SIZE:  1024*1024 # make these configurable parameters
+	MAX_COUNT: 512
+
+	convertDocsToPacks: (docs, callback) ->
+		packs = []
+		top = null
+		docs.forEach (d,i) ->
+			# skip existing packs
+			if d.pack?
+				top = null
+				return
+			sz = BSON.calculateObjectSize(d)
+			# decide if this doc can be added to the current pack
+			validLength = top? && (top.pack.length < PackManager.MAX_COUNT)
+			validSize = top? && (top.sz + sz < PackManager.MAX_SIZE)
+			bothPermanent = top? && (top.expiresAt? is false) && (d.expiresAt? is false)
+			bothTemporary = top? && (top.expiresAt? is true) && (d.expiresAt? is true)
+			within1Day = bothTemporary && (d.meta.start_ts - top.meta.start_ts < 24 * 3600 * 1000)
+			if top? && validLength && validSize && (bothPermanent || (bothTemporary && within1Day))
+				top.pack = top.pack.concat {v: d.v, meta: d.meta,  op: d.op, _id: d._id}
+				top.sz += sz
+				top.n += 1
+				top.v_end = d.v
+				top.meta.end_ts = d.meta.end_ts
+				top.expiresAt = d.expiresAt if top.expiresAt?
+				return
+			else
+				# create a new pack
+				top = _.clone(d)
+				top.pack = [ {v: d.v, meta: d.meta,  op: d.op, _id: d._id} ]
+				top.meta = { start_ts: d.meta.start_ts, end_ts: d.meta.end_ts }
+				top.sz = sz
+				top.n = 1
+				top.v_end = d.v
+				delete top.op
+				delete top._id
+				packs.push top
+
+		callback(null, packs)
+
+	checkHistory: (docs, callback) ->
+		errors = []
+		prev = null
+		error = (args...) ->
+			errors.push args
+		docs.forEach (d,i) ->
+			if d.pack?
+				n = d.pack.length
+				last = d.pack[n-1]
+				error('bad pack v_end', d) if d.v_end != last.v
+				error('bad pack start_ts', d) if d.meta.start_ts != d.pack[0].meta.start_ts
+				error('bad pack end_ts', d) if d.meta.end_ts != last.meta.end_ts
+				d.pack.forEach (p, i) ->
+					prev = v
+					v = p.v
+					error('bad version', v, 'in', p) if v <= prev
+					#error('expired op', p, 'in pack') if p.expiresAt?
+			else
+				prev = v
+				v = d.v
+				error('bad version', v, 'in', d) if v <= prev
+		if errors.length
+			callback(errors)
+		else
+			callback()
+
+	insertPack: (packObj, callback) ->
+		bulk = db.docHistory.initializeOrderedBulkOp()
+		doc_id = packObj.doc_id
+		expect_nInserted = 1
+		expect_nRemoved = packObj.pack.length
+		logger.log {doc_id: doc_id}, "adding pack, removing #{expect_nRemoved} ops"
+		bulk.insert packObj
+		ids = (op._id for op in packObj.pack)
+		bulk.find({_id:{$in:ids}}).remove()
+		bulk.execute (err, result) ->
+			if err?
+				logger.error {doc_id: doc_id}, "error adding pack"
+				callback(err, result)
+			else if result.nInserted != expect_nInserted or result.nRemoved != expect_nRemoved
+				logger.error {doc_id: doc_id, result}, "unexpected result adding pack"
+				callback(new Error(
+					msg: 'unexpected result'
+					expected: {expect_nInserted, expect_nRemoved}
+				), result)
+			else
+				db.docHistoryStats.update {doc_id:doc_id}, {
+					$inc:{update_count:-expect_nRemoved},
+					$currentDate:{last_packed:true}
+				}, {upsert:true}, () ->
+					callback(err, result)
+
+	# retrieve document ops/packs and check them
+	getDocHistory: (doc_id, callback) ->
+		db.docHistory.find({doc_id:ObjectId(doc_id)}).sort {v:1}, (err, docs) ->
+			return callback(err) if err?
+			# for safety, do a consistency check of the history
+			logger.log {doc_id}, "checking history for document"
+			PackManager.checkHistory docs, (err) ->
+				return callback(err) if err?
+				callback(err, docs)
+				#PackManager.deleteExpiredPackOps docs, (err) ->
+				#	return callback(err) if err?
+				#	callback err, docs
+
+	packDocHistory: (doc_id, options, callback) ->
+		if typeof callback == "undefined" and typeof options == 'function'
+			callback = options
+			options = {}
+		LockManager.runWithLock(
+			"HistoryLock:#{doc_id}",
+			(releaseLock) ->
+				PackManager._packDocHistory(doc_id, options, releaseLock)
+			,	callback
+		)
+
+	_packDocHistory: (doc_id, options, callback) ->
+		logger.log {doc_id},"starting pack operation for document history"
+
+		PackManager.getDocHistory doc_id, (err, docs) ->
+			return callback(err) if err?
+			origDocs = 0
+			origPacks = 0
+			for d in docs
+				if d.pack? then	origPacks++	else origDocs++
+			PackManager.convertDocsToPacks docs, (err, packs) ->
+				return callback(err) if err?
+				total = 0
+				for p in packs
+					total = total + p.pack.length
+				logger.log {doc_id, origDocs, origPacks, newPacks: packs.length, totalOps: total}, "document stats"
+				if packs.length
+					if options['dry-run']
+						logger.log {doc_id}, 'dry-run, skipping write packs'
+						return callback()
+					PackManager.savePacks packs, (err) ->
+						return callback(err) if err?
+						# check the history again
+						PackManager.getDocHistory doc_id, callback
+				else
+					logger.log {doc_id}, "no packs to write"
+					# keep a record that we checked this one to avoid rechecking it
+					db.docHistoryStats.update {doc_id:doc_id}, {
+						$currentDate:{last_checked:true}
+					}, {upsert:true}, () ->
+						callback null, null
+
+	DB_WRITE_DELAY: 100
+
+	savePacks: (packs, callback) ->
+		async.eachSeries packs, PackManager.safeInsert, (err, result) ->
+			if err?
+				logger.log {err, result}, "error writing packs"
+				callback err, result
+			else
+				callback()
+
+	safeInsert: (packObj, callback) ->
+		PackManager.insertPack packObj, (err, result) ->
+			setTimeout () ->
+				callback(err,result)
+			, PackManager.DB_WRITE_DELAY
+
+	deleteExpiredPackOps: (docs, callback) ->
+		now = Date.now()
+		toRemove = []
+		toUpdate = []
+		docs.forEach (d,i) ->
+			if d.pack?
+				newPack = d.pack.filter (op) ->
+					if op.expiresAt? then op.expiresAt > now else true
+				if newPack.length == 0
+					toRemove.push d
+				else if newPack.length < d.pack.length
+					# adjust the pack properties
+					d.pack = newPack
+					first = d.pack[0]
+					last = d.pack[d.pack.length - 1]
+					d.v_end = last.v
+					d.meta.start_ts = first.meta.start_ts
+					d.meta.end_ts = last.meta.end_ts
+					toUpdate.push d
+		if toRemove.length or toUpdate.length
+			bulk = db.docHistory.initializeOrderedBulkOp()
+			toRemove.forEach (pack) ->
+				console.log "would remove", pack
+				#bulk.find({_id:pack._id}).removeOne()
+			toUpdate.forEach (pack) ->
+				console.log "would update", pack
+				#bulk.find({_id:pack._id}).updateOne(pack);
+			bulk.execute callback
+		else
+			callback()


Added timestamp checking to live view

Added timestamp checking to live view

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


Fail silently if one of the required fields could not be found

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


空client

空client

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


fix a bug that `pasteFromClipboard` does not return text from clipboard

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -217,7 +217,7 @@
 # We return null to avoid the return value from the copy operations being passed to sendResponse.
 #
 copyToClipboard = (request) -> Clipboard.copy(request.data); null
-pasteFromClipboard = (request) -> Clipboard.paste(); null
+pasteFromClipboard = (request) -> Clipboard.paste()

 #
 # Selects the tab with the ID specified in request.id


Remove ad_manager_spec temporarily

Remove ad_manager_spec temporarily

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


chore (Model) fix and unskip integration test case for passing in streams as options

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


specs for #889 #884

specs for #889 #884

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

--- test/unit/services/leafletIteratorsSpec.coffee
+++ test/unit/services/leafletIteratorsSpec.coffee
@@ -0,0 +1,27 @@
+describe 'leafletIterators', ->
+
+  beforeEach ->
+      module('leaflet-directive')
+      inject (_$compile_, _$rootScope_, _leafletData_, _leafletIterators_) ->
+          @$compile = _$compile_
+          @$rootScope = _$rootScope_
+          @leafletData = _leafletData_
+          @subject = _leafletIterators_
+
+  it 'exists', ->
+      expect(@subject).toBeDefined()
+
+  describe 'forEach/each', ->
+      it 'prototypes should not be called', ->
+        class Dummy
+          prop1: 'prop1'
+          prop2: 'prop2'
+        d = new Dummy()
+        d.prop3 = 'prop3'
+
+        vals = []
+        @subject.each d, (val) ->
+          vals.push val
+
+        expect(vals.length).toBe 1
+        expect(vals[0]).toBe d.prop3


fixes the description test

fixes the description test


Make `activateModeWithQueue` support link hint mode modifiers

--- content_scripts/link_hints.coffee
+++ content_scripts/link_hints.coffee
@@ -254,6 +254,7 @@

     if ((event.keyCode == keyCodes.shiftKey or event.keyCode == keyCodes.ctrlKey) and
         (@mode == OPEN_IN_CURRENT_TAB or
+         @mode == OPEN_WITH_QUEUE or
          @mode == OPEN_IN_NEW_BG_TAB or
          @mode == OPEN_IN_NEW_FG_TAB))
       # Toggle whether to open link in a new or current tab.


Add google script

Add google script

Feeglebot was running in a London DC, so it required the UK Google
link. Last I knew, Octobot was in the US so I've updated it to use
the main .com instead - if there are issues with redirects, change
the search URL to the correct country.

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

--- scripts/google.coffee
+++ scripts/google.coffee
@@ -0,0 +1,25 @@
+# Description:
+#   Returns the URL of the first google hit for a query
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   None
+#
+# Commands:
+#   hubot google me <query> - Googles <query> & returns 1st result's URL
+#
+# Author:
+#   searls
+
+module.exports = (robot) ->
+  robot.respond /(google)( me)? (.*)/i, (msg) ->
+    googleMe msg, msg.match[3], (url) ->
+      msg.send msg.message.user.name + ": Here you go! " + url
+
+googleMe = (msg, query, cb) ->
+  msg.http('http://www.google.com/search')
+    .query({q: query})
+    .get() (err, res, body) ->
+      cb body.match(/class="r"><a href="\/url\?q=([^"]*)(&sa.*)">/)?[1] || "Sorry, Google had zero results for '#{query}'"


seo: return socialapidata from scriptblock

--- workers/social/lib/social/render/scriptblock.coffee
+++ workers/social/lib/social/render/scriptblock.coffee
@@ -116,4 +116,4 @@
         queue.fin()
   ]

-  dash queue, -> callback null, createHTML()
+  dash queue, -> callback null, createHTML(), socialapidata


added validate handler test file

added validate handler test 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/andrewjcasal/koding.git/'


pricing: define "payment plan subscription" relationship in `JGroup`

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -210,6 +210,8 @@
         linkPaymentMethod:
           (signature String, Function)
         unlinkPaymentMethod:
+          (signature String, Function)
+        addSubscription:
           (signature String, Function)
     schema          :
       title         :
@@ -300,6 +302,9 @@
       plan          :
         targetType  : 'JPaymentPlan'
         as          : 'group plan'
+      subscription  :
+        targetType  : 'JPaymentSubscription'
+        as          : 'payment plan subscription'

   constructor:->
     super
@@ -1420,3 +1425,9 @@
         @fetchPacks {}, options, callback
       when 'plan'
         @fetchPlans {}, options, callback
+
+  addSubscription$: permit 'edit own groups',
+    success: (client, id, callback) ->
+      JPaymentSubscription = require '../payment/subscription'
+      JPaymentSubscription.one _id: id, (err, subscription) =>
+        @addSubscription subscription, callback


testing add_nodes

testing add_nodes

--- src/main/webapp/app/coffeescripts/views/MapMarkerView.coffee
+++ src/main/webapp/app/coffeescripts/views/MapMarkerView.coffee
@@ -21,8 +21,6 @@

   render: ->
     @marker.setMap($a.map)
-    console.log @marker
-    $a.testM = @marker
     @

   # Draw the marker by determining the type of icon


Reorganize WorkspaceView into sections

Reorganize WorkspaceView into sections

--- src/workspace-view.coffee
+++ src/workspace-view.coffee
@@ -162,10 +162,171 @@
     @command 'core:save', => @saveActivePaneItem()
     @command 'core:save-as', => @saveActivePaneItemAs()

+  ###
+  Section: Accessing the Workspace Model
+  ###
+
   # Public: Get the underlying model object.
   #
   # Returns a {Workspace}.
   getModel: -> @model
+
+  ###
+  Section: Accessing Views
+  ###
+
+  # Public: Register a function to be called for every current and future
+  # editor view in the workspace (only includes {EditorView}s that are pane
+  # items).
+  #
+  # * `callback` A {Function} with an {EditorView} as its only argument.
+  #   * `editorView` {EditorView}
+  #
+  # Returns a subscription object with an `.off` method that you can call to
+  # unregister the callback.
+  eachEditorView: (callback) ->
+    callback(editorView) for editorView in @getEditorViews()
+    attachedCallback = (e, editorView) ->
+      callback(editorView) unless editorView.mini
+    @on('editor:attached', attachedCallback)
+    off: => @off('editor:attached', attachedCallback)
+
+  # Public: Register a function to be called for every current and future
+  # pane view in the workspace.
+  #
+  # * `callback` A {Function} with a {PaneView} as its only argument.
+  #   * `paneView` {PaneView}
+  #
+  # Returns a subscription object with an `.off` method that you can call to
+  # unregister the callback.
+  eachPaneView: (callback) ->
+    @panes.eachPaneView(callback)
+
+  # Public: Get all existing pane views.
+  #
+  # Prefer {Workspace::getPanes} if you don't need access to the view objects.
+  # Also consider using {::eachPaneView} if you want to register a callback for
+  # all current and *future* pane views.
+  #
+  # Returns an Array of all open {PaneView}s.
+  getPaneViews: ->
+    @panes.getPaneViews()
+
+  # Public: Get the active pane view.
+  #
+  # Prefer {Workspace::getActivePane} if you don't actually need access to the
+  # view.
+  #
+  # Returns a {PaneView}.
+  getActivePaneView: ->
+    @panes.getActivePaneView()
+
+  # Public: Get the view associated with the active pane item.
+  #
+  # Returns a view.
+  getActiveView: ->
+    @panes.getActiveView()
+
+  ###
+  Section: Adding elements to the workspace
+  ###
+
+  # Public: Prepend an element or view to the panels at the top of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  prependToTop: (element) ->
+    @vertical.prepend(element)
+
+  # Public: Append an element or view to the panels at the top of the workspace.
+  #
+  # * `element` jQuery object or DOM element
+  appendToTop: (element) ->
+    @panes.before(element)
+
+  # Public: Prepend an element or view to the panels at the bottom of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  prependToBottom: (element) ->
+    @panes.after(element)
+
+  # Public: Append an element or view to the panels at the bottom of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  appendToBottom: (element) ->
+    @vertical.append(element)
+
+  # Public: Prepend an element or view to the panels at the left of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  prependToLeft: (element) ->
+    @horizontal.prepend(element)
+
+  # Public: Append an element or view to the panels at the left of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  appendToLeft: (element) ->
+    @vertical.before(element)
+
+  # Public: Prepend an element or view to the panels at the right of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  prependToRight: (element) ->
+    @vertical.after(element)
+
+  # Public: Append an element or view to the panels at the right of the
+  # workspace.
+  #
+  # * `element` jQuery object or DOM element
+  appendToRight: (element) ->
+    @horizontal.append(element)
+
+  ###
+  Section: Focusing pane views
+  ###
+
+  # Focus the previous pane by id.
+  focusPreviousPaneView: -> @model.activatePreviousPane()
+
+  # Focus the next pane by id.
+  focusNextPaneView: -> @model.activateNextPane()
+
+  # Public: Focus the pane directly above the active pane.
+  focusPaneViewAbove: -> @panes.focusPaneViewAbove()
+
+  # Public: Focus the pane directly below the active pane.
+  focusPaneViewBelow: -> @panes.focusPaneViewBelow()
+
+  # Public: Focus the pane directly to the left of the active pane.
+  focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft()
+
+  # Public: Focus the pane directly to the right of the active pane.
+  focusPaneViewOnRight: -> @panes.focusPaneViewOnRight()
+
+  ###
+  Section: Private
+  ###
+
+  afterAttach: (onDom) ->
+    @focus() if onDom
+
+  # Called by SpacePen
+  beforeRemove: ->
+    @model.destroy()
+
+  setEditorFontSize: (fontSize) ->
+    atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
+
+  setEditorFontFamily: (fontFamily) ->
+    atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
+
+  setEditorLineHeight: (lineHeight) ->
+    atom.themes.updateGlobalEditorStyle('line-height', lineHeight)

   # Install the Atom shell commands on the user's system.
   installShellCommands: ->
@@ -202,9 +363,6 @@
         $(document.body).focus()
         true

-  afterAttach: (onDom) ->
-    @focus() if onDom
-
   # Prompts to save all unsaved items
   confirmClose: ->
     @panes.confirmClose()
@@ -243,143 +401,10 @@
     for editorElement in @panes.element.querySelectorAll('.pane > .item-views > .editor')
       $(editorElement).view()

-  # Public: Prepend an element or view to the panels at the top of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  prependToTop: (element) ->
-    @vertical.prepend(element)
-
-  # Public: Append an element or view to the panels at the top of the workspace.
-  #
-  # * `element` jQuery object or DOM element
-  appendToTop: (element) ->
-    @panes.before(element)
-
-  # Public: Prepend an element or view to the panels at the bottom of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  prependToBottom: (element) ->
-    @panes.after(element)
-
-  # Public: Append an element or view to the panels at the bottom of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  appendToBottom: (element) ->
-    @vertical.append(element)
-
-  # Public: Prepend an element or view to the panels at the left of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  prependToLeft: (element) ->
-    @horizontal.prepend(element)
-
-  # Public: Append an element or view to the panels at the left of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  appendToLeft: (element) ->
-    @vertical.before(element)
-
-  # Public: Prepend an element or view to the panels at the right of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  prependToRight: (element) ->
-    @vertical.after(element)
-
-  # Public: Append an element or view to the panels at the right of the
-  # workspace.
-  #
-  # * `element` jQuery object or DOM element
-  appendToRight: (element) ->
-    @horizontal.append(element)
-
-  # Public: Get the active pane view.
-  #
-  # Prefer {Workspace::getActivePane} if you don't actually need access to the
-  # view.
-  #
-  # Returns a {PaneView}.
-  getActivePaneView: ->
-    @panes.getActivePaneView()
-
-  # Public: Get the view associated with the active pane item.
-  #
-  # Returns a view.
-  getActiveView: ->
-    @panes.getActiveView()
-
-  # Focus the previous pane by id.
-  focusPreviousPaneView: -> @model.activatePreviousPane()
-
-  # Focus the next pane by id.
-  focusNextPaneView: -> @model.activateNextPane()
-
-  # Public: Focus the pane directly above the active pane.
-  focusPaneViewAbove: -> @panes.focusPaneViewAbove()
-
-  # Public: Focus the pane directly below the active pane.
-  focusPaneViewBelow: -> @panes.focusPaneViewBelow()
-
-  # Public: Focus the pane directly to the left of the active pane.
-  focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft()
-
-  # Public: Focus the pane directly to the right of the active pane.
-  focusPaneViewOnRight: -> @panes.focusPaneViewOnRight()
-
-  # Public: Register a function to be called for every current and future
-  # pane view in the workspace.
-  #
-  # * `callback` A {Function} with a {PaneView} as its only argument.
-  #   * `paneView` {PaneView}
-  #
-  # Returns a subscription object with an `.off` method that you can call to
-  # unregister the callback.
-  eachPaneView: (callback) ->
-    @panes.eachPaneView(callback)
-
-  # Public: Get all existing pane views.
-  #
-  # Prefer {Workspace::getPanes} if you don't need access to the view objects.
-  # Also consider using {::eachPaneView} if you want to register a callback for
-  # all current and *future* pane views.
-  #
-  # Returns an Array of all open {PaneView}s.
-  getPaneViews: ->
-    @panes.getPaneViews()
-
-  # Public: Register a function to be called for every current and future
-  # editor view in the workspace (only includes {EditorView}s that are pane
-  # items).
-  #
-  # * `callback` A {Function} with an {EditorView} as its only argument.
-  #   * `editorView` {EditorView}
-  #
-  # Returns a subscription object with an `.off` method that you can call to
-  # unregister the callback.
-  eachEditorView: (callback) ->
-    callback(editorView) for editorView in @getEditorViews()
-    attachedCallback = (e, editorView) ->
-      callback(editorView) unless editorView.mini
-    @on('editor:attached', attachedCallback)
-    off: => @off('editor:attached', attachedCallback)
-
-  # Called by SpacePen
-  beforeRemove: ->
-    @model.destroy()
-
-  setEditorFontSize: (fontSize) ->
-    atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
-
-  setEditorFontFamily: (fontFamily) ->
-    atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
-
-  setEditorLineHeight: (lineHeight) ->
-    atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
+
+  ###
+  Section: Deprecated
+  ###

   # Deprecated
   eachPane: (callback) ->


Added method to enable/disable selection.

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


Remove Module::docsPath (unused)

Remove Module::docsPath (unused)

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


Filter incidents by division

Filter incidents by division

Closes #38.

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

--- app/assets/javascripts/incidents/filter.coffee
+++ app/assets/javascripts/incidents/filter.coffee
@@ -0,0 +1,12 @@
+filterDivisions = () ->
+  $(this).siblings('button').removeClass 'btn-primary'
+  $(this).addClass 'btn-primary'
+  division = $(this).text()
+  $('table.incidents tbody tr').show()
+  if division != 'All'
+    $('table.incidents tbody tr').filter () ->
+      $(this).data('division') != division
+    .hide()
+
+$(document).ready ->
+  $('.division-filter').on 'click', 'button', filterDivisions


Don't focus atom-spec.coffee

Don't focus atom-spec.coffee

--- spec/atom-spec.coffee
+++ spec/atom-spec.coffee
@@ -3,7 +3,7 @@
 path = require 'path'
 ThemeManager = require '../src/theme-manager'

-fdescribe "the `atom` global", ->
+describe "the `atom` global", ->
   beforeEach ->
     window.rootView = new RootView


added trigger bbcode function

added trigger bbcode 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/herrkris/bbphone-app.git/'


email config

email config

error: pathspec 'both/config/emails.coffee' did not match any file(s) known to git

--- both/config/emails.coffee
+++ both/config/emails.coffee
@@ -0,0 +1,10 @@
+if Meteor.isServer
+	PrettyEmail.options =
+		facebook: 'http://facebook.com/onthecode'
+		twitter: 'http://twitter.com/BenPeterJones'
+		website: 'http://benjaminpeterjones.com'
+
+		siteName: 'Meteor Starter'
+		companyAddress: 'Jessnerstrasse 18, 12047 Berlin'
+		companyName: 'Code to Create'
+		companyUrl: 'http://code2create.com'


config: remove nginx location from webserver


Set `config` defaults in its constructor

--- src/app/config.coffee
+++ src/app/config.coffee
@@ -15,10 +15,13 @@
   configDirPath: configDirPath
   settings: null

+  constructor: ->
+    @settings = {}
+    @setDefaults "core", require('root-view').configDefaults
+    @setDefaults "editor", require('editor').configDefaults
+
   load: ->
-    @settings = {}
     @loadUserConfig()
-    @assignDefaults()
     @loadPackages(@getAvailableTextMateBundles())
     @loadPackages(@getAvailableAtomPackages())
     @requireUserInitScript()


Correct once() method of scoped event specifiers.

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/JoshuaToenyes/stout-core.git/'


Restart interval of main window should be longer than specs window.

--- src/app/window.coffee
+++ src/app/window.coffee
@@ -157,7 +157,9 @@
   timesReloaded = process.global.timesReloaded ? 0
   ++timesReloaded

-  if timesReloaded > 3
+  restartValue = if window.location.search.indexOf('spec-bootstrap') == -1 then 10 else 3
+
+  if timesReloaded > restartValue
     atom.restartRendererProcess()
   else
     $native.reload()


update to latest version of oauth-io addon api

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


Enabled query filter

Enabled query filter

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-ex-google-bigquery.git/'


activity: show container while not showing list itself

--- client/activity/lib/components/chatpane/index.coffee
+++ client/activity/lib/components/chatpane/index.coffee
@@ -32,25 +32,25 @@

     return null  unless @props.messages?.size

-

-      <Scroller
-        onTopThresholdReached={@bound 'onTopThresholdReached'}
-        ref="scrollContainer">
-        <ChatList
-          isMessagesLoading={@props.thread?.getIn ['flags', 'isMessagesLoading']}
-          messages={@props.messages}
-          showItemMenu={@props.showItemMenu}
-          channelName={@props.thread.getIn ['channel', 'name']}
-        />
-      </Scroller>
-

+    <Scroller
+      onTopThresholdReached={@bound 'onTopThresholdReached'}
+      ref="scrollContainer">
+      <ChatList
+        isMessagesLoading={@props.thread?.getIn ['flags', 'isMessagesLoading']}
+        messages={@props.messages}
+        showItemMenu={@props.showItemMenu}
+        channelName={@props.thread.getIn ['channel', 'name']}
+      />
+    </Scroller>

   render: ->

-        {@renderBody()}
-        {@props.children}
+

+          {@renderBody()}
+          {@props.children}
+


export mocks as a module

export mocks as a module

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

--- test/server/mocks/index.coffee
+++ test/server/mocks/index.coffee
@@ -0,0 +1,3 @@
+module.exports =
+  crudModel: require './crud'
+  crudControllerFactory: require './crudControllerFactory'


minor comment update

minor comment update

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


Initial.

Initial.

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


Update es-419.coffee

Update es-419.coffee

--- app/locale/es-419.coffee
+++ app/locale/es-419.coffee
@@ -322,7 +322,7 @@
     tip_lines_of_code: "Medir el progreso en la programación en líneas de código es como medir el progreso de construcción de una aeronave por su peso. — Bill Gates"
     tip_source_code: "Quisiera cambiar el mundo, pero no me dan el código fuente."
     tip_javascript_java: "Java es a Javascript lo mismo que Comer es a Comercial. - Chris Heilmann"
-#    tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr."
+    tip_move_forward: "Hagas lo que hagas, siempre sigue hacia delante. - Martin Luther King Jr."

   game_menu:
     inventory_tab: "Inventario"
@@ -504,45 +504,45 @@
     matt_title: "Programador"
     matt_blurb: "Bicicletero"

-#  teachers:
-#    title: "CodeCombat for Teachers"
-#    preparation_title: "Preparation"
-#    preparation_1: "CodeCombat is free to play for the core level progression and does not require students to sign up. We encourage teachers to"
-#    preparation_play_campaign: "play through the campaign"
-#    preparation_2: "to try it out, but the only thing you absolutely need to do to be ready is ensure students have access to a computer."
-#    preparation_3: "It is not necessary for teachers to be comfortable with computer science concepts for students to have fun learning with CodeCombat."
-#    violent_title: "Is it violent?"
-#    violent_1: "We get this from teachers a lot due to our name. Although CodeCombat does contain cartoon violence, there is nothing graphic in either the visuals or language."
-#    violent_2: "If you are comfortable having your students play Angry Birds, you will be comfortable with CodeCombat."
-#    for_girls_title: "Is it for girls?"
-#    for_girls_1: "There are three game modes in CodeCombat: building, puzzles, and combat. We have intentionally designed each to appeal to both boys and girls and think that the building and puzzle levels especially differentiate the game from violent triple A titles that repel female players."
-#    what_cover_title: "What do we cover?"
-#    what_cover_1: "There are 20 levels in the Hour of Code tutorial that teach and reinforce 6 specific computer science concepts:"
-#    what_cover_notation_1: "Formal notation"
-#    what_cover_notation_2: "- builds an understanding of the importance of syntax in programming."
-#    what_cover_methods_1: "Calling methods"
-#    what_cover_methods_2: "- familiarizes students with the syntax of object-oriented method calls."
-#    what_cover_parameters_1: "Parameters"
-#    what_cover_parameters_2: "- trains how to pass parameters to functions."
-#    what_cover_strings_1: "Strings"
-#    what_cover_strings_2: "- teaches students about string notation and passing strings as parameters."
-#    what_cover_loops_1: "Loops"
-#    what_cover_loops_2: "- develops the abstraction of designing short programs with loops."
-#    what_cover_variables_1: "Variables"
-#    what_cover_variables_2: "- adds the skill of referencing values that change over time."
-#    what_cover_2: "Students may continue past level 20, depending on their speed and interest, to learn two additional concepts in later levels:"
-#    what_cover_logic_1: "Conditional logic"
-#    what_cover_logic_2: "- when and how to use if/else to control in-game outcomes."
-#    what_cover_input_1: "Handling player input"
-#    what_cover_input_2: "- responding to input events to create a user interface."
-#    sys_requirements_title: "System Requirements"
-#    sys_requirements_1: "Because CodeCombat is a game, it is more intensive for computers to run smoothly than video or written tutorials. We have optimized it to run quickly on all modern browsers and on older machines so that everyone can play. That said, here are our suggestions for getting the most out of your Hour of Code experience:"
-#    sys_requirements_2: "Use newer versions of Chrome or Firefox."
-#    sys_requirements_3: "Although CodeCombat will work on browsers as old as IE9, the performance is not as good. Chrome is best."
-#    sys_requirements_4: "Use newer computers."
-#    sys_requirements_5: "Older computers, Chromebooks, and netbooks tend to have very few system resources, which makes for a less enjoyable experience. At least 2GB of RAM is required."
-#    sys_requirements_6: "Allow players to wear headphones/earbuds to hear the audio."
-#    sys_requirements_7: "We help players learn through voiceover and sound effects, which will make classrooms noisy and distracting."
+teachers:
+    title: "CodeCombat para Profesores"
+    preparation_title: "Preparación"
+    preparation_1: "CodeCombat es gratuito para jugar en la progresión de nivel básico y no requiere el registro de los usuarios. Alentamos a los profesores a"
+    preparation_play_campaign: "jugar a través de la campaña"
+    preparation_2: "para probarlo, la única cosa que necesitas para estar listo es asegurarte que los estudiantes tengan acceso a una computadora con internet."
+    preparation_3: "No es necesario que los maestros se sienten cómodos con los conceptos informáticos para que los estudiantes se divierten aprendiendo con CodeCombat."
+    violent_title: "¿Es violento?"
+    violent_1: "Nos preguntan esto debido a nuestro nombre. Sin embargo CodeCombat solo contiene violencia de dibujos animados, no hay nada gráfico en las imágenes o el lenguaje."
+    violent_2: "Si te sientes cómodo cuanto tus estudiantes juegan Angry Bird, entonces estaras cómodo con CodeCombat."
+    for_girls_title: "¿Es para chicas?"
+    for_girls_1: "Existen tres modos de juego en CodeCombat: Edificación, rompecabezas, y combate. Hemos diseñado intencionalmente cada uno para atraer tanto a los niños como a las niñas, y creemos en que los niveles de construcción y rompecabezas diferencia el juego de los títulos triple A ultra violentos que repelen a las jugadoras."
+    what_cover_title: "¿Qué es lo que cubrimos?"
+    what_cover_1: "Hay 20 niveles en nuestro tutorial Hora del Código que enseña y refuerza 6 conceptos especifico de las ciencias computacionales:"
+    what_cover_notation_1: "Notación Formal"
+    what_cover_notation_2: "- construye una comprensión de la importancia de la sintaxis en la programación."
+    what_cover_methods_1: "Metodos de llamada"
+    what_cover_methods_2: "- familiariza a los estudiantes con la sintaxis de las llamadas a métodos orientados a objetos."
+    what_cover_parameters_1: "Parametros"
+    what_cover_parameters_2: "- entrena en cómo pasar parámetros a funciones."
+    what_cover_strings_1: "Cadenas"
+    what_cover_strings_2: "- enseña a los estudiantes acerca de la notación en cadena y como pasar estas cadenas como parámetros."
+    what_cover_loops_1: "Bucles"
+    what_cover_loops_2: "- desarrolla la abstracción del diseño de programas cortos con bucles."
+    what_cover_variables_1: "Variables"
+    what_cover_variables_2: "- añade la habilidad de referenciar valores que cambian con el tiempo."
+    what_cover_2: "Los estudiantes pueden continuar más allá del nivel 20, dependiendo de su velocidad e interés, para aprender dos conceptos adicionales en los niveles tardíos:"
+    what_cover_logic_1: "Condicionales lógicos"
+    what_cover_logic_2: "- cuándo y cómo utilizar if / else para controlar los resultados del juego."
+    what_cover_input_1: "Manipulación de eventos de entrada"
+    what_cover_input_2: "- responder a eventos de entrada para crear una interfaz de usuario."
+    sys_requirements_title: "Requerimientos del sistema"
+    sys_requirements_1: "Debido que CodeCombat es un juego, es más difícil para las computadoras correrlo en relación a un tutorial escrito o un video. Para que todos puedan jugar, hemos optimizado la web para correr rápidamente en todos los navegadores modernos y en maquinas antiguas. Dicho esto, aquí están nuestras sugerencias para sacar el máximo provecho de su experiencia en la Hora del Código:"
+    sys_requirements_2: "Usar una versión actualizada del navegador Chrome o Firefox."
+    sys_requirements_3: "Aunque CodeCombat funcionará en navegadores tan antiguas como IE9, el rendimiento no es tan bueno. Chrome es la mejor opción."
+    sys_requirements_4: "Usar computadoras nuevas."
+    sys_requirements_5: "Cumputadoras viejas, Chromebooks y netbooks tienden a tener menos recursos del sistema, lo que los convierte en una experiencia menos agradable. Se requiere al menos 2 GB de RAM."
+    sys_requirements_6: "Permitir a los estudiantes usar auriculares / audífonos para escuchar el audio."
+    sys_requirements_7: "Ayudamos a los jugadores mediante efectos de sonidos y voces en off, lo que podría hacer a las aulas espacios ruidosos y molestos."

   versions:
     save_version_title: "Guardar nueva versión"


Update spanish translations for es-419

Update spanish translations for es-419

--- app/locale/es-419.coffee
+++ app/locale/es-419.coffee
@@ -81,7 +81,7 @@
     awaiting_levels_adventurer_prefix: "Nosotros creamos 5 nuevos niveles cada semana"
     awaiting_levels_adventurer: "Registrate como un aventurero"
     awaiting_levels_adventurer_suffix: "para ser el primero en jugar nuevos niveles."
-#    adjust_volume: "Adjust volume"
+    adjust_volume: "Ajustar el volumen"
     choose_your_level: "Elige tu nivel" # The rest of this section is the old play view at /play-old and isn't very important.
     adventurer_prefix: "Puedes saltar a cualquier nivel de abajo, o discutir los niveles en "
     adventurer_forum: "el foro del aventurero"
@@ -160,10 +160,10 @@
     date: "Fecha"
     body: "Cuerpo"
     version: "Versión"
-#    pending: "Pending"
-#    accepted: "Accepted"
-#    rejected: "Rejected"
-#    withdrawn: "Withdrawn"
+    pending: "Pendiente"
+    accepted: "Aceptado"
+    rejected: "Rechazado"
+    withdrawn: "Retirado"
     submitter: "Emisor"
     submitted: "Enviado"
     commit_msg: "Enviar mensaje"
@@ -171,10 +171,10 @@
     version_history: "Historial de Versiones"
     version_history_for: "Historial de Versiones para: "
     select_changes: "Selcciona dos cambios abajo para ver la diferencia"
-#    undo_prefix: "Undo"
-#    undo_shortcut: "(Ctrl+Z)"
-#    redo_prefix: "Redo"
-#    redo_shortcut: "(Ctrl+Shift+Z)"
+    undo_prefix: "Deshacer"
+    undo_shortcut: "(Ctrl+Z)"
+    redo_prefix: "Rehacer"
+    redo_shortcut: "(Ctrl+Shift+Z)"
     play_preview: "Mira el avance del nivel"
     result: "Resultado"
     results: "Resultados"
@@ -198,9 +198,9 @@
     hard: "Difícil"
     player: "Jugador"
     player_level: "Nivel" # Like player level 5, not like level: Dungeons of Kithgard
-#    warrior: "Warrior"
-#    ranger: "Ranger"
-#    wizard: "Wizard"
+    warrior: "Guerrero"
+    ranger: "Guardabosques"
+    wizard: "Mago"

   units:
     second: "segundo"
@@ -371,13 +371,13 @@
   subscribe:
     subscribe_title: "Suscribirse"
     unsubscribe: "Des-suscribirse"
-#    confirm_unsubscribe: "Confirm Unsubscribe"
-#    never_mind: "Never Mind, I Still Love You"
-#    thank_you_months_prefix: "Thank you for supporting us these last"
-#    thank_you_months_suffix: "months."
-#    thank_you: "Thank you for supporting CodeCombat."
-#    sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
-#    unsubscribe_feedback_placeholder: "O, what have we done?"
+    confirm_unsubscribe: "Confirmar cancelacion de suscripción"
+    never_mind: "Olvidalo, Te sigo queriendo"
+    thank_you_months_prefix: "Gracias por tu apoyo en estos ultimos"
+    thank_you_months_suffix: "meses."
+    thank_you: "Gracias por apoyar CodeCombat."
+    sorry_to_see_you_go: "¡Sentimos que te vayas! Por favor, haznos saber lo que podríamos haber hecho mejor."
+    unsubscribe_feedback_placeholder: "¿Pero qué hemos hecho?"
     levels: "Adquirí más practica con un nivel bonus!"
     heroes: "Héroes más poderosos!"
     gems: "Bonus de 3500 todos los meses!"
@@ -625,12 +625,12 @@
     revert: "Revertir"
     revert_models: "Revertir Modelos"
     pick_a_terrain: "Elije un Terreno"
-#    dungeon: "Dungeon"
-#    indoor: "Indoor"
-#    desert: "Desert"
+    dungeon: "Calabozo"
+    indoor: "Interior"
+    desert: "Desierto"
     grassy: "Herboso"
     small: "Pequeño"
-#    large: "Large"
+    large: "Grande"
     fork_title: "Fork de Nueva Versión"
     fork_creating: "Creando Fork..."
     generate_terrain: "Generar terreno"
@@ -651,9 +651,9 @@
     level_tab_thangs_all: "Todo"
     level_tab_thangs_conditions: "Condiciones Iniciales"
     level_tab_thangs_add: "Agregar Thangs"
-#    add_components: "Add Components"
-#    component_configs: "Component Configurations"
-#    config_thang: "Double click to configure a thang"
+    add_components: "Agregar Componentes"
+    component_configs: "Configuraciones del Componente"
+    config_thang: "Doble clic para configurar un thang"
     delete: "Borrar"
     duplicate: "Duplicar"
 #    stop_duplicate: "Stop Duplicate"
@@ -691,7 +691,7 @@
 #    achievement_query_goals: "Key achievement off of level goals"
 #    level_completion: "Level Completion"
 #    pop_i18n: "Populate I18N"
-#    tasks: "Tasks"
+    tasks: "Tareas"

   article:
     edit_btn_preview: "Vista previa"
@@ -900,7 +900,7 @@
     leaderboard: "Clasificación"
     user_schema: "Esquema de Usuario"
     user_profile: "Perfil de Usuario"
-#    patch: "Patch"
+    patch: "Parche"
     patches: "Parches"
     patched_model: "Documento fuente"
     model: "Modelo"
@@ -923,13 +923,13 @@
     employers: "Empleadores"
     candidates: "Candidatos"
     candidate_sessions: "Sesión de candidato"
-#    user_remark: "User Remark"
-#    user_remarks: "User Remarks"
+    user_remark: "Observación del usuario"
+    user_remarks: "Observaciones del usuario"
     versions: "Versiones"
     items: "Items"
     heroes: "Héroes"
     achievement: "Logros"
-#    clas: "CLAs"
+    clas: "CLAs"
     play_counts: "Conteo de juegos"
     feedback: "Feedback"
     payment_info: "Información de pago"
@@ -965,7 +965,7 @@
     archmage_wiki_url: "nuestra wiki de Archimago"
     opensource_description_suffix: "Para la lista de softwares que hacen al juego posible."
     practices_title: "Mejores prácticas respetuosas"
-#    practices_description: "These are our promises to you, the player, in slightly less legalese."
+    practices_description: "Estas son nuestras promesas hacia ti, el jugador, en términos menos legales."
     privacy_title: "Privacidad"
     privacy_description: "No vederemos nada sobre tu información personalWe will not sell any of your personal information."
     security_title: "Seguridad"


added product service unit test

added product service unit test

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


Fire final end event when request is finished.

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/RobotSnacks/stout-server.git/'


Teams: Disable Domains tab on team settings modal unless isKoding.


minor: code styling

minor: code styling

--- client/landing/site.landing/coffee/core/utils.coffee
+++ client/landing/site.landing/coffee/core/utils.coffee
@@ -466,12 +466,11 @@
       url       : "/-/teams/create"
       data      : formData
       type      : 'POST'
-      xhrFields : withCredentials : yes
       success   : ->
         KD.utils.clearTeamData()
         location.href = formData.redirect
-      error     : ({responseText}) =>
-        new KDNotificationView title : responseText  routeIfInvitationTokenIsValid: (token) ->
+      error     : ({responseText}) ->
+        new KDNotificationView title : responseText

   routeIfInvitationTokenIsValid: (token) ->


bug fix to limits

bug fix to limits

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


compute/ctrl: remove private template on unshare

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

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -784,6 +784,7 @@
         @checkRevisionFromOriginalStackTemplate stackTemplate
       else
         @removeRevisionFromUnSharedStackTemplate _id, stackTemplate
+        @storage.templates.pop stackTemplate  unless stackTemplate.isMine()
         new kd.NotificationView { title : 'Stack Template is Unshared With Team' }


fix moment

fix moment

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


Page control added properly on time_list.s.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/Bogdan-p/bookingbug-angular.git/'


Add several ember related handlebars snippets

error: pathspec 'snippets/handlebars.cson' did not match any file(s) known to git


Remove Fira Code as the default font

Remove Fira Code as the default font

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


Specs added to show stack overflow issue.

error: pathspec 'spec/waterfall-spec.coffee' did not match any file(s) known to git

--- spec/waterfall-spec.coffee
+++ spec/waterfall-spec.coffee
@@ -0,0 +1,58 @@
+Waterfall = jasmine._given.__Waterfall__
+packFunctions = (n, fn)->
+  (fn for i in [0...n])
+
+#Repitition of the closures and lack of nesting is very intentional
+#as to keep the async calls reasonable.
+
+describe "Waterfall", ->
+
+  context "basic run", ->
+    counter = null
+    Given -> counter = 0
+    When -> new Waterfall(packFunctions(100, -> counter++), ->).flow()
+    Then -> expect(counter).toBe(100)
+
+  xcontext "when we have 128,000 functions", ->
+    counter = null
+    Given -> counter = 0
+    When -> new Waterfall(packFunctions(128000, -> counter++), ->).flow()
+    Then -> expect(counter).toBe(128000)
+
+  context "final fn runs last", ->
+    counter = null
+    countDuringFinal = null
+    Given -> counter = 0
+    Given -> @finalFn = -> countDuringFinal = 100
+    When -> new Waterfall(packFunctions(100, -> counter++), @finalFn).flow()
+    Then -> expect(countDuringFinal).toBe(counter)
+
+  context "with async functions", ->
+    counter = null
+    asyncCounter = null
+    counterDuringFinal = null
+    Given -> [counter, asyncCounter] = [0, 0]
+    Given ->
+      @asyncFn = (done)->
+        setTimeout ->
+          counter++
+          asyncCounter++
+          done()
+        , 5
+
+    Given -> @finalFn = -> counterDuringFinal = counter
+    Given ->
+      @functions = packFunctions(100, -> counter++).
+        concat(packFunctions(100, -> counter++)).
+        concat(packFunctions(10, @asyncFn))
+
+    When -> new Waterfall(@functions, @finalFn).flow()
+    Then ->
+      waitsFor ->
+        asyncCounter == 10
+      runs ->
+        expect(counter).toBe(210)
+    And ->
+      runs ->
+        expect(counterDuringFinal).toBe(counter)
+


Fixed bug #350: Now on change slug, redirect the user to the new valid project url

--- app/coffee/modules/admin/project-profile.coffee
+++ app/coffee/modules/admin/project-profile.coffee
@@ -85,7 +85,7 @@
 ## Project Profile Directive
 #############################################################################

-ProjectProfileDirective = ($log, $repo, $confirm) ->
+ProjectProfileDirective = ($log, $repo, $confirm, $location) ->
     link = ($scope, $el, $attrs) ->
         form = $el.find("form").checksley()
         submit = =>
@@ -94,6 +94,7 @@
             promise = $repo.save($scope.project)
             promise.then ->
                 $confirm.notify("success")
+                $location.path("/project/#{$scope.project.slug}/admin/project-profile/details")

             promise.then null, (data) ->
                 form.setErrors(data)
@@ -152,5 +153,5 @@

     return {link:link}

-module.directive("tgProjectProfile", ["$log", "$tgRepo", "$tgConfirm", ProjectProfileDirective])
+module.directive("tgProjectProfile", ["$log", "$tgRepo", "$tgConfirm", "$location", ProjectProfileDirective])
 module.directive("tgProjectFeatures", ["$log", "$tgRepo", "$tgConfirm", ProjectFeaturesDirective])


furhter work on the parser, beginning of extra arg handling

--- src/scripts/drush.coffee
+++ src/scripts/drush.coffee
@@ -11,11 +11,36 @@
   site_aliases = []
   allowed_commands = ["sa", "cc", "pml", "unif", "pmi", "ws", "vget", "rq"]

+  # helper method to propigate the site aliases in memory
+  update_aliases = (msg) ->
+    output = ''
+    raw_aliases = ''
+    fetch_aliases = spawn("drush", ["sa"])
+    fetch_aliases.stdout.on "data", (data) ->
+      raw_aliases += data
+    fetch_aliases.stderr.on "data", (data) ->
+      output = "Update experienced an error: " + data
+    fetch_aliases.on "exit", (code) ->
+      if code is 0
+        site_aliases = raw_aliases.split('\n')
+        output = "Alias update complete."
+      unless msg is `undefined`
+        msg.send output
+
+  # run the update script upon construction
+  update_aliases()
+
   # Our allowed commands
   commands =
-    drush_sa: (msg) ->
-      msg.send "Aliases we have in memory, if this list is empty or is unexpected update aliases."
-      msg.send site_aliases.join("\n")
+    # site aliases, the only command that does not need an alias prefix
+    drush_sa: (msg, args) ->
+      #msg.send "extra arguments: " + args.join(' ')
+      if args.indexOf('--update-aliases') is -1
+        msg.send "If this list is empty or has unexpected results update aliases ('drush sa --update-aliases')."
+        msg.send "Aliases we have in memory:\n" + site_aliases.join("\n")
+      else
+        msg.send "Updating aliases..."
+        update_aliases(msg)

   # parsing the user input after "drush "
   parse_command = (user_command) ->
@@ -30,34 +55,21 @@
     else
       `undefined`

-  # Begin our public facing methods
-  update_aliases: (msg) ->
-    output = ''
-    raw_aliases = ''
-    fetch_aliases = spawn("drush", ["sa"])
-    fetch_aliases.stdout.on "data", (data) ->
-      raw_aliases += data
-    fetch_aliases.stderr.on "data", (data) ->
-      output = "Update experienced an error: " + data
-    fetch_aliases.on "exit", (code) ->
-      if code is 0
-        site_aliases = raw_aliases.split('\n')
-        output = "drush aliases updated"
-      unless msg is `undefined`
-        msg.send output
+  # BEGIN public facing methods

   # The main method, fire this when we recieve a "drush " command.
   execute: (msg) ->
-    msg.send "we got args: " + msg.match[1]
+    #msg.send "we got args: " + msg.match[1]
     command = parse_command(msg.match[1])
     unless command is `undefined`
-      commands[command.cmnd](msg)
+      commands[command.cmnd](msg, command.extra_args)
     else
       msg.send "'drush " + msg.match[1] + "' is and invalid command. Please try again."

+# Instanciate the drush interface
 drush = drush_interface()
-drush.update_aliases()

+# Hook in with hobot
 module.exports = (robot) ->
   robot.respond /drush (.*)$/i, (msg) ->
     msg.send "drush fired!"


Component for filtering objects by their properties

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

--- src/components/FilterProperty.coffee
+++ src/components/FilterProperty.coffee
@@ -0,0 +1,47 @@
+noflo = require "noflo"
+
+class FilterProperty extends noflo.Component
+    constructor: ->
+        @accepts = []
+        @regexps = []
+
+        @inPorts =
+            accept: new noflo.ArrayPort()
+            regexp: new noflo.ArrayPort()
+            in: new noflo.Port()
+        @outPorts =
+            out: new noflo.Port()
+
+        @inPorts.accept.on "data", (data) =>
+            @accepts.push data
+        @inPorts.regexp.on "data", (data) =>
+            @regexps.push data
+
+        @inPorts.in.on "begingroup", (group) =>
+            @outPorts.out.beginGroup group
+        @inPorts.in.on "data", (data) =>
+            @filterData data
+        @inPorts.in.on "endgroup", =>
+            @outPorts.out.endGroup()
+        @inPorts.in.on "disconnect", =>
+            @outPorts.out.disconnect()
+
+    filterData: (object) ->
+        newData = {}
+        match = false
+        for property, value of object
+            if @accepts.indexOf(property) isnt -1
+                newData[property] = value
+                match = true
+                continue
+
+            for expression in @regexps
+                regexp = new RegExp expression
+                if regexp.exec property
+                    newData[property] = value
+                    match = true
+
+        return unless match
+        @outPorts.out.send newData
+
+exports.getComponent = -> new FilterProperty


Home: PasswordForm: add client-side password checks

I added this as a separate commit, I don't know what planned for this ux but I
didn't want to left it as is, you can see it http://g.recordit.co/kSJHIUpEY3.gif

If there is a flow designed already you can revert this 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/andrewjcasal/koding.git/'


add bind_all to pusher mock

add bind_all to pusher mock

--- test/dummy/spec/javascripts/mock-objects/pusher.js.coffee
+++ test/dummy/spec/javascripts/mock-objects/pusher.js.coffee
@@ -9,19 +9,25 @@
   class Channel

     constructor: ->
-      @callbacks = {}
+      @events = {}
+      @all = $.Callbacks()
+
+    bind_all: (fn) ->
+      @all.add fn

     bind: (name, fn) ->
-      (@callbacks[name] or= $.Callbacks()).add fn
+      (@events[name] or= $.Callbacks()).add fn

     unbind: (name, fn) ->
-      @callbacks[name]?.remove fn
+      @events[name]?.remove fn

     send: (name, data) ->
-      @callbacks[name]?.fire data
+      @all.fire name, data
+      @events[name]?.fire data

-  getChanel = (name) -> channels[name] or= new Channel
+  getChanel = (name) ->
+    channels[name] or= new Channel

   class FakePusher


Add specs for normalizeKeystrokes helper

error: pathspec 'spec/helpers-spec.coffee' did not match any file(s) known to git

--- spec/helpers-spec.coffee
+++ spec/helpers-spec.coffee
@@ -0,0 +1,26 @@
+{normalizeKeystrokes} = require '../src/helpers'
+
+describe ".normalizeKeystrokes(keystrokes)", ->
+  it "parses and normalizes the keystrokes", ->
+    expect(normalizeKeystrokes('ctrl--')).toBe 'ctrl--'
+    expect(normalizeKeystrokes('ctrl-x')).toBe 'ctrl-x'
+    expect(normalizeKeystrokes('a')).toBe 'a'
+    expect(normalizeKeystrokes('shift-a')).toBe 'shift-A'
+    expect(normalizeKeystrokes('shift-9')).toBe 'shift-9'
+    expect(normalizeKeystrokes('-')).toBe '-'
+    expect(normalizeKeystrokes('- -')).toBe '- -'
+    expect(normalizeKeystrokes('a b')).toBe 'a b'
+    expect(normalizeKeystrokes('cmd-k cmd-v')).toBe 'cmd-k cmd-v'
+    expect(normalizeKeystrokes('cmd-cmd')).toBe 'cmd'
+    expect(normalizeKeystrokes('cmd-shift')).toBe 'shift-cmd'
+    expect(normalizeKeystrokes('cmd-shift-a')).toBe 'shift-cmd-A'
+    expect(normalizeKeystrokes('cmd-ctrl-alt--')).toBe 'ctrl-alt-cmd--'
+
+    expect(normalizeKeystrokes('a-b')).toBe false
+    expect(normalizeKeystrokes('---')).toBe false
+    expect(normalizeKeystrokes('cmd-a-b')).toBe false
+
+    expect(-> normalizeKeystrokes('-a-b')).toThrow()
+    expect(-> normalizeKeystrokes('--')).toThrow()
+    expect(-> normalizeKeystrokes('- ')).toThrow()
+    expect(-> normalizeKeystrokes('a ')).toThrow()


whitespace

whitespace

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/amit-bansil/wiretrap.git/'


Add auto select input component

Add auto select input component

[#96883346]

error: pathspec 'review_front/app/components/auto-select-input.coffee' did not match any file(s) known to git

--- review_front/app/components/auto-select-input.coffee
+++ review_front/app/components/auto-select-input.coffee
@@ -0,0 +1,10 @@
+`import Ember from 'ember'`
+
+AutoSelectInput = Ember.TextField.extend
+  attributeBindings: ['readonly']
+  readonly: true
+
+  mouseUp: ->
+    @$().select()
+
+`export default AutoSelectInput`


Filter by primary role, not all roles

Filter by primary role, not all roles

[#99909028]

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


Improve filter chain acceptance specs.

Improve filter chain acceptance specs.

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/jamesotron/ember-enumerology.git/'


levels and default game states

levels and default game states

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

--- src/title_screen.coffee
+++ src/title_screen.coffee
@@ -0,0 +1,10 @@
+TitleScreen = (I={}) ->
+  self = GameState(I)
+
+  self.bind 'update', ->
+    engine.nextLevel() if justPressed.any
+
+  self.bind "overlay", (canvas) ->
+    drawTitleText canvas, window.title, "Press any key to start"
+
+  return self


Scale graphs

Scale graphs

Signed-off-by: Dmitriy Zaporozhets <be23d75b156792e5acab51b196a2deb155d35d6a@gmail.com>

--- app/assets/javascripts/stat_graph_contributors_graph.js.coffee
+++ app/assets/javascripts/stat_graph_contributors_graph.js.coffee
@@ -46,11 +46,7 @@

 class window.ContributorsMasterGraph extends ContributorsGraph
   constructor: (@data) ->
-    if $(window).width() > 1214
-      @width = 1100
-    else
-      @width = 870
-
+    @width = $('.container').width() - 70
     @height = 200
     @x = null
     @y = null
@@ -124,11 +120,7 @@

 class window.ContributorsAuthorGraph extends ContributorsGraph
   constructor: (@data) ->
-    if $(window).width() > 1214
-      @width = 490
-    else
-      @width = 380
-
+    @width = $('.container').width()/2 - 100
     @height = 200
     @x = null
     @y = null


possibly fixing events, probably breaking everything

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


added arabic translation

added arabic translation

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

--- client/i18n/arabic.coffee
+++ client/i18n/arabic.coffee
@@ -0,0 +1,31 @@
+ar =
+  # Billing
+  "Past Invoices": "فواتير سابقة"
+  "Upcoming Invoice": "فواتير قادمة"
+  "Cancel Subscription": "الغاء الاشتراك"
+  "Confirm Cancelling Subscription": "تأكيد الغاء الاشتراك"
+  "Are you sure you want to cancel your subscription?": "هل انت متأكد انك تريد الغاء اشتراكك؟ سوف نحفظ بياناتك حتى تتمكن من اعادة  حسابك فى اى وقت"
+  "Cancel": "الغاء"
+  "on": "على"
+  "Yes, cancel my subscription": "نعم, الغى اشتراكى"
+  "Line Items": "خط الاصناف"
+  "Paid": "مدفوع"
+  "month": "شهر"
+  "Nothing to see here": "لا شيئ هنا"
+
+  # Credit Card
+  "Name": "الإسم"
+  "Billing Info": "بيانات الدفع"
+  "Card Number": "رقم كارت الائتمان"
+  "Expiration": "تاريخ الانتهاء"
+  "Card Code": "رمز الكارت السرى"
+  "Subscription to": "الاشتراك ب"
+  "Address": "العنوان"
+
+  # Notifications
+  "Error getting past invoices": "خطأ فى ايجاد الفواتير السابقة"
+  "Error getting upcoming invoice": "خطأ فى ايجاد الفواتير القادمة"
+  "Error canceling subscription": "خطأ فى الغاء الاشتراك"
+  "Your subscription has been canceled": "تم الغاء اشتراكك"
+
+T9n.map "ar", ar


Add test file of selection

Add test file of selection

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


Fix grammar to valiate JSON numbers.

Fix grammar to valiate JSON numbers.

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/ANATAS/poso-dev-atom.git/'


Added simple table view

Added simple table view

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

--- SingularityUI/app/views/simpleTableView.coffee
+++ SingularityUI/app/views/simpleTableView.coffee
@@ -0,0 +1,17 @@
+View = require './view'
+
+class SimpleTableView extends View
+
+    initialize: ->
+        @listenTo @collection, 'sync',  @render
+        @listenTo @collection, 'reset', =>
+            @$el.empty()
+
+    render: ->
+        return if not @collection.synced
+
+        @$el.html @template
+            data:   @collection.toJSON()
+            synced: @collection.synced
+
+module.exports = SimpleView


Unfocus theme test

Unfocus theme test

--- spec/apm-cli-spec.coffee
+++ spec/apm-cli-spec.coffee
@@ -539,7 +539,7 @@
           expect(fs.existsSync(path.join(packagePath, 'package.cson'))).toBeTruthy()

     describe "when creating a theme", ->
-      fit "generates the proper file structure", ->
+      it "generates the proper file structure", ->
         callback = jasmine.createSpy('callback')
         apm.run(['init', '--theme', 'fake-theme'], callback)


IDE: router: Fix infinite loop when there is no machine available.


Add clean task

Add clean 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/frostney/shopkeeper.git/'


Better logging and listen on all necessary ports

--- lib/models/localhost-proxy.coffee
+++ lib/models/localhost-proxy.coffee
@@ -4,24 +4,26 @@
 module.exports = class LocalhostProxy
   constructor: (port) ->
     @port = port
-    @remoteHost = 'http://159.203.117.55'
+    @remoteHost = 'http://ile.learn.co'
     @desiredPorts = ['3000', '4000', '8000', '9393']

   start: ->
     @withAvailablePort((ports) =>
-      console.log ports
       server = httpProxy.createProxyServer({target: @remoteHost + ':' + @port})

       for port in @desiredPorts
         console.log 'Port: ' + port + ' Available: ' + !!ports[port]
         if !!ports[port]
           server.listen(parseInt(port), 'localhost')
+          console.log 'Listening on port: ' + port
+        else
+          console.log 'NOT listening on port: ' + port
     )

   withAvailablePort: (callback) ->
     ports = {}

-    for port in @desiredPorts
+    @desiredPorts.forEach (port) ->
       try
         server = net.createServer()
         server.listen parseInt(port), 'localhost'
@@ -34,4 +36,14 @@
       catch error
         ports[port] = false

-    callback(ports)
+    allChecked = =>
+      @desiredPorts.every((port) ->
+        ports[port] != null
+      )
+
+    checkInterval = setInterval(=>
+      console.log 'Finished checking available ports: ' + allChecked(ports)
+      if allChecked()
+        clearInterval(checkInterval)
+        callback(ports)
+    , 100)


set port and db by ENV variables

set port and db by ENV variables

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


Added test for navigator class

Added test for navigator class

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


Use pageX instead of clientX

Use pageX instead of clientX

--- assets/javascripts/views/layout/resizer.coffee
+++ assets/javascripts/views/layout/resizer.coffee
@@ -41,9 +41,9 @@
   onDrag: (event) =>
     return if @lastDrag and @lastDrag > Date.now() - 50
     @lastDrag = Date.now()
-    @resize(event.clientX, false)
+    @resize(event.pageX, false)
     return

   onDragEnd: (event) =>
-    @resize(event.clientX or (event.screenX - window.screenX), true)
+    @resize(event.pageX or (event.screenX - window.screenX), true)
     return


better naming; we now talk about "syncing" the event log

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


Actually add indicator controller

Actually add indicator controller

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

--- client/src/controllers/indicator_controller.coffee
+++ client/src/controllers/indicator_controller.coffee
@@ -0,0 +1,11 @@
+window.Backbone ||= {}
+window.Backbone.Controllers ||= {}
+
+
+class Backbone.Controllers.IndicatorController extends Backbone.Diorama.Controller
+  constructor: (indicatorAttributes) ->
+    indicator = new Backbone.Models.Indicator indicatorAttributes
+    indicatorView = new Backbone.Views.IndicatorView(indicator: indicator)
+
+    indicatorView.render()
+    $('.main-content').prepend(indicatorView.el)


Update JAccount.can which is the main security method for server-side

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -340,10 +340,14 @@

   @getFlagRole =-> 'owner'

+  # WARNING! Be sure everything is safe when you change anything in this function
   can:(action, target)->
     switch action
-      when 'delete','flag','reset guests'
+      when 'delete'
+        # Users can delete their stuff but super-admins can delete all of them ಠ_ಠ
         @profile.nickname in dummyAdmins or target?.originId?.equals @getId()
+      when 'flag', 'reset guests'
+        @profile.nickname in dummyAdmins

   fetchRole: secure ({connection}, callback)->


SocialWorker: handle duplicate combinedStorage case

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -945,26 +945,26 @@
   createAppStorage: (options, callback) ->

     { appId, version, data } = options
-
-    JCombinedAppStorage.one { accountId : @getId() }, (err, storage) =>
+    accountId = @getId()
+
+    addStorage = (storage, options, callback) ->
+      { appId, data } = options
+      query = { $set : {} }
+      query.$set["storage.#{appId}.data"] = { data : data ? {} }
+      storage.update query, (err) ->
+        return callback err, storage
+
+    JCombinedAppStorage.one { accountId }, (err, storage) =>
       return callback err  if err
-
-      if storage
-        query = { $set : {} }
-        query.$set["storage.#{appId}.data"] = { data : data ? {} }
-        storage.update query, (err) ->
-          console.log 'updating'
-          console.log storage
-          return callback err, storage
-
-      else
-        query                = { accountId : @getId(), storage : {} }
-        query.storage[appId] = { data : data ? {} }
-        newStorage = new JCombinedAppStorage query
-        newStorage.save (err) ->
-          console.log 'creating'
-          return callback err  if err
-          callback null, newStorage
+      return addStorage storage, { appId, data }, callback  if storage
+
+      query = { accountId, storage : {} }
+      query.storage[appId] = { data : data ? {} }
+      newStorage = new JCombinedAppStorage query
+      newStorage.save (err) =>
+        # recursive call in case of unique index error
+        return @createAppStorage options, callback  if err?.code is 11000
+        return callback err, newStorage

   migrateOldAppStorageIfExists: (options, callback) ->


Revert renaming failureFn to fin

Revert renaming failureFn to fin

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


forgot a few changes

forgot a few changes

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


authorizationCodeGrant test stubs

authorizationCodeGrant test stubs

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

--- test/strategies/oauth2/authorizationCodeGrant.coffee
+++ test/strategies/oauth2/authorizationCodeGrant.coffee
@@ -0,0 +1,80 @@
+# Test dependencies
+nock      = require 'nock'
+chai      = require 'chai'
+sinon     = require 'sinon'
+sinonChai = require 'sinon-chai'
+expect    = chai.expect
+FormUrlencoded = require('form-urlencoded')
+
+
+
+
+# Assertions
+chai.use sinonChai
+chai.should()
+
+
+
+
+# Code under test
+Strategy = require('passport-strategy')
+OAuth2Strategy = require '../../../lib/strategies/OAuth2'
+
+
+
+describe 'OAuth2Strategy authorizationCodeGrant', ->
+
+  describe 'with defaults and valid parameters', ->
+
+    it 'should use the "POST" method'
+    it 'should send the "grant_type" as "authorization_code"'
+    it 'should send the code'
+    it 'should send the redirect_uri'
+    it 'should set the accept header'
+    it 'should set the user agent'
+
+
+
+
+  describe 'with custom method', ->
+    it 'should use the correct HTTP method'
+
+
+
+
+  describe 'with "client_secret_basic" auth', ->
+    it 'should set the Authorization header'
+    it 'should use the Basic scheme'
+    it 'should set base64 encoded credentials'
+
+
+
+
+  describe 'with "client_secret_post" auth', ->
+    it 'should send the client_id'
+    it 'should send the client_secret'
+
+
+
+
+  describe 'with error response', ->
+    it 'should provide an error'
+    it 'should not provide a token response'
+
+
+
+
+  describe 'with "x-www-form-urlencoded" response', ->
+    it 'should not provide an error'
+    it 'should provide the token response'
+
+
+
+
+  describe 'with "JSON" response', ->
+    it 'should not provide an error'
+    it 'should provide the token response'
+
+
+
+


Add test for client request

Add test for client request

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

--- test/test_client.coffee
+++ test/test_client.coffee
@@ -0,0 +1,26 @@
+client  = require 'nack/client'
+process = require 'nack/process'
+
+config = __dirname + "/fixtures/echo.ru"
+
+exports.testClientRequest = (test) ->
+  test.expect 5
+
+  p = process.createProcess config
+  p.on 'ready', () ->
+    c = client.createConnection p.sock
+    test.ok c
+
+    request = c.request 'GET', '/foo', {}
+    test.ok request
+
+    request.end()
+
+    request.on "response", (response) ->
+      test.ok response
+      test.same 200, response.statusCode
+
+      p.quit()
+      p.on 'exit', () ->
+        test.ok true
+        test.done()


add tree list test

add tree list test

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

--- test/tree-list.coffee
+++ test/tree-list.coffee
@@ -0,0 +1,168 @@
+describe('TreeList', ->
+  beforeEach( ->
+    @list = new Quill.Document.TreeList()
+    @a = { str: 'a' }
+    @b = { str: 'b' }
+    @c = { str: 'c' }
+    @a.length = @b.length = @c.length = -> return 3
+  )
+
+  describe('manipulation', ->
+    it('append to empty list', ->
+      @list.append(@a)
+      expect(@list.length).toEqual(1)
+      expect(@list.head).toEqual(@a)
+      expect(@list.tail).toEqual(@a)
+      expect(@a.prev).toBeUndefined()
+      expect(@a.next).toBeUndefined()
+    )
+
+    it('insert to become head', ->
+      @list.append(@b)
+      @list.insertBefore(@a, @b)
+      expect(@list.length).toEqual(2)
+      expect(@list.head).toEqual(@a)
+      expect(@list.tail).toEqual(@b)
+      expect(@a.prev).toBeUndefined()
+      expect(@a.next).toEqual(@b)
+      expect(@b.prev).toEqual(@a)
+      expect(@b.next).toBeUndefined()
+    )
+
+    it('insert to become tail', ->
+      @list.append(@a)
+      @list.insertBefore(@b, undefined)
+      expect(@list.length).toEqual(2)
+      expect(@list.head).toEqual(@a)
+      expect(@list.tail).toEqual(@b)
+      expect(@a.prev).toBeUndefined()
+      expect(@a.next).toEqual(@b)
+      expect(@b.prev).toEqual(@a)
+      expect(@b.next).toBeUndefined()
+    )
+
+    it('insert in middle', ->
+      @list.append(@a, @c)
+      @list.insertBefore(@b, @c)
+      expect(@list.length).toEqual(3)
+      expect(@list.head).toEqual(@a)
+      expect(@a.next).toEqual(@b)
+      expect(@b.next).toEqual(@c)
+      expect(@list.tail).toEqual(@c)
+    )
+
+    it('remove head', ->
+      @list.append(@a, @b)
+      @list.remove(@a)
+      expect(@list.length).toEqual(1)
+      expect(@list.head).toEqual(@b)
+      expect(@list.tail).toEqual(@b)
+      expect(@list.head.prev).toBeUndefined()
+      expect(@list.tail.next).toBeUndefined()
+    )
+
+    it('remove tail', ->
+      @list.append(@a, @b)
+      @list.remove(@b)
+      expect(@list.length).toEqual(1)
+      expect(@list.head).toEqual(@a)
+      expect(@list.tail).toEqual(@a)
+      expect(@list.head.prev).toBeUndefined()
+      expect(@list.tail.next).toBeUndefined()
+    )
+
+    it('remove inner', ->
+      @list.append(@a, @b, @c)
+      @list.remove(@b)
+      expect(@list.length).toEqual(2)
+      expect(@list.head).toEqual(@a)
+      expect(@list.tail).toEqual(@c)
+      expect(@list.head.prev).toBeUndefined()
+      expect(@list.tail.next).toBeUndefined()
+      expect(@a.next).toEqual(@c)
+      expect(@c.prev).toEqual(@a)
+    )
+
+    it('remove only node', ->
+      @list.append(@a)
+      @list.remove(@a)
+      expect(@list.length).toEqual(0)
+      expect(@list.head).toBeUndefined()
+      expect(@list.tail).toBeUndefined()
+    )
+  )
+
+  describe('iteration', ->
+    beforeEach( ->
+      @spy = {
+        callback: (args...) ->
+      }
+      spyOn(@spy, 'callback')
+    )
+
+    it('iterate over empty list', ->
+      @list.forEach(@spy.callback)
+      expect(@spy.callback.calls.count()).toEqual(0)
+    )
+
+    it('find', ->
+      @list.append(@a, @b, @c)
+      expect(@list.find(0)).toEqual([@a, 0])
+      expect(@list.find(2)).toEqual([@a, 2])
+      expect(@list.find(3)).toEqual([@b, 0])
+      expect(@list.find(4)).toEqual([@b, 1])
+      expect(@list.find(10)).toEqual(false)
+    )
+
+    it('forEach', ->
+      @list.append(@a, @b, @c)
+      @list.forEach(@spy.callback)
+      expect(@spy.callback.calls.count()).toEqual(3)
+      result = _.reduce(@spy.callback.calls.all(), (memo, call) ->
+        return memo + call.args[0].str
+      , '')
+      expect(result).toEqual('abc')
+    )
+
+    it('reduce', ->
+      @list.append(@a, @b, @c)
+      memo = @list.reduce((memo, node) ->
+        return memo + node.str
+      , '')
+      expect(memo).toEqual('abc')
+    )
+
+    it('forEachAt', ->
+      @list.append(@a, @b, @c)
+      @list.forEachAt(3, 3, @spy.callback)
+      expect(@spy.callback.calls.count()).toEqual(1)
+      expect(@spy.callback.calls.first().args).toEqual([@b, 0, 3])
+    )
+
+    it('forEachAt partial nodes', ->
+      @list.append(@a, @b, @c)
+      @list.forEachAt(1, 3, @spy.callback)
+      expect(@spy.callback.calls.count()).toEqual(2)
+      calls = @spy.callback.calls.all()
+      expect(calls[0].args).toEqual([@a, 1, 2])
+      expect(calls[1].args).toEqual([@b, 0, 1])
+    )
+
+    it('forEachAt partial nodes', ->
+      @list.append(@a, @b, @c)
+      @list.forEachAt(1, 7, @spy.callback)
+      expect(@spy.callback.calls.count()).toEqual(3)
+      calls = @spy.callback.calls.all()
+      expect(calls[0].args).toEqual([@a, 1, 2])
+      expect(calls[1].args).toEqual([@b, 0, 3])
+      expect(calls[2].args).toEqual([@c, 0, 2])
+    )
+
+    it('forEachAt at part of single node', ->
+      @list.append(@a, @b, @c)
+      @list.forEachAt(4, 1, @spy.callback)
+      expect(@spy.callback.calls.count()).toEqual(1)
+      expect(@spy.callback.calls.first().args).toEqual([@b, 1, 1])
+    )
+  )
+)


CUI

CUI

- Fixed "initNodeDebugCopy".

--- src/base/CUI.coffee
+++ src/base/CUI.coffee
@@ -687,7 +687,7 @@

 	@initNodeDebugCopy: ->
 		Events.listen
-			type: "keyup"
+			type: "keydown"
 			capture: true
 			call: (ev) =>
 				if ev.getKeyboard() != "Alt+C"


bug fix

bug fix

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


check for group fields when minifying

check for group fields when minifying

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


Updated rivets

Updated rivets

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


Spec for #save

Spec for #save

--- apps/artwork/test/routes.coffee
+++ apps/artwork/test/routes.coffee
@@ -1,13 +1,12 @@
-{ fabricate } = require 'antigravity'
-_ = require 'underscore'
-sinon = require 'sinon'
-Backbone = require 'backbone'
-routes = require '../routes'
-CurrentUser = require '../../../models/current_user.coffee'
-Artwork = require '../../../models/artwork.coffee'
+{ fabricate }   = require 'antigravity'
+_               = require 'underscore'
+sinon           = require 'sinon'
+Backbone        = require 'backbone'
+routes          = require '../routes'
+CurrentUser     = require '../../../models/current_user.coffee'
+Artwork         = require '../../../models/artwork.coffee'

 describe 'Artwork routes', ->
-
   beforeEach ->
     sinon.stub Backbone, 'sync'
     @req = { params: { id: 'foo' }, query: { sort: '-published_at' } }
@@ -17,7 +16,6 @@
     Backbone.sync.restore()

   describe '#index', ->
-
     it 'bootstraps the artwork', ->
       routes.index @req, @res
       _.last(Backbone.sync.args)[2].success fabricate 'artwork', id: 'andy-foobar'
@@ -31,3 +29,10 @@
       _.last(Backbone.sync.args)[2].success fabricate 'artwork', id: 'andy-foobar', artist: null
       @res.locals.sd.ARTWORK.id.should.equal 'andy-foobar'
       @res.render.args[0][0].should.equal 'index'
+
+  describe '#save', ->
+    it 'saves the artwork', ->
+      @req.user = new CurrentUser fabricate 'user'
+      routes.save @req, @res
+      _.last(Backbone.sync.args)[0].should.equal 'create'
+      _.last(Backbone.sync.args)[1].url.should.include "/api/v1/collection/saved-artwork/artwork/#{@req.params.id}?user_id=#{@req.user.id}"


Add trailing wildcard route for filter

Add trailing wildcard route for filter

--- apps/legacy_routes/index.coffee
+++ apps/legacy_routes/index.coffee
@@ -3,6 +3,7 @@
 to = require './to'

 app.get '/filter/artworks', to '/browse'
+app.get '/filter/artworks/*', to '/browse'
 app.get '/genes', to '/categories'
 app.get '/partner-application', to '/apply'
 app.get '/fair-application', to '/apply/fair'


Kloud: initial commit for Kloud access via socialapi

error: pathspec 'workers/social/lib/social/models/computeproviders/kloud.coffee' did not match any file(s) known to git

--- workers/social/lib/social/models/computeproviders/kloud.coffee
+++ workers/social/lib/social/models/computeproviders/kloud.coffee
@@ -0,0 +1,69 @@
+{ Base, secure, signature } = require 'bongo'
+
+KONFIG       = require 'koding-config-manager'
+async        = require 'async'
+_            = require 'underscore'
+
+KodingError  = require '../../error'
+KodingLogger = require '../kodinglogger'
+
+{ Kite }     = require 'kite.js'
+SockJs       = require 'node-sockjs-client'
+
+# Kloud wrapper on social backend
+#
+module.exports = class Kloud extends Base
+
+  @trait __dirname, '../../traits/protected'
+  { permit } = require '../group/permissionset'
+
+  @share()
+
+  @set
+    permissions    :
+      'kite ping'  : ['member']
+    sharedMethods  :
+      static       :
+        ping       : (signature Function)
+
+  TIMEOUT = 10000
+
+  getArgs = (client, args) ->
+
+    args[0] ?= {}
+    args[0].impersonate = client.connection.delegate.profile.nickname
+    return args
+
+
+  # calls kite.ping on Kloud on behalf of loggedin user
+  #
+  @ping  = (client, callback) ->
+    @tell client, 'kite.ping', [], callback
+
+  @ping$ = permit 'kite ping', { success: @ping }
+
+
+  @tell = (client, method, args = [], callback) ->
+
+    @transport
+      .tell method, getArgs client, args
+      .then  (res) ->
+        callback null, res
+        return res
+      .timeout TIMEOUT
+      .catch (err) ->
+        callback err
+
+
+  do ->
+
+    options          =
+      url            : "http://localhost:#{KONFIG.kloud.port}/kite"
+      autoConnect    : yes
+      autoReconnect  : yes
+      transportClass : SockJs
+      auth           :
+        type         : 'kloudctl'
+        key          : KONFIG.kloud.secretKey
+
+    Kloud.transport = new Kite options


default view state ('login') added

default view state ('login') added

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/roseliux/CafeTownsend-Angular-Rails.git/'


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

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

--- src/distance.coffee
+++ src/distance.coffee
@@ -0,0 +1,14 @@
+Flickerable = (I={}, self) ->
+  originalAlpha = I.alpha
+
+  self.bind 'update', ->
+    I.flickerDuration = I.flickerDuration.approach(0, 1)
+
+    if I.flickerDuration > 0
+      if I.age.mod(I.flickerFrequency) is 0
+        if I.alpha is I.flickerAlpha
+          I.alpha = originalAlpha
+        else
+          I.alpha = I.flickerAlpha
+    else
+      I.alpha = originalAlpha