diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee index 669899e6c..de1695490 100644 --- a/app/models/CocoModel.coffee +++ b/app/models/CocoModel.coffee @@ -1,5 +1,6 @@ storage = require 'lib/storage' deltasLib = require 'lib/deltas' +auth = require 'lib/auth' class CocoSchema extends Backbone.Model constructor: (path, args...) -> @@ -200,6 +201,8 @@ class CocoModel extends Backbone.Model hasReadAccess: (actor) -> # actor is a User object + actor ?= auth.me + return true if actor.isAdmin() if @get('permissions')? for permission in @get('permissions') if permission.target is 'public' or actor.get('_id') is permission.target @@ -210,6 +213,8 @@ class CocoModel extends Backbone.Model hasWriteAccess: (actor) -> # actor is a User object + actor ?= auth.me + return true if actor.isAdmin() if @get('permissions')? for permission in @get('permissions') if permission.target is 'public' or actor.get('_id') is permission.target diff --git a/app/models/Patch.coffee b/app/models/Patch.coffee new file mode 100644 index 000000000..a88c30941 --- /dev/null +++ b/app/models/Patch.coffee @@ -0,0 +1,5 @@ +CocoModel = require('./CocoModel') + +module.exports = class PatchModel extends CocoModel + @className: "Patch" + urlRoot: "/db/patch" \ No newline at end of file diff --git a/app/styles/modal/save_version.sass b/app/styles/modal/save_version.sass index 256a59a5e..e7ab79751 100644 --- a/app/styles/modal/save_version.sass +++ b/app/styles/modal/save_version.sass @@ -1,6 +1,11 @@ #save-version-modal .modal-body padding: 10px 50px 30px 20px + + .modal-footer + text-align: left + .buttons + text-align: right #cla-link cursor: pointer diff --git a/app/templates/modal/save_version.jade b/app/templates/modal/save_version.jade index ebeb7d352..7fcfd871d 100644 --- a/app/templates/modal/save_version.jade +++ b/app/templates/modal/save_version.jade @@ -1,30 +1,46 @@ extends /templates/modal/modal_base block modal-header-content - h3(data-i18n="versions.save_version_title") Save New Version + if isPatch + h3(data-i18n="versions.submit_patch_title") Submit Patch + else + h3(data-i18n="versions.save_version_title") Save New Version block modal-body-content - .changes-stub - form.form-inline - .form-group.commit-message - input.form-control#commit-message(name="commitMessage", type="text", placeholder="Commit Message") - .checkbox - label - input#major-version(name="version-is-major", type="checkbox") - | Major Changes + if hasChanges + .changes-stub + form.form-inline + .form-group.commit-message + input.form-control#commit-message(name="commitMessage", type="text", placeholder="Commit Message") + if !isPatch + .checkbox + label + input#major-version(name="version-is-major", type="checkbox") + | Major Changes + else + .alert.alert-danger No changes block modal-body-wait-content - h3(data-i18n="common.saving") Saving... + if hasChanges + if isPatch + h3(data-i18n="versions.submitting_patch") Submitting Patch... + else + h3(data-i18n="common.saving") Saving... block modal-footer-content - if !noSaveButton + if hasChanges #accept-cla-wrapper.alert.alert-info span(data-i18n="versions.cla_prefix") To save changes, first you must agree to our | strong#cla-link(data-i18n="versions.cla_url") CLA span(data-i18n="versions.cla_suffix") . - button.btn#agreement-button(data-i18n="versions.cla_agree") I AGREE + button.btn.btn-sm#agreement-button(data-i18n="versions.cla_agree") I AGREE + if isPatch + .alert.alert-info An owner will need to approve it before your changes will become visible. - button.btn(data-dismiss="modal", data-i18n="common.cancel") Cancel - if !noSaveButton - button.btn.btn-primary#save-version-button(data-i18n="common.save") Save + .buttons + button.btn(data-dismiss="modal", data-i18n="common.cancel") Cancel + if hasChanges && !isPatch + button.btn.btn-primary#save-version-button(data-i18n="common.save") Save + if hasChanges && isPatch + button.btn.btn-primary#submit-patch-button(data-i18n="versions.submit_patch") Submit Patch \ No newline at end of file diff --git a/app/views/admin/users_view.coffee b/app/views/admin/users_view.coffee index c19c7bd37..acc9a8152 100644 --- a/app/views/admin/users_view.coffee +++ b/app/views/admin/users_view.coffee @@ -38,8 +38,7 @@ module.exports = class UsersView extends View @users.fetch() @listenTo(@users, 'all', @render) - getRenderData: => + getRenderData: -> c = super() c.users = (user.attributes for user in @users.models) - console.log('our render data', c) c \ No newline at end of file diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/save_view.coffee index b2a6874db..33d94370b 100644 --- a/app/views/editor/level/save_view.coffee +++ b/app/views/editor/level/save_view.coffee @@ -25,7 +25,7 @@ module.exports = class LevelSaveView extends SaveVersionModal context.levelNeedsSave = @level.hasLocalChanges() context.modifiedComponents = _.filter @supermodel.getModels(LevelComponent), @shouldSaveEntity context.modifiedSystems = _.filter @supermodel.getModels(LevelSystem), @shouldSaveEntity - context.noSaveButton = not (context.levelNeedsSave or context.modifiedComponents.length or context.modifiedSystems.length) + context.hasChanges = (context.levelNeedsSave or context.modifiedComponents.length or context.modifiedSystems.length) @lastContext = context context diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/save_version_modal.coffee index 826ac06ed..db4c45de3 100644 --- a/app/views/modal/save_version_modal.coffee +++ b/app/views/modal/save_version_modal.coffee @@ -1,6 +1,8 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/modal/save_version' DeltaView = require 'views/editor/delta' +Patch = require 'models/Patch' +forms = require 'lib/forms' module.exports = class SaveVersionModal extends ModalView id: 'save-version-modal' @@ -11,15 +13,23 @@ module.exports = class SaveVersionModal extends ModalView 'click #save-version-button': 'onClickSaveButton' 'click #cla-link': 'onClickCLALink' 'click #agreement-button': 'onAgreedToCLA' + 'click #submit-patch-button': 'onClickPatchButton' constructor: (options) -> super options @model = options.model + new Patch() + @isPatch = not @model.hasWriteAccess() + + getRenderData: -> + c = super() + c.isPatch = @isPatch + c.hasChanges = @model.hasLocalChanges() + c afterRender: -> super() @$el.find(if me.get('signedCLA') then '#accept-cla-wrapper' else '#save-version-button').hide() - return unless @model changeEl = @$el.find('.changes-stub') deltaView = new DeltaView({model:@model}) @insertSubView(deltaView, changeEl) @@ -30,6 +40,27 @@ module.exports = class SaveVersionModal extends ModalView commitMessage: @$el.find('#commit-message').val() } + onClickPatchButton: -> + forms.clearFormAlerts @$el + patch = new Patch() + patch.set 'delta', @model.getDelta() + patch.set 'commitMessage', @$el.find('#commit-message').val() + patch.set 'target', { + 'collection': _.string.underscored @model.constructor.className + 'id': @model.id + } + errors = patch.validate() + forms.applyErrorsToForm(@$el, errors) if errors + res = patch.save() + return unless res + @enableModalInProgress(@$el) + + res.error => + @disableModalInProgress(@$el) + + res.success => + @hide() + onClickCLALink: -> window.open('/cla', 'cla', 'height=800,width=900') diff --git a/server/patches/patch_handler.coffee b/server/patches/patch_handler.coffee index a9a26e05b..c38068ae5 100644 --- a/server/patches/patch_handler.coffee +++ b/server/patches/patch_handler.coffee @@ -7,7 +7,7 @@ mongoose = require('mongoose') PatchHandler = class PatchHandler extends Handler modelClass: Patch editableProperties: [] - postEditableProperties: ['delta', 'target'] + postEditableProperties: ['delta', 'target', 'commitMessage'] jsonSchema: require './patch_schema' makeNewInstance: (req) -> diff --git a/server/patches/patch_schema.coffee b/server/patches/patch_schema.coffee index 7e02f4b8a..eae980d4e 100644 --- a/server/patches/patch_schema.coffee +++ b/server/patches/patch_schema.coffee @@ -2,10 +2,9 @@ c = require '../commons/schemas' patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article'] -PatchSchema = c.object({title:'Patch', required:['target', 'delta']}, { +PatchSchema = c.object({title:'Patch', required:['target', 'delta', 'commitMessage']}, { delta: { title: 'Delta', type:['array', 'object'] } - title: c.shortString() - description: c.shortString({maxLength: 500}) + commitMessage: c.shortString({maxLength: 500, minLength: 1}) creator: c.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}]) created: c.date( { title: 'Created', readOnly: true }) status: { enum: ['pending', 'accepted', 'rejected', 'withdrawn']} diff --git a/test/server/functional/patch.spec.coffee b/test/server/functional/patch.spec.coffee index b9875a814..d8694baf0 100644 --- a/test/server/functional/patch.spec.coffee +++ b/test/server/functional/patch.spec.coffee @@ -14,6 +14,7 @@ describe '/db/patch', -> patchURL = getURL('/db/patch') patches = {} patch = + commitMessage: 'Accept this patch!' delta: {name:['test']} target: id:null