mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 18:15:52 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
50095a1778
17 changed files with 102 additions and 37 deletions
|
@ -68,7 +68,7 @@ expandFlattenedDelta = (delta, left, schema) ->
|
|||
parentLeft = left
|
||||
parentSchema = schema
|
||||
for key, i in delta.dataPath
|
||||
# TODO: A more comprehensive way of getting child schemas
|
||||
# TODO: Better schema/json walking
|
||||
childSchema = parentSchema?.items or parentSchema?.properties?[key] or {}
|
||||
childLeft = parentLeft?[key]
|
||||
humanKey = null
|
||||
|
|
|
@ -69,25 +69,18 @@ module.exports.thangNames = thangNames =
|
|||
"Buffy"
|
||||
"Allankrita"
|
||||
]
|
||||
"Peasant": [
|
||||
"Peasant M": [
|
||||
"Yorik"
|
||||
"Hector"
|
||||
"Thad"
|
||||
"Victor"
|
||||
"Lyle"
|
||||
"Charles"
|
||||
"Mary"
|
||||
"Brandy"
|
||||
"Gwendolin"
|
||||
"Tabitha"
|
||||
"Regan"
|
||||
"Yusef"
|
||||
"Hingle"
|
||||
"Azgot"
|
||||
"Piers"
|
||||
"Carlton"
|
||||
"Giselle"
|
||||
"Bernadette"
|
||||
"Hershell"
|
||||
"Gawain"
|
||||
"Durfkor"
|
||||
|
@ -99,6 +92,13 @@ module.exports.thangNames = thangNames =
|
|||
"Icey"
|
||||
"Matilda"
|
||||
"Mertia"
|
||||
"Mary"
|
||||
"Brandy"
|
||||
"Gwendolin"
|
||||
"Tabitha"
|
||||
"Regan"
|
||||
"Giselle"
|
||||
"Bernadette"
|
||||
]
|
||||
"Archer F": [
|
||||
"Phoebe"
|
||||
|
|
|
@ -8,7 +8,7 @@ class Vector
|
|||
a.copy()[name](b, useZ)
|
||||
|
||||
isVector: true
|
||||
apiProperties: ['x', 'y', 'magnitude', 'heading', 'distance', 'dot', 'equals', 'copy']
|
||||
apiProperties: ['x', 'y', 'magnitude', 'heading', 'distance', 'dot', 'equals', 'copy', 'distanceSquared']
|
||||
|
||||
constructor: (@x=0, @y=0, @z=0) ->
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
module.exports = nativeDescription: "Nederlands (België)", englishDescription: "Dutch (Belgium)", translation:
|
||||
common:
|
||||
loading: "Aan het laden..."
|
||||
loading: "Bezig met laden..."
|
||||
saving: "Opslaan..."
|
||||
sending: "Verzenden..."
|
||||
send: "Verzend"
|
||||
cancel: "Annuleren"
|
||||
save: "Opslagen"
|
||||
save: "Opslaan"
|
||||
publish: "Publiceren"
|
||||
create: "Creëer"
|
||||
delay_1_sec: "1 seconde"
|
||||
|
@ -46,7 +46,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
|
|||
employers: "Werkgevers"
|
||||
|
||||
versions:
|
||||
save_version_title: "Nieuwe versie opslagen"
|
||||
save_version_title: "Nieuwe versie opslaan"
|
||||
new_major_version: "Nieuwe hoofd versie"
|
||||
cla_prefix: "Om bewerkingen op te slaan, moet je eerst akkoord gaan met onze"
|
||||
cla_url: "CLA"
|
||||
|
@ -308,7 +308,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
|
|||
|
||||
editor:
|
||||
main_title: "CodeCombat Editors"
|
||||
main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!"
|
||||
main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die je nodig hebt!"
|
||||
article_title: "Artikel Editor"
|
||||
article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes."
|
||||
thang_title: "Thang Editor"
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription: "Dutch (Netherlands)", translation:
|
||||
common:
|
||||
loading: "Aan het laden..."
|
||||
loading: "Bezig met laden..."
|
||||
saving: "Opslaan..."
|
||||
sending: "Verzenden..."
|
||||
send: "Verzend"
|
||||
cancel: "Annuleren"
|
||||
save: "Opslagen"
|
||||
save: "Opslaan"
|
||||
publish: "Publiceren"
|
||||
create: "Creëer"
|
||||
delay_1_sec: "1 seconde"
|
||||
|
@ -46,7 +46,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
|
|||
employers: "Werkgevers"
|
||||
|
||||
versions:
|
||||
save_version_title: "Nieuwe versie opslagen"
|
||||
save_version_title: "Nieuwe versie opslaan"
|
||||
new_major_version: "Nieuwe hoofd versie"
|
||||
cla_prefix: "Om bewerkingen op te slaan, moet je eerst akkoord gaan met onze"
|
||||
cla_url: "CLA"
|
||||
|
@ -308,7 +308,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
|
|||
|
||||
editor:
|
||||
main_title: "CodeCombat Editors"
|
||||
main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!"
|
||||
main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die je nodig hebt!"
|
||||
article_title: "Artikel Editor"
|
||||
article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes."
|
||||
thang_title: "Thang Editor"
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", translation:
|
||||
common:
|
||||
loading: "Aan het laden..."
|
||||
loading: "Bezig met laden..."
|
||||
saving: "Opslaan..."
|
||||
sending: "Verzenden..."
|
||||
send: "Verzend"
|
||||
cancel: "Annuleren"
|
||||
save: "Opslagen"
|
||||
save: "Opslaan"
|
||||
publish: "Publiceren"
|
||||
create: "Creëer"
|
||||
delay_1_sec: "1 seconde"
|
||||
|
@ -46,7 +46,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
|
|||
employers: "Werkgevers"
|
||||
|
||||
versions:
|
||||
save_version_title: "Nieuwe versie opslagen"
|
||||
save_version_title: "Nieuwe versie opslaan"
|
||||
new_major_version: "Nieuwe hoofd versie"
|
||||
cla_prefix: "Om bewerkingen op te slaan, moet je eerst akkoord gaan met onze"
|
||||
cla_url: "CLA"
|
||||
|
@ -308,7 +308,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
|
|||
|
||||
editor:
|
||||
main_title: "CodeCombat Editors"
|
||||
main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!"
|
||||
main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die je nodig hebt!"
|
||||
article_title: "Artikel Editor"
|
||||
article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes."
|
||||
thang_title: "Thang Editor"
|
||||
|
|
|
@ -133,6 +133,7 @@ class CocoModel extends Backbone.Model
|
|||
schema ?= @schema()
|
||||
models = []
|
||||
|
||||
# TODO: Better schema/json walking
|
||||
if $.isArray(data) and schema.items?
|
||||
for subData, i in data
|
||||
models = models.concat(@getReferencedModels(subData, schema.items, path+i+'/', shouldLoadProjection))
|
||||
|
@ -226,5 +227,27 @@ class CocoModel extends Backbone.Model
|
|||
|
||||
watching: ->
|
||||
return me.id in (@get('watchers') or [])
|
||||
|
||||
populateI18N: (data, schema, path='') ->
|
||||
# TODO: Better schema/json walking
|
||||
sum = 0
|
||||
data ?= $.extend true, {}, @attributes
|
||||
schema ?= @schema() or {}
|
||||
if schema.properties?.i18n and _.isPlainObject(data) and not data.i18n?
|
||||
data.i18n = {}
|
||||
sum += 1
|
||||
|
||||
if _.isPlainObject data
|
||||
for key, value of data
|
||||
numChanged = 0
|
||||
numChanged = @populateI18N(value, childSchema, path+'/'+key) if childSchema = schema.properties?[key]
|
||||
if numChanged and not path # should only do this for the root object
|
||||
@set key, value
|
||||
sum += numChanged
|
||||
|
||||
if schema.items and _.isArray data
|
||||
sum += @populateI18N(value, schema.items, path+'/'+index) for value, index in data
|
||||
|
||||
sum
|
||||
|
||||
module.exports = CocoModel
|
||||
|
|
|
@ -68,6 +68,8 @@ block header
|
|||
a(data-i18n="common.fork")#fork-level-start-button Fork
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
|
||||
li.divider
|
||||
li.dropdown-header Info
|
||||
li#level-history-button
|
||||
|
|
|
@ -28,6 +28,7 @@ block content
|
|||
th(data-i18n="employers.candidate_last_updated") Last Updated
|
||||
if me.isAdmin()
|
||||
th ✓?
|
||||
th ಥ_ಥ
|
||||
|
||||
tbody
|
||||
for candidate, index in candidates
|
||||
|
@ -57,4 +58,8 @@ block content
|
|||
if candidate.get('jobProfileApproved')
|
||||
td ✓
|
||||
else
|
||||
td ✗
|
||||
td ✗
|
||||
if profile.active
|
||||
td ᶘ ᵒᴥᵒᶅ
|
||||
else
|
||||
td ⨂_⨂
|
|
@ -233,6 +233,7 @@ class InternationalizationNode extends TreemaNode.nodeMap.object
|
|||
type: "object"
|
||||
properties: {}
|
||||
}
|
||||
return i18nChildSchema unless @parent
|
||||
unless @schema.props?
|
||||
console.warn "i18n props array is empty! Filling with all parent properties by default"
|
||||
@schema.props = (prop for prop,_ of @parent.schema.properties when prop isnt "i18n")
|
||||
|
|
|
@ -40,6 +40,7 @@ module.exports = class ThangComponentEditView extends CocoView
|
|||
@render()
|
||||
|
||||
buildExtantComponentTreema: ->
|
||||
new Level() # hack to load the schema
|
||||
treemaOptions =
|
||||
supermodel: @supermodel
|
||||
schema: Level.schema.properties.thangs.items.properties.components
|
||||
|
|
|
@ -31,6 +31,7 @@ module.exports = class EditorLevelView extends View
|
|||
'click #patches-tab': -> @patchesView.load()
|
||||
'click #level-patch-button': 'startPatchingLevel'
|
||||
'click #level-watch-button': 'toggleWatchLevel'
|
||||
'click #pop-level-i18n-button': -> @level.populateI18N()
|
||||
|
||||
constructor: (options, @levelID) ->
|
||||
super options
|
||||
|
|
|
@ -77,7 +77,8 @@ grabUser = (session, callback) ->
|
|||
|
||||
totalEmailsSent = 0
|
||||
emailUser = (user, callback) ->
|
||||
return callback null, false if user.emails?.recruiting?.enabled is false # TODO: later, obey also "announcements" when that's untangled
|
||||
#return callback null, false if user.emails?.anyNotes?.enabled is false # TODO: later, uncomment to obey also "anyNotes" when that's untangled
|
||||
return callback null, false if user.emails?.recruitNotes?.enabled is false
|
||||
return callback null, false if user.email in alreadyEmailed
|
||||
return callback null, false if DEBUGGING and (totalEmailsSent > 1 or Math.random() > 0.1)
|
||||
++totalEmailsSent
|
||||
|
|
|
@ -132,14 +132,24 @@ module.exports.setup = (app) ->
|
|||
return errors.notFound res, "No user found with email '#{req.query.email}'"
|
||||
|
||||
emails = _.clone(user.get('emails')) or {}
|
||||
emailSettings.enabled = false for emailSettings in _.values(emails)
|
||||
emails.generalNews ?= {}
|
||||
emails.generalNews.enabled = false
|
||||
emails.anyNotes ?= {}
|
||||
emails.anyNotes.enabled = false
|
||||
user.update {$set: {emails: emails, emailSubscriptions: []}}, {}, =>
|
||||
msg = ''
|
||||
|
||||
if req.query.recruitNotes
|
||||
emails.recruitNotes ?= {}
|
||||
emails.recruitNotes.enabled = false
|
||||
msg = "Unsubscribed #{req.query.email} from recruiting emails."
|
||||
|
||||
else
|
||||
msg = "Unsubscribed #{req.query.email} from all CodeCombat emails. Sorry to see you go!"
|
||||
emailSettings.enabled = false for emailSettings in _.values(emails)
|
||||
emails.generalNews ?= {}
|
||||
emails.generalNews.enabled = false
|
||||
emails.anyNotes ?= {}
|
||||
emails.anyNotes.enabled = false
|
||||
|
||||
user.update {$set: {emails: emails}}, {}, =>
|
||||
return errors.serverError res, 'Database failure.' if err
|
||||
res.send "Unsubscribed #{req.query.email} from all CodeCombat emails. Sorry to see you go! <p><a href='/account/settings'>Account settings</a></p>"
|
||||
res.send msg + "<p><a href='/account/settings'>Account settings</a></p>"
|
||||
res.end()
|
||||
|
||||
module.exports.loginUser = loginUser = (req, res, user, send=true, next=null) ->
|
||||
|
|
|
@ -47,7 +47,7 @@ UserSchema.methods.setEmailSubscription = (newName, enabled) ->
|
|||
oldSubs.push(oldName) if enabled
|
||||
@set('emailSubscriptions', oldSubs)
|
||||
|
||||
newSubs = _.clone(@get('emails') or jsonschema.properties.emails.default)
|
||||
newSubs = _.clone(@get('emails') or _.cloneDeep(jsonschema.properties.emails.default))
|
||||
newSubs[newName] ?= {}
|
||||
newSubs[newName].enabled = enabled
|
||||
@set('emails', newSubs)
|
||||
|
@ -60,7 +60,7 @@ UserSchema.methods.isEmailSubscriptionEnabled = (newName) ->
|
|||
oldName = emailNameMap[newName]
|
||||
return oldName and oldName in oldSubs if oldSubs
|
||||
emails ?= {}
|
||||
_.defaults emails, jsonschema.properties.emails.default
|
||||
_.defaults emails, _.cloneDeep(jsonschema.properties.emails.default)
|
||||
return emails[newName]?.enabled
|
||||
|
||||
UserSchema.statics.updateMailChimp = (doc, callback) ->
|
||||
|
|
|
@ -235,9 +235,10 @@ UserHandler = class UserHandler extends Handler
|
|||
getCandidates: (req, res) ->
|
||||
authorized = req.user.isAdmin() or ('employer' in req.user.get('permissions'))
|
||||
since = (new Date((new Date()) - 2 * 30.4 * 86400 * 1000)).toISOString()
|
||||
query = {'jobProfile.active': true, 'jobProfile.updated': {$gt: since}}
|
||||
#query = {'jobProfile.updated': {$gt: since}}
|
||||
#query = {'jobProfile.active': true, 'jobProfile.updated': {$gt: since}}
|
||||
query = {'jobProfile.updated': {$gt: since}}
|
||||
query.jobProfileApproved = true unless req.user.isAdmin()
|
||||
query['jobProfile.active'] = true unless req.user.isAdmin()
|
||||
selection = 'jobProfile'
|
||||
selection += ' email' if authorized
|
||||
selection += ' jobProfileApproved' if req.user.isAdmin()
|
||||
|
@ -251,7 +252,7 @@ UserHandler = class UserHandler extends Handler
|
|||
fields = if authorized then ['jobProfile', 'jobProfileApproved', 'photoURL', '_id'] else ['jobProfile']
|
||||
obj = _.pick document.toObject(), fields
|
||||
obj.photoURL ||= obj.jobProfile.photoURL if authorized
|
||||
subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated']
|
||||
subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated', 'active']
|
||||
if authorized
|
||||
subfields = subfields.concat ['name']
|
||||
obj.jobProfile = _.pick obj.jobProfile, subfields
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require '../common'
|
||||
request = require 'request'
|
||||
User = require '../../../server/users/User'
|
||||
|
||||
urlLogin = getURL('/auth/login')
|
||||
urlReset = getURL('/auth/reset')
|
||||
|
@ -16,7 +17,8 @@ describe '/auth/whoami', ->
|
|||
describe '/auth/login', ->
|
||||
|
||||
it 'clears Users first', (done) ->
|
||||
User.remove {}, (err) ->
|
||||
clearModels [User], (err) ->
|
||||
throw err if err
|
||||
request.get getURL('/auth/whoami'), ->
|
||||
throw err if err
|
||||
done()
|
||||
|
@ -134,3 +136,21 @@ describe '/auth/reset', ->
|
|||
form = req.form()
|
||||
form.append('username', 'scott@gmail.com')
|
||||
form.append('password', 'nada')
|
||||
|
||||
describe '/auth/unsubscribe', ->
|
||||
it 'clears Users first', (done) ->
|
||||
clearModels [User], (err) ->
|
||||
throw err if err
|
||||
request.get getURL('/auth/whoami'), ->
|
||||
throw err if err
|
||||
done()
|
||||
|
||||
it 'removes just recruitment emails if you include ?recruitNotes=1', (done) ->
|
||||
loginJoe (joe) ->
|
||||
url = getURL('/auth/unsubscribe?recruitNotes=1&email='+joe.get('email'))
|
||||
request.get url, (error, response) ->
|
||||
expect(response.statusCode).toBe(200)
|
||||
user = User.findOne(joe.get('_id')).exec (err, user) ->
|
||||
expect(user.get('emails').recruitNotes.enabled).toBe(false)
|
||||
expect(user.isEmailSubscriptionEnabled('generalNews')).toBeTruthy()
|
||||
done()
|
||||
|
|
Loading…
Reference in a new issue