Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-06-01 11:45:27 -07:00
commit 9cbc6028b2
15 changed files with 82 additions and 67 deletions

View file

@ -5,6 +5,7 @@ BEEN_HERE_BEFORE_KEY = 'beenHereBefore'
init = ->
module.exports.me = window.me = new User(window.userObject) # inserted into main.html
module.exports.me.onLoaded()
trackFirstArrival()
if me and not me.get('testGroupNumber')?
# Assign testGroupNumber to returning visitors; new ones in server/routes/auth

View file

@ -162,10 +162,14 @@ groupDeltasByAffectingPaths = (deltas) ->
prunedMap
module.exports.pruneConflictsFromDelta = (delta, conflicts) ->
expandedDeltas = (conflict.pendingDelta for conflict in conflicts)
module.exports.pruneExpandedDeltasFromDelta delta, expandedDeltas
module.exports.pruneExpandedDeltasFromDelta = (delta, expandedDeltas) ->
# the jsondiffpatch delta mustn't include any dangling nodes,
# or else things will get removed which shouldn't be, or errors will occur
for conflict in conflicts
prunePath delta, conflict.pendingDelta.deltaPath
for expandedDelta in expandedDeltas
prunePath delta, expandedDelta.deltaPath
if _.isEmpty delta then undefined else delta
prunePath = (delta, path) ->

View file

@ -34,5 +34,5 @@ module.exports.applyErrorsToForm = (el, errors) ->
module.exports.clearFormAlerts = (el) ->
$('.has-error', el).removeClass('has-error')
$('.alert', el).remove()
$('.alert.alert-danger', el).remove()
el.find('.help-block.error-help-block').remove()

View file

@ -78,7 +78,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
creating: "Fiók létrehozása"
sign_up: "Regisztráció"
log_in: "Belépés meglévő fiókkal"
# social_signup: "Or, you can sign up through Facebook or G+:"
social_signup: "De regisztrálhatsz a Facebook-on vagy a G+:-on keresztül is."
# required: "You need to log in before you can go that way."
home:
@ -166,10 +166,10 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
email_announcements_description: "Szeretnél levelet kapni a legújabb fejlesztéseinkről?"
email_notifications: "Értesítések"
# email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
# email_any_notes: "Any Notifications"
# email_any_notes_description: "Disable to stop all activity notification emails."
# email_recruit_notes: "Job Opportunities"
# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
email_any_notes: "Bármely értesítés"
email_any_notes_description: "Minden tevékenységgel kapcsolatos e-mail értesítés letiltása."
email_recruit_notes: "Álláslehetőségek"
email_recruit_notes_description: "Ha igazán jól játszol lehet, hogy felveszzük veled a kapcsolatot és megbeszéljük, hogy szerezzünk-e neked egy (jobb) állást."
contributor_emails: "Hozzájárulóknak szóló levelek"
contribute_prefix: "Folyamatosan keresünk embereket, hogy csatlakozzanak hozzánk. Nézz rá a "
contribute_page: "segítők oldalára"
@ -181,8 +181,8 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
job_profile: "Munkaköri leírás"
job_profile_approved: "Munkaköri leírásodat a Codecombat jóváhagyta. Munkaadók mindaddig láthatják, amíg meg nem jelölöd inaktíként, vagy négy hétig,ha addig nem kerül megváltoztatásra."
job_profile_explanation: "Szió! Töltsd ki ezt és majd kapcsolatba lépünk veled és keresünk neked egy szoftware fejlesztői állást."
# sample_profile: "See a sample profile"
# view_profile: "View Your Profile"
sample_profile: "Nézz meg egy mintaprofilt!"
view_profile: "Nézd meg a profilodat!"
account_profile:
edit_settings: "Beállítások szerkesztése"

View file

