mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 10:56:53 -05:00
7bab895dee
Previously, when diplomats submit translations, the system would try to figure out whether it should be a 'patch' or a 'change', and then would either create a patch for an admin or artisan to review and accept or reject, or would apply the changes immediately and they would be live. This was done as a compromise between getting translations live quickly, but also preventing already-translated text from getting overwritten without oversight. But having the client handle this added logical complexity. So this makes all diplomats submit patches, no matter what. The server is then in charge of deciding if it should auto-accept the patch or not. Either way, a patch is created. There was also much refactoring. This commit includes: * Update jsondiffpatch so changes within array items are handled correctly * Refactor posting patches to use the new auto-accepting logic, and out of Patch model * Refactor POST /db/patch/:handle/status so that it doesn't rely on handlers * Refactor patch stat handling to ensure auto-accepted patches are counted * Refactor User.incrementStat to use mongodb update commands, to avoid race conditions * Refactor Patch tests
84 lines
3.1 KiB
CoffeeScript
84 lines
3.1 KiB
CoffeeScript
errors = require '../commons/errors'
|
|
log = require 'winston'
|
|
wrap = require 'co-express'
|
|
database = require '../commons/database'
|
|
mongoose = require 'mongoose'
|
|
Campaign = require '../models/Campaign'
|
|
CourseInstance = require '../models/CourseInstance'
|
|
Classroom = require '../models/Classroom'
|
|
Course = require '../models/Course'
|
|
User = require '../models/User'
|
|
Level = require '../models/Level'
|
|
parse = require '../commons/parse'
|
|
|
|
module.exports =
|
|
|
|
fetchLevelSolutions: wrap (req, res) ->
|
|
unless req.user?.isTeacher() or req.user?.isAdmin()
|
|
log.debug "courses.fetchLevelSolutions: level solutions only for teachers, (#{req.user?.id})"
|
|
throw new errors.Forbidden()
|
|
|
|
course = yield database.getDocFromHandle(req, Course)
|
|
throw new errors.NotFound('Course not found.') unless course
|
|
|
|
campaign = yield Campaign.findById course.get('campaignID')
|
|
throw new errors.NotFound('Campaign not found.') unless campaign
|
|
|
|
# TODO: why does campaign.get('levels') return opposite order from direct db query?
|
|
sortedLevelIDs = _.keys campaign.get('levels')
|
|
sortedLevelIDs.reverse()
|
|
|
|
levelOriginals = (mongoose.Types.ObjectId(levelID) for levelID in sortedLevelIDs)
|
|
query = { original: { $in: levelOriginals }, slug: { $exists: true }}
|
|
select = {documentation: 1, intro: 1, name: 1, original: 1, practice: 1, slug: 1, thangs: 1, i18n: 1}
|
|
levels = yield Level.find(query).select(select).lean()
|
|
levels.sort((a, b) -> sortedLevelIDs.indexOf(a.original + '') - sortedLevelIDs.indexOf(b.original + ''))
|
|
res.status(200).send(levels)
|
|
|
|
fetchNextLevel: wrap (req, res) ->
|
|
levelOriginal = req.params.levelOriginal
|
|
if not database.isID(levelOriginal)
|
|
throw new errors.UnprocessableEntity('Invalid level original ObjectId')
|
|
|
|
course = yield database.getDocFromHandle(req, Course)
|
|
if not course
|
|
throw new errors.NotFound('Course not found.')
|
|
|
|
campaign = yield Campaign.findById course.get('campaignID')
|
|
if not campaign
|
|
throw new errors.NotFound('Campaign not found.')
|
|
|
|
levels = _.values(campaign.get('levels'))
|
|
levels = _.sortBy(levels, 'campaignIndex')
|
|
|
|
nextLevelOriginal = null
|
|
foundLevelOriginal = false
|
|
for level, index in levels
|
|
if level.original.toString() is levelOriginal
|
|
foundLevelOriginal = true
|
|
nextLevelOriginal = levels[index+1]?.original
|
|
break
|
|
|
|
if not foundLevelOriginal
|
|
throw new errors.NotFound('Level original ObjectId not found in that course')
|
|
|
|
if not nextLevelOriginal
|
|
return res.status(200).send({})
|
|
|
|
dbq = Level.findOne({original: mongoose.Types.ObjectId(nextLevelOriginal)})
|
|
|
|
dbq.sort({ 'version.major': -1, 'version.minor': -1 })
|
|
dbq.select(parse.getProjectFromReq(req))
|
|
level = yield dbq
|
|
level = level.toObject({req: req})
|
|
res.status(200).send(level)
|
|
|
|
get: (Model, options={}) -> wrap (req, res) ->
|
|
query = {}
|
|
if req.query.releasePhase
|
|
query.releasePhase = req.query.releasePhase
|
|
dbq = Model.find(query)
|
|
dbq.select(parse.getProjectFromReq(req))
|
|
results = yield database.viewSearch(dbq, req)
|
|
results = Course.sortCourses results
|
|
res.send(results)
|