mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Merge pull request #3011 from darvelo/validations
Add Validations Layer and Post Validations
This commit is contained in:
commit
bb88b3664f
7 changed files with 126 additions and 25 deletions
|
@ -23,7 +23,9 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
self.notifications.showSuccess('Successfully converted to ' + (val ? 'static page' : 'post'));
|
self.notifications.showSuccess('Successfully converted to ' + (val ? 'static page' : 'post'));
|
||||||
|
|
||||||
return self.get('page');
|
return self.get('page');
|
||||||
}, this.notifications.showErrors);
|
}, function (errors) {
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.get('page');
|
return this.get('page');
|
||||||
|
@ -103,7 +105,7 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
|
|
||||||
// Because the server transforms the candidate slug by stripping
|
// Because the server transforms the candidate slug by stripping
|
||||||
// certain characters and appending a number onto the end of slugs
|
// certain characters and appending a number onto the end of slugs
|
||||||
// to enforce uniqueness, there are cases where we can get back a
|
// to enforce uniqueness, there are cases where we can get back a
|
||||||
// candidate slug that is a duplicate of the original except for
|
// candidate slug that is a duplicate of the original except for
|
||||||
// the trailing incrementor (e.g., this-is-a-slug and this-is-a-slug-2)
|
// the trailing incrementor (e.g., this-is-a-slug and this-is-a-slug-2)
|
||||||
|
|
||||||
|
@ -135,7 +137,9 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
return self.get('model').save().then(function () {
|
return self.get('model').save().then(function () {
|
||||||
self.notifications.showSuccess('Permalink successfully changed to <strong>' +
|
self.notifications.showSuccess('Permalink successfully changed to <strong>' +
|
||||||
self.get('slug') + '</strong>.');
|
self.get('slug') + '</strong>.');
|
||||||
}, self.notifications.showErrors);
|
}, function (errors) {
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -183,12 +187,12 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
//Validation complete
|
//Validation complete
|
||||||
this.set('published_at', newPublishedAt);
|
this.set('published_at', newPublishedAt);
|
||||||
|
|
||||||
//@ TODO: Make sure we're saving ONLY the publish date here,
|
this.get('model').save().then(function () {
|
||||||
// Don't want to accidentally save text the user's been working on.
|
|
||||||
this.get('model').save('published_at').then(function () {
|
|
||||||
self.notifications.showSuccess('Publish date successfully changed to <strong>' +
|
self.notifications.showSuccess('Publish date successfully changed to <strong>' +
|
||||||
formatDate(self.get('published_at')) + '</strong>.');
|
formatDate(self.get('published_at')) + '</strong>.');
|
||||||
}, this.notifications.showErrors);
|
}, function (errors) {
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,8 +9,8 @@ var PostController = Ember.ObjectController.extend({
|
||||||
|
|
||||||
this.get('model').save().then(function () {
|
this.get('model').save().then(function () {
|
||||||
self.notifications.showSuccess('Post successfully marked as ' + (featured ? 'featured' : 'not featured') + '.');
|
self.notifications.showSuccess('Post successfully marked as ' + (featured ? 'featured' : 'not featured') + '.');
|
||||||
}).catch(function () {
|
}).catch(function (errors) {
|
||||||
self.notifications.showError('An error occured while saving the post.');
|
self.notifications.showErrors(errors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,22 +109,26 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, {
|
||||||
actions: {
|
actions: {
|
||||||
save: function () {
|
save: function () {
|
||||||
var status = this.get('willPublish') ? 'published' : 'draft',
|
var status = this.get('willPublish') ? 'published' : 'draft',
|
||||||
|
model = this.get('model'),
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
// set markdown equal to what's in the editor, minus the image markers.
|
// set markdown equal to what's in the editor, minus the image markers.
|
||||||
this.set('markdown', this.getMarkdown().withoutMarkers);
|
this.set('markdown', this.getMarkdown().withoutMarkers);
|
||||||
|
|
||||||
this.set('status', status);
|
this.set('status', status);
|
||||||
return this.get('model').save().then(function (model) {
|
|
||||||
|
return model.save().then(function () {
|
||||||
model.updateTags();
|
model.updateTags();
|
||||||
// `updateTags` triggers `isDirty => true`.
|
// `updateTags` triggers `isDirty => true`.
|
||||||
// for a saved model it would otherwise be false.
|
// for a saved model it would otherwise be false.
|
||||||
self.set('isDirty', false);
|
self.set('isDirty', false);
|
||||||
|
|
||||||
self.notifications.showSuccess('Post status saved as <strong>' +
|
self.notifications.showSuccess('Post status saved as <strong>' +
|
||||||
model.get('status') + '</strong>.');
|
model.get('status') + '</strong>.');
|
||||||
return model;
|
return model;
|
||||||
}, this.notifications.showErrors);
|
}, function (errors) {
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setSaveType: function (newType) {
|
setSaveType: function (newType) {
|
||||||
|
|
69
core/client/mixins/validation-engine.js
Normal file
69
core/client/mixins/validation-engine.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { getRequestErrorMessage } from 'ghost/utils/ajax';
|
||||||
|
|
||||||
|
import ValidatorExtensions from 'ghost/utils/validator-extensions';
|
||||||
|
import PostValidator from 'ghost/validators/post';
|
||||||
|
|
||||||
|
ValidatorExtensions.init();
|
||||||
|
|
||||||
|
var ValidationEngine = Ember.Mixin.create({
|
||||||
|
validators: {
|
||||||
|
post: PostValidator
|
||||||
|
},
|
||||||
|
|
||||||
|
validate: function () {
|
||||||
|
var self = this,
|
||||||
|
type = this.get('validationType'),
|
||||||
|
validator = this.get('validators.' + type);
|
||||||
|
|
||||||
|
return new Ember.RSVP.Promise(function (resolve, reject) {
|
||||||
|
if (!type || !validator) {
|
||||||
|
return reject('The validator specified, "' + type + '", did not exist!');
|
||||||
|
}
|
||||||
|
|
||||||
|
var validationErrors = validator.validate(self);
|
||||||
|
|
||||||
|
if (Ember.isEmpty(validationErrors)) {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return reject(validationErrors);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// override save to do validation first
|
||||||
|
save: function () {
|
||||||
|
var self = this,
|
||||||
|
// this is a hack, but needed for async _super calls.
|
||||||
|
// ref: https://github.com/emberjs/ember.js/pull/4301
|
||||||
|
_super = this.__nextSuper;
|
||||||
|
|
||||||
|
// If validation fails, reject with validation errors.
|
||||||
|
// If save to the server fails, reject with server response.
|
||||||
|
return this.validate().then(function () {
|
||||||
|
return _super.call(self);
|
||||||
|
}).catch(function (result) {
|
||||||
|
var message = 'There was an error saving this ' + self.get('validationType');
|
||||||
|
|
||||||
|
if (Ember.isArray(result)) {
|
||||||
|
// get validation error messages
|
||||||
|
message += ': ' + result.mapBy('message').join(' ');
|
||||||
|
} else if (typeof result === 'object') {
|
||||||
|
// Get messages from server response
|
||||||
|
message += ': ' + getRequestErrorMessage(result);
|
||||||
|
} else if (typeof result === 'string') {
|
||||||
|
message += ': ' + result;
|
||||||
|
} else {
|
||||||
|
message += '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// set format for notifications.showErrors
|
||||||
|
message = [{ message: message }];
|
||||||
|
|
||||||
|
return new Ember.RSVP.Promise(function (resolve, reject) {
|
||||||
|
reject(message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ValidationEngine;
|
|
@ -1,4 +1,8 @@
|
||||||
var Post = DS.Model.extend({
|
import ValidationEngine from 'ghost/mixins/validation-engine';
|
||||||
|
|
||||||
|
var Post = DS.Model.extend(ValidationEngine, {
|
||||||
|
validationType: 'post',
|
||||||
|
|
||||||
uuid: DS.attr('string'),
|
uuid: DS.attr('string'),
|
||||||
title: DS.attr('string'),
|
title: DS.attr('string'),
|
||||||
slug: DS.attr('string'),
|
slug: DS.attr('string'),
|
||||||
|
@ -24,18 +28,6 @@ var Post = DS.Model.extend({
|
||||||
isPublished: Ember.computed.equal('status', 'published'),
|
isPublished: Ember.computed.equal('status', 'published'),
|
||||||
isDraft: Ember.computed.equal('status', 'draft'),
|
isDraft: Ember.computed.equal('status', 'draft'),
|
||||||
|
|
||||||
validate: function () {
|
|
||||||
var validationErrors = [];
|
|
||||||
|
|
||||||
if (!this.get('title.length')) {
|
|
||||||
validationErrors.push({
|
|
||||||
message: 'You must specify a title for the post.'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return validationErrors;
|
|
||||||
}.property('title'),
|
|
||||||
|
|
||||||
// remove client-generated tags, which have `id: null`.
|
// remove client-generated tags, which have `id: null`.
|
||||||
// Ember Data won't recognize/update them automatically
|
// Ember Data won't recognize/update them automatically
|
||||||
// when returned from the server with ids.
|
// when returned from the server with ids.
|
||||||
|
|
15
core/client/utils/validator-extensions.js
Normal file
15
core/client/utils/validator-extensions.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
function init() {
|
||||||
|
// Provide a few custom validators
|
||||||
|
//
|
||||||
|
validator.extend('empty', function (str) {
|
||||||
|
return Ember.isBlank(str);
|
||||||
|
});
|
||||||
|
|
||||||
|
validator.extend('notContains', function (str, badString) {
|
||||||
|
return !_.contains(str, badString);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: init
|
||||||
|
};
|
17
core/client/validators/post.js
Normal file
17
core/client/validators/post.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
var PostValidator = Ember.Object.create({
|
||||||
|
validate: function (model) {
|
||||||
|
var validationErrors = [],
|
||||||
|
|
||||||
|
title = model.get('title');
|
||||||
|
|
||||||
|
if (validator.empty(title)) {
|
||||||
|
validationErrors.push({
|
||||||
|
message: 'You must specify a title for the post.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationErrors;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default PostValidator;
|
Loading…
Add table
Reference in a new issue