@ -15,10 +15,10 @@ class CocoModel extends Backbone.Model
super()
if not @constructor.className
console.error("#{@} needs a className set.")
@markToRevert()
@addSchemaDefaults()
@on 'sync', @onLoaded, @
@on 'error', @onError, @
@on 'add', @onLoaded, @
@saveBackup = _.debounce(@saveBackup, 500)
type: ->
@ -38,14 +38,15 @@ class CocoModel extends Backbone.Model
@loaded = true
@loading = false
@jqxhr = null
@markToRevert()
@loadFromBackup()
getNormalizedURL: -> "#{@urlRoot}/#{@id}"
set: ->
inFlux = @loading or not @loaded
@markToRevert() unless inFlux or @_revertAttributes
res = super(arguments...)
@saveBackup() if @saveBackups and @loaded and @hasLocalChanges()
@saveBackup() if @saveBackups and (not inFlux) and @hasLocalChanges()
res
loadFromBackup: ->
@ -62,21 +63,28 @@ class CocoModel extends Backbone.Model
@backedUp = {}
schema: -> return @constructor.schema
getValidationErrors: ->
errors = tv4.validateMultiple(@attributes, @constructor.schema or {}).errors
return errors if errors?.length
validate: ->
result = tv4.validateMultiple(@attributes, @constructor.schema? or {})
if result.errors?.length
console.log @, "got validate result with errors:", result
return result.errors unless result.valid
errors = @getValidationErrors()
if errors?.length
console.debug "Validation failed for #{@constructor.className}: '#{@get('name') or @}'."
for error in errors
console.debug "\t", error.dataPath, ":", error.message
return errors
save: (attrs, options) ->
@set 'editPath', document.location.pathname
options ?= {}
options.headers ?= {}
options.headers['X-Current-Path'] = document.location.pathname
success = options.success
error = options.error
options.success = (model, res) =>
@trigger "save:success", @
success(@, res) if success
@markToRevert()
@markToRevert() if @_revertAttributes
@clearBackup()
options.error = (model, res) =>
error(@, res) if error
@ -93,7 +101,7 @@ class CocoModel extends Backbone.Model
@jqxhr
markToRevert: ->
return unless @saveBackups
console.debug "Saving _revertAttributes for #{@constructor.className}: '#{@get('name')}'"
if @type() is 'ThangType'
@_revertAttributes = _.clone @attributes # No deep clones for these!
else
@ -142,7 +150,6 @@ class CocoModel extends Backbone.Model
#console.log "setting", prop, "to", sch.default, "from sch.default" if sch.default?
@set prop, sch.default if sch.default?
if @loaded
@markToRevert()
@loadFromBackup()
@isObjectID: (s) ->

View file

@ -53,3 +53,7 @@
margin: 10px 10px 0
input
margin-right: 5px
#errors-wrapper
margin-top: 20px
margin-bottom: 0

View file

@ -53,3 +53,7 @@ block modal-body-content
label
input(id=id + "-version-is-major", name="version-is-major", type="checkbox")
span(data-i18n="versions.new_major_version") New Major Version
#errors-wrapper.alert.alert-danger.hide
strong Validation Error! Save failed.
p.errors

View file

@ -44,26 +44,27 @@ module.exports = class DeltaView extends CocoView
@expandedDeltas = @model.getExpandedDeltaWith(@comparisonModel)
else
@expandedDeltas = @model.getExpandedDelta()
@filterExpandedDeltas()
[@expandedDeltas, @skippedDeltas] = @filterDeltas(@expandedDeltas)
if @headModel
@headDeltas = @headModel.getExpandedDelta()
@headDeltas = @filterDeltas(@headDeltas)[0]
@conflicts = deltasLib.getConflicts(@headDeltas, @expandedDeltas)
filterExpandedDeltas: ->
return unless @skipPaths
filterDeltas: (deltas) ->
return [deltas, []] unless @skipPaths
for path, i in @skipPaths
@skipPaths[i] = [path] if _.isString(path)
newDeltas = []
for delta in @expandedDeltas
skippedDeltas = []
for delta in deltas
skip = false
for skipPath in @skipPaths
if _.isEqual _.first(delta.dataPath, skipPath.length), skipPath
skip = true
break
newDeltas.push delta unless skip
@expandedDeltas = newDeltas
if skip then skippedDeltas.push delta else newDeltas.push delta
[newDeltas, skippedDeltas]
getRenderData: ->
c = super()
@ -87,7 +88,7 @@ module.exports = class DeltaView extends CocoView
@expandDetails(deltaEl, deltaData)
expandDetails: (deltaEl, deltaData) ->
treemaOptions = { schema: deltaData.schema, readOnly: true }
treemaOptions = { schema: deltaData.schema or {}, readOnly: true }
if _.isObject(deltaData.left) and leftEl = deltaEl.find('.old-value')
options = _.defaults {data: deltaData.left}, treemaOptions
@ -110,4 +111,5 @@ module.exports = class DeltaView extends CocoView
getApplicableDelta: ->
delta = @model.getDelta()
delta = deltasLib.pruneConflictsFromDelta delta, @conflicts if @conflicts
delta = deltasLib.pruneExpandedDeltasFromDelta delta, @skippedDeltas if @skippedDeltas
delta

