mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Modify courses i18n edit view to be less error-prone
* Do not use 'backup' system * Warn when about to lose changes * Show list of patches and their statuses
This commit is contained in:
parent
ae28223b96
commit
09a9358b9e
7 changed files with 112 additions and 29 deletions
|
@ -3,3 +3,9 @@ CocoCollection = require 'collections/CocoCollection'
|
|||
|
||||
module.exports = class Patches extends CocoCollection
|
||||
model: PatchModel
|
||||
|
||||
fetchMineFor: (targetModel, options={}) ->
|
||||
options.url = "#{_.result(targetModel, 'url')}/patches"
|
||||
options.data ?= {}
|
||||
options.data.creator = me.id
|
||||
@fetch(options)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#patch-submit
|
||||
margin-top: 5px
|
||||
|
||||
td
|
||||
.translation-table td
|
||||
width: 40%
|
||||
|
||||
.outer-content
|
||||
|
@ -11,3 +11,12 @@
|
|||
|
||||
select
|
||||
margin-bottom: 10px
|
||||
|
||||
td.accepted
|
||||
background: lightgreen
|
||||
|
||||
td.rejected, td.withdrawn
|
||||
background: pink
|
||||
|
||||
td.pending
|
||||
background: lightyellow
|
||||
|
|
|
@ -2,7 +2,7 @@ extends /templates/core/modal-base
|
|||
|
||||
block modal-header-content
|
||||
.modal-header-content
|
||||
h3(data-i18n="resources.patch") Patch
|
||||
h3(data-i18n="resources.patch")
|
||||
|
||||
block modal-body-content
|
||||
.modal-body
|
||||
|
@ -14,12 +14,12 @@ block modal-body-content
|
|||
|
||||
block modal-footer
|
||||
.modal-footer
|
||||
button(data-dismiss="modal", data-i18n="common.cancel").btn Cancel
|
||||
button(data-dismiss="modal", data-i18n="common.cancel").btn
|
||||
if isPatchCreator
|
||||
if status != 'withdrawn'
|
||||
button.btn.btn-danger#withdraw-button(data-i18n="general.withdraw") Withdraw
|
||||
button.btn.btn-danger#withdraw-button(data-i18n="general.withdraw")
|
||||
if isPatchRecipient
|
||||
if status != 'accepted'
|
||||
button.btn.btn-primary#accept-button(data-i18n="general.accept") Accept
|
||||
button.btn.btn-primary#accept-button(data-i18n="general.accept")
|
||||
if status != 'rejected'
|
||||
button.btn.btn-danger#reject-button(data-i18n="general.reject") Reject
|
||||
button.btn.btn-danger#reject-button(data-i18n="general.reject")
|
||||
|
|
|
@ -50,23 +50,42 @@ block header
|
|||
a(data-toggle="coco-modal", data-target="core/ContactModal", data-i18n="nav.contact") Email
|
||||
|
||||
block outer_content
|
||||
.outer-content
|
||||
|
||||
.outer-content.container-fluid
|
||||
select.form-control#language-select
|
||||
.row
|
||||
|
||||
for row in translationList
|
||||
table.table
|
||||
tr
|
||||
th= row.title
|
||||
tr(data-format=row.format || '')
|
||||
td.english-value-row
|
||||
div= row.enValue
|
||||
tr(data-format=row.format || '')
|
||||
td.to-value-row
|
||||
if row.format === 'markdown'
|
||||
div(data-index=row.index.toString())= row.toValue
|
||||
else
|
||||
input.input-sm.form-control.translation-input(data-index=row.index.toString(), value=row.toValue)
|
||||
|
||||
.col-sm-6
|
||||
for row in translationList
|
||||
table.table.translation-table
|
||||
tr
|
||||
th= row.title
|
||||
tr(data-format=row.format || '')
|
||||
td.english-value-row
|
||||
div= row.enValue
|
||||
tr(data-format=row.format || '')
|
||||
td.to-value-row
|
||||
if row.format === 'markdown'
|
||||
div(data-index=row.index.toString())= row.toValue
|
||||
else
|
||||
input.input-sm.form-control.translation-input(data-index=row.index.toString(), value=row.toValue)
|
||||
|
||||
#patches-col.col-sm-6
|
||||
if view.patches
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
h3.panel-title Patches Submitted
|
||||
table.table
|
||||
tr
|
||||
th Description
|
||||
th Submitted
|
||||
th Status
|
||||
for patch in view.patches.models
|
||||
tr
|
||||
td
|
||||
a.open-patch-link(data-patch-id=patch.id)= patch.get('commitMessage')
|
||||
td= moment(patch.created()).format('LLLL')
|
||||
td(class=patch.get('status'))= patch.get('status')
|
||||
|
||||
|
||||
.clearfix
|
||||
block footer
|
||||
|
|
|
@ -2,10 +2,29 @@ I18NEditModelView = require './I18NEditModelView'
|
|||
Course = require 'models/Course'
|
||||
deltasLib = require 'core/deltas'
|
||||
Patch = require 'models/Patch'
|
||||
Patches = require 'collections/Patches'
|
||||
PatchModal = require 'views/editor/PatchModal'
|
||||
|
||||
# TODO: Apply these changes to all i18n views if it proves to be more reliable
|
||||
|
||||
module.exports = class I18NEditCourseView extends I18NEditModelView
|
||||
id: "i18n-edit-course-view"
|
||||
modelClass: Course
|
||||
|
||||
events:
|
||||
'click .open-patch-link': 'onClickOpenPatchLink'
|
||||
|
||||
constructor: ->
|
||||
super(arguments...)
|
||||
@model.saveBackups = false
|
||||
@madeChanges = false
|
||||
@patches = new Patches()
|
||||
@patches.comparator = '_id'
|
||||
@supermodel.trackRequest(@patches.fetchMineFor(@model))
|
||||
|
||||
onLoaded: ->
|
||||
super(arguments...)
|
||||
@originalModel = @model.clone()
|
||||
|
||||
buildTranslationList: ->
|
||||
lang = @selectedLanguage
|
||||
|
@ -17,6 +36,27 @@ module.exports = class I18NEditCourseView extends I18NEditModelView
|
|||
if description = @model.get('description')
|
||||
@wrapRow 'Course description', ['description'], description, i18n[lang]?.description, []
|
||||
|
||||
onTranslationChanged: ->
|
||||
super(arguments...)
|
||||
@madeChanges = true
|
||||
|
||||
onClickOpenPatchLink: (e) ->
|
||||
patchID = $(e.currentTarget).data('patch-id')
|
||||
patch = @patches.get(patchID)
|
||||
modal = new PatchModal(patch, @model)
|
||||
@openModalView(modal)
|
||||
|
||||
onLeaveMessage: ->
|
||||
if @madeChanges
|
||||
return 'You have unsaved changes!'
|
||||
|
||||
onLanguageSelectChanged: ->
|
||||
if @madeChanges
|
||||
return unless confirm('You have unsaved changes!')
|
||||
super(arguments...)
|
||||
@madeChanges = false
|
||||
@model.set(@originalModel.clone().attributes)
|
||||
|
||||
onSubmitPatch: (e) ->
|
||||
|
||||
delta = @model.getDelta()
|
||||
|
@ -42,6 +82,9 @@ module.exports = class I18NEditCourseView extends I18NEditModelView
|
|||
Promise.resolve(res)
|
||||
.then =>
|
||||
@savedBefore = true
|
||||
@madeChanges = false
|
||||
@patches.add(patch)
|
||||
@renderSelectors('#patches-col')
|
||||
button.text('Submit Changes')
|
||||
.catch =>
|
||||
button.text('Error Submitting Changes')
|
||||
|
|
|
@ -169,6 +169,9 @@ module.exports =
|
|||
dbq.findOne({ _id: handle })
|
||||
else
|
||||
dbq.findOne({ slug: handle })
|
||||
|
||||
if options.select
|
||||
dbq.select(options.select)
|
||||
|
||||
dbq.exec(done)
|
||||
|
||||
|
|
|
@ -8,22 +8,25 @@ database = require '../commons/database'
|
|||
parse = require '../commons/parse'
|
||||
|
||||
module.exports =
|
||||
patches: (options={}) -> wrap (req, res) ->
|
||||
patches: (Model, options={}) -> wrap (req, res) ->
|
||||
dbq = Patch.find()
|
||||
dbq.limit(parse.getLimitFromReq(req))
|
||||
dbq.skip(parse.getSkipFromReq(req))
|
||||
dbq.select(parse.getProjectFromReq(req))
|
||||
|
||||
id = req.params.handle
|
||||
if not database.isID(id)
|
||||
throw new errors.UnprocessableEntity('Invalid ID')
|
||||
doc = yield database.getDocFromHandle(req, Model, {_id: 1})
|
||||
if not doc
|
||||
throw new errors.NotFound('Patchable document not found')
|
||||
|
||||
query =
|
||||
$or: [
|
||||
{'target.original': id+''}
|
||||
{'target.original': mongoose.Types.ObjectId(id)}
|
||||
{'target.original': doc.id }
|
||||
{'target.original': doc._id }
|
||||
]
|
||||
status: req.query.status or 'pending'
|
||||
if req.query.status
|
||||
query.status = req.query.status
|
||||
if req.user and req.query.creator is req.user.id
|
||||
query.creator = req.user._id
|
||||
|
||||
patches = yield dbq.find(query).sort('-created')
|
||||
res.status(200).send(patches)
|
||||
|
|
Loading…
Reference in a new issue