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:
Scott Erickson 2016-08-23 14:36:45 -07:00
parent ae28223b96
commit 09a9358b9e
7 changed files with 112 additions and 29 deletions

View file

@ -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)

View file

@ -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

View file

@ -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")

View file

@ -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

View file

@ -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')

View file

@ -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)

View file

@ -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)