View file

@ -53,7 +53,7 @@ module.exports = class LevelSaveView extends SaveVersionModal
commitLevel: ->
modelsToSave = []
@showLoading()
formsToSave = []
for form in @$el.find('form')
# Level form is first, then LevelComponents' forms, then LevelSystems' forms
fields = {}
@ -75,7 +75,19 @@ module.exports = class LevelSaveView extends SaveVersionModal
@level.publish()
else if @level.isPublished() and not newModel.isPublished()
newModel.publish() # Publish any LevelComponents that weren't published yet
formsToSave.push form
for model in modelsToSave
if errors = model.getValidationErrors()
messages = ("\t #{error.dataPath}: #{error.message}" for error in errors)
messages = messages.join('<br />')
@$el.find('#errors-wrapper .errors').html(messages)
@$el.find('#errors-wrapper').removeClass('hide')
return
@showLoading()
tuples = _.zip(modelsToSave, formsToSave)
for [newModel, form] in tuples
res = newModel.save()
do (newModel, form) =>
res.error =>

View file

@ -152,32 +152,6 @@ class EventPrereqNode extends TreemaNode.nodeMap.object
class ChannelNode extends TreemaNode.nodeMap.string
buildValueForEditing: (valEl) ->
super(valEl)
valEl.find('input').autocomplete(source: channels, minLength: 0, delay: 0, autoFocus: true)
autocompleteValues = ({label: val?.title or key, value: key} for key, val of Backbone.Mediator.channelSchemas)
valEl.find('input').autocomplete(source: autocompleteValues, minLength: 0, delay: 0, autoFocus: true)
valEl
channels = [
"tome:palette-hovered",
"tome:palette-clicked",
"tome:spell-shown",
"end-current-script",
"goal-manager:new-goal-states",
"god:new-world-created",
"help-multiplayer",
"help-next",
"help-overview",
"level-restart-ask",
"level-set-playing",
"level:docs-hidden",
"level:team-set",
"playback:manually-scrubbed",
"sprite:speech-updated",
"surface:coordinates-shown",
"surface:frame-changed",
"surface:sprite-selected",
"world:thang-attacked-when-out-of-range",
"world:thang-collected-item",
"world:thang-died",
"world:thang-left-map",
"world:thang-touched-goal",
"world:won"
]

View file

@ -51,4 +51,5 @@ module.exports = class SettingsTabView extends View
onSettingsChanged: (e) =>
$('.level-title').text @settingsTreema.data.name
for key in @editableSettings
continue unless @settingsTreema.data[key] is undefined
@level.set key, @settingsTreema.data[key]

View file

@ -194,7 +194,7 @@ module.exports = class ThangsTabView extends View
return unless @selectedExtantThang and e.thang?.id is @selectedExtantThang?.id
@surface.camera.dragDisabled = true
{stageX, stageY} = e.originalEvent
wop = @surface.camera.canvasToWorld x: stageX, y: stageY
wop = @surface.camera.screenToWorld x: stageX, y: stageY
wop.z = @selectedExtantThang.depth / 2
@adjustThangPos @selectedExtantSprite, @selectedExtantThang, wop
[w, h] = [@surface.camera.canvasWidth, @surface.camera.canvasHeight]
@ -250,6 +250,7 @@ module.exports = class ThangsTabView extends View
# @thangsTreema.deselectAll()
selectAddThang: (e) =>
return if e? and $(e.target).closest('#thang-search').length # Ignore if you're trying to search thangs
return unless e? and $(e.target).closest('#editor-level-thangs-tab-view').length or key.isPressed('esc')
if e then target = $(e.target) else target = @$el.find('.add-thangs-palette') # pretend to click on background if no event
return true if target.attr('id') is 'surface'
@ -258,7 +259,7 @@ module.exports = class ThangsTabView extends View
@$el.find('.add-thangs-palette .add-thang-palette-icon.selected').removeClass('selected')
@selectAddThangType(if wasSelected then null else target.attr 'data-thang-type') unless key.alt or key.meta
target.addClass('selected') if @addThangType
false
#false # was causing #1099, any reason to keep?
moveAddThangSelection: (direction) ->
return unless @addThangType
@ -319,7 +320,7 @@ module.exports = class ThangsTabView extends View
onSurfaceMouseMoved: (e) ->
return unless @addThangSprite
wop = @surface.camera.canvasToWorld x: e.x, y: e.y
wop = @surface.camera.screenToWorld x: e.x, y: e.y
wop.z = 0.5
@adjustThangPos @addThangSprite, @addThangSprite.thang, wop
null

View file

@ -8,6 +8,7 @@ module.exports = class PatchModal extends ModalView
template: template
plain: true
modalWidthPercent: 60
@DOC_SKIP_PATHS = ['_id','version', 'commitMessage', 'parent', 'created', 'slug', 'index', '__v', 'patches']
events:
'click #withdraw-button': 'withdrawPatch'
@ -36,14 +37,16 @@ module.exports = class PatchModal extends ModalView
headModel = null
if @targetModel.hasWriteAccess()
headModel = @originalSource.clone(false)
headModel.markToRevert true
headModel.set(@targetModel.attributes)
headModel.loaded = true
pendingModel = @originalSource.clone(false)
pendingModel.markToRevert true
pendingModel.applyDelta(@patch.get('delta'))
pendingModel.loaded = true
@deltaView = new DeltaView({model:pendingModel, headModel:headModel})
@deltaView = new DeltaView({model:pendingModel, headModel:headModel, skipPaths: PatchModal.DOC_SKIP_PATHS})
changeEl = @$el.find('.changes-stub')
@insertSubView(@deltaView, changeEl)
super()

View file

@ -2,6 +2,7 @@ ModalView = require 'views/kinds/ModalView'
template = require 'templates/modal/versions'
tableTemplate = require 'templates/kinds/table'
DeltaView = require 'views/editor/delta'
PatchModal = require 'views/editor/patch_modal'
class VersionsViewCollection extends Backbone.Collection
url: ""
@ -49,7 +50,7 @@ module.exports = class VersionsModalView extends ModalView
laterVersion = new @model(_id:$(rows[0]).val())
earlierVersion = new @model(_id:$(rows[1]).val())
@deltaView = new DeltaView({model:earlierVersion, comparisonModel:laterVersion, skipPaths:['_id','version', 'commitMessage', 'parent', 'created', 'slug', 'index']})
@deltaView = new DeltaView({model:earlierVersion, comparisonModel:laterVersion, skipPaths:PatchModal.DOC_SKIP_PATHS})
@insertSubView(@deltaView, deltaEl)
getRenderData: (context={}) ->

View file

@ -325,7 +325,8 @@ module.exports = class Handler
newDocument.save (err) =>
return @sendDatabaseError(res, err) if err
@sendSuccess(res, @formatEntity(req, newDocument))
@notifyWatchersOfChange(req.user, newDocument, req.body.editPath) if @modelClass.schema.is_patchable
if @modelClass.schema.is_patchable
@notifyWatchersOfChange(req.user, newDocument, req.headers['x-current-path'])
if major?
parentDocument.makeNewMinorVersion(updatedObject, major, done)