ESLint: Alias model in controllers
no issue - https://github.com/ember-cli/eslint-plugin-ember/blob/HEAD/docs/rules/alias-model-in-controller.md - replace `model` with a meaningful property name everywhere possible - refactor `design` and `general` settings controllers to use a directly injected settings service rather than passing it in as a "model" to be more explicit
This commit is contained in:
parent
a9fcddaf3f
commit
050f4d99b6
|
@ -1,7 +1,7 @@
|
|||
import Component from '@ember/component';
|
||||
import ValidationState from 'ghost-admin/mixins/validation-state';
|
||||
import {alias, readOnly} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {readOnly} from '@ember/object/computed';
|
||||
import {run} from '@ember/runloop';
|
||||
|
||||
export default Component.extend(ValidationState, {
|
||||
|
@ -10,7 +10,6 @@ export default Component.extend(ValidationState, {
|
|||
|
||||
new: false,
|
||||
|
||||
model: alias('navItem'),
|
||||
errors: readOnly('navItem.errors'),
|
||||
|
||||
errorClass: computed('hasError', function () {
|
||||
|
|
|
@ -25,25 +25,25 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
settings: service(),
|
||||
ui: service(),
|
||||
|
||||
model: null,
|
||||
post: null,
|
||||
|
||||
customExcerptScratch: alias('model.customExcerptScratch'),
|
||||
codeinjectionFootScratch: alias('model.codeinjectionFootScratch'),
|
||||
codeinjectionHeadScratch: alias('model.codeinjectionHeadScratch'),
|
||||
metaDescriptionScratch: alias('model.metaDescriptionScratch'),
|
||||
metaTitleScratch: alias('model.metaTitleScratch'),
|
||||
ogDescriptionScratch: alias('model.ogDescriptionScratch'),
|
||||
ogTitleScratch: alias('model.ogTitleScratch'),
|
||||
twitterDescriptionScratch: alias('model.twitterDescriptionScratch'),
|
||||
twitterTitleScratch: alias('model.twitterTitleScratch'),
|
||||
slugValue: boundOneWay('model.slug'),
|
||||
customExcerptScratch: alias('post.customExcerptScratch'),
|
||||
codeinjectionFootScratch: alias('post.codeinjectionFootScratch'),
|
||||
codeinjectionHeadScratch: alias('post.codeinjectionHeadScratch'),
|
||||
metaDescriptionScratch: alias('post.metaDescriptionScratch'),
|
||||
metaTitleScratch: alias('post.metaTitleScratch'),
|
||||
ogDescriptionScratch: alias('post.ogDescriptionScratch'),
|
||||
ogTitleScratch: alias('post.ogTitleScratch'),
|
||||
twitterDescriptionScratch: alias('post.twitterDescriptionScratch'),
|
||||
twitterTitleScratch: alias('post.twitterTitleScratch'),
|
||||
slugValue: boundOneWay('post.slug'),
|
||||
|
||||
facebookDescription: or('ogDescriptionScratch', 'customExcerptScratch', 'seoDescription'),
|
||||
facebookImage: or('model.ogImage', 'model.featureImage'),
|
||||
facebookImage: or('post.ogImage', 'post.featureImage'),
|
||||
facebookTitle: or('ogTitleScratch', 'seoTitle'),
|
||||
seoTitle: or('metaTitleScratch', 'model.titleScratch'),
|
||||
seoTitle: or('metaTitleScratch', 'post.titleScratch'),
|
||||
twitterDescription: or('twitterDescriptionScratch', 'customExcerptScratch', 'seoDescription'),
|
||||
twitterImage: or('model.twitterImage', 'model.featureImage'),
|
||||
twitterImage: or('post.twitterImage', 'post.featureImage'),
|
||||
twitterTitle: or('twitterTitleScratch', 'seoTitle'),
|
||||
|
||||
_showSettingsMenu: false,
|
||||
|
@ -63,7 +63,7 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
});
|
||||
|
||||
this.get('model.author').then((author) => {
|
||||
this.get('post.author').then((author) => {
|
||||
this.set('selectedAuthor', author);
|
||||
});
|
||||
|
||||
|
@ -77,7 +77,7 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
|
||||
// fired when menu is closed
|
||||
if (!this.get('showSettingsMenu') && this._showSettingsMenu) {
|
||||
let post = this.get('model');
|
||||
let post = this.get('post');
|
||||
let errors = post.get('errors');
|
||||
|
||||
// reset the publish date if it has an error
|
||||
|
@ -108,9 +108,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
this.set('_showThrobbers', true);
|
||||
}).restartable(),
|
||||
|
||||
seoDescription: computed('model.scratch', 'metaDescriptionScratch', function () {
|
||||
seoDescription: computed('post.scratch', 'metaDescriptionScratch', function () {
|
||||
let metaDescription = this.get('metaDescriptionScratch') || '';
|
||||
let mobiledoc = this.get('model.scratch');
|
||||
let mobiledoc = this.get('post.scratch');
|
||||
let markdown = mobiledoc.cards && mobiledoc.cards[0][1].markdown;
|
||||
let placeholder;
|
||||
|
||||
|
@ -129,9 +129,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
return placeholder;
|
||||
}),
|
||||
|
||||
seoURL: computed('model.slug', 'config.blogUrl', function () {
|
||||
seoURL: computed('post.slug', 'config.blogUrl', function () {
|
||||
let blogUrl = this.get('config.blogUrl');
|
||||
let seoSlug = this.get('model.slug') ? this.get('model.slug') : '';
|
||||
let seoSlug = this.get('post.slug') ? this.get('post.slug') : '';
|
||||
let seoURL = `${blogUrl}/${seoSlug}`;
|
||||
|
||||
// only append a slash to the URL if the slug exists
|
||||
|
@ -175,32 +175,32 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
togglePage() {
|
||||
this.toggleProperty('model.page');
|
||||
this.toggleProperty('post.page');
|
||||
|
||||
// If this is a new post. Don't save the model. Defer the save
|
||||
// If this is a new post. Don't save the post. Defer the save
|
||||
// to the user pressing the save button
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
toggleFeatured() {
|
||||
this.toggleProperty('model.featured');
|
||||
this.toggleProperty('post.featured');
|
||||
|
||||
// If this is a new post. Don't save the model. Defer the save
|
||||
// If this is a new post. Don't save the post. Defer the save
|
||||
// to the user pressing the save button
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -212,12 +212,12 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
.perform(newSlug)
|
||||
.catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
setPublishedAtBlogDate(date) {
|
||||
let post = this.get('model');
|
||||
let post = this.get('post');
|
||||
let dateString = moment(date).format('YYYY-MM-DD');
|
||||
|
||||
post.get('errors').remove('publishedAtBlogDate');
|
||||
|
@ -231,7 +231,7 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setPublishedAtBlogTime(time) {
|
||||
let post = this.get('model');
|
||||
let post = this.get('post');
|
||||
|
||||
post.get('errors').remove('publishedAtBlogDate');
|
||||
|
||||
|
@ -244,48 +244,48 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setCustomExcerpt(excerpt) {
|
||||
let model = this.get('model');
|
||||
let currentExcerpt = model.get('customExcerpt');
|
||||
let post = this.get('post');
|
||||
let currentExcerpt = post.get('customExcerpt');
|
||||
|
||||
if (excerpt === currentExcerpt) {
|
||||
return;
|
||||
}
|
||||
|
||||
model.set('customExcerpt', excerpt);
|
||||
post.set('customExcerpt', excerpt);
|
||||
|
||||
return model.validate({property: 'customExcerpt'}).then(() => this.get('savePost').perform());
|
||||
return post.validate({property: 'customExcerpt'}).then(() => this.get('savePost').perform());
|
||||
},
|
||||
|
||||
setHeaderInjection(code) {
|
||||
let model = this.get('model');
|
||||
let currentCode = model.get('codeinjectionHead');
|
||||
let post = this.get('post');
|
||||
let currentCode = post.get('codeinjectionHead');
|
||||
|
||||
if (code === currentCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
model.set('codeinjectionHead', code);
|
||||
post.set('codeinjectionHead', code);
|
||||
|
||||
return model.validate({property: 'codeinjectionHead'}).then(() => this.get('savePost').perform());
|
||||
return post.validate({property: 'codeinjectionHead'}).then(() => this.get('savePost').perform());
|
||||
},
|
||||
|
||||
setFooterInjection(code) {
|
||||
let model = this.get('model');
|
||||
let currentCode = model.get('codeinjectionFoot');
|
||||
let post = this.get('post');
|
||||
let currentCode = post.get('codeinjectionFoot');
|
||||
|
||||
if (code === currentCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
model.set('codeinjectionFoot', code);
|
||||
post.set('codeinjectionFoot', code);
|
||||
|
||||
return model.validate({property: 'codeinjectionFoot'}).then(() => this.get('savePost').perform());
|
||||
return post.validate({property: 'codeinjectionFoot'}).then(() => this.get('savePost').perform());
|
||||
},
|
||||
|
||||
setMetaTitle(metaTitle) {
|
||||
// Grab the model and current stored meta title
|
||||
let model = this.get('model');
|
||||
let currentTitle = model.get('metaTitle');
|
||||
// Grab the post and current stored meta title
|
||||
let post = this.get('post');
|
||||
let currentTitle = post.get('metaTitle');
|
||||
|
||||
// If the title entered matches the stored meta title, do nothing
|
||||
if (currentTitle === metaTitle) {
|
||||
|
@ -293,11 +293,11 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
|
||||
// If the title entered is different, set it as the new meta title
|
||||
model.set('metaTitle', metaTitle);
|
||||
post.set('metaTitle', metaTitle);
|
||||
|
||||
// Make sure the meta title is valid and if so, save it into the model
|
||||
return model.validate({property: 'metaTitle'}).then(() => {
|
||||
if (model.get('isNew')) {
|
||||
// Make sure the meta title is valid and if so, save it into the post
|
||||
return post.validate({property: 'metaTitle'}).then(() => {
|
||||
if (post.get('isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -306,9 +306,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setMetaDescription(metaDescription) {
|
||||
// Grab the model and current stored meta description
|
||||
let model = this.get('model');
|
||||
let currentDescription = model.get('metaDescription');
|
||||
// Grab the post and current stored meta description
|
||||
let post = this.get('post');
|
||||
let currentDescription = post.get('metaDescription');
|
||||
|
||||
// If the title entered matches the stored meta title, do nothing
|
||||
if (currentDescription === metaDescription) {
|
||||
|
@ -316,11 +316,11 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
|
||||
// If the title entered is different, set it as the new meta title
|
||||
model.set('metaDescription', metaDescription);
|
||||
post.set('metaDescription', metaDescription);
|
||||
|
||||
// Make sure the meta title is valid and if so, save it into the model
|
||||
return model.validate({property: 'metaDescription'}).then(() => {
|
||||
if (model.get('isNew')) {
|
||||
// Make sure the meta title is valid and if so, save it into the post
|
||||
return post.validate({property: 'metaDescription'}).then(() => {
|
||||
if (post.get('isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -329,9 +329,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setOgTitle(ogTitle) {
|
||||
// Grab the model and current stored facebook title
|
||||
let model = this.get('model');
|
||||
let currentTitle = model.get('ogTitle');
|
||||
// Grab the post and current stored facebook title
|
||||
let post = this.get('post');
|
||||
let currentTitle = post.get('ogTitle');
|
||||
|
||||
// If the title entered matches the stored facebook title, do nothing
|
||||
if (currentTitle === ogTitle) {
|
||||
|
@ -339,11 +339,11 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
|
||||
// If the title entered is different, set it as the new facebook title
|
||||
model.set('ogTitle', ogTitle);
|
||||
post.set('ogTitle', ogTitle);
|
||||
|
||||
// Make sure the facebook title is valid and if so, save it into the model
|
||||
return model.validate({property: 'ogTitle'}).then(() => {
|
||||
if (model.get('isNew')) {
|
||||
// Make sure the facebook title is valid and if so, save it into the post
|
||||
return post.validate({property: 'ogTitle'}).then(() => {
|
||||
if (post.get('isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -352,9 +352,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setOgDescription(ogDescription) {
|
||||
// Grab the model and current stored facebook description
|
||||
let model = this.get('model');
|
||||
let currentDescription = model.get('ogDescription');
|
||||
// Grab the post and current stored facebook description
|
||||
let post = this.get('post');
|
||||
let currentDescription = post.get('ogDescription');
|
||||
|
||||
// If the title entered matches the stored facebook description, do nothing
|
||||
if (currentDescription === ogDescription) {
|
||||
|
@ -362,11 +362,11 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
|
||||
// If the description entered is different, set it as the new facebook description
|
||||
model.set('ogDescription', ogDescription);
|
||||
post.set('ogDescription', ogDescription);
|
||||
|
||||
// Make sure the facebook description is valid and if so, save it into the model
|
||||
return model.validate({property: 'ogDescription'}).then(() => {
|
||||
if (model.get('isNew')) {
|
||||
// Make sure the facebook description is valid and if so, save it into the post
|
||||
return post.validate({property: 'ogDescription'}).then(() => {
|
||||
if (post.get('isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -375,9 +375,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setTwitterTitle(twitterTitle) {
|
||||
// Grab the model and current stored twitter title
|
||||
let model = this.get('model');
|
||||
let currentTitle = model.get('twitterTitle');
|
||||
// Grab the post and current stored twitter title
|
||||
let post = this.get('post');
|
||||
let currentTitle = post.get('twitterTitle');
|
||||
|
||||
// If the title entered matches the stored twitter title, do nothing
|
||||
if (currentTitle === twitterTitle) {
|
||||
|
@ -385,11 +385,11 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
|
||||
// If the title entered is different, set it as the new twitter title
|
||||
model.set('twitterTitle', twitterTitle);
|
||||
post.set('twitterTitle', twitterTitle);
|
||||
|
||||
// Make sure the twitter title is valid and if so, save it into the model
|
||||
return model.validate({property: 'twitterTitle'}).then(() => {
|
||||
if (model.get('isNew')) {
|
||||
// Make sure the twitter title is valid and if so, save it into the post
|
||||
return post.validate({property: 'twitterTitle'}).then(() => {
|
||||
if (post.get('isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -398,9 +398,9 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setTwitterDescription(twitterDescription) {
|
||||
// Grab the model and current stored twitter description
|
||||
let model = this.get('model');
|
||||
let currentDescription = model.get('twitterDescription');
|
||||
// Grab the post and current stored twitter description
|
||||
let post = this.get('post');
|
||||
let currentDescription = post.get('twitterDescription');
|
||||
|
||||
// If the description entered matches the stored twitter description, do nothing
|
||||
if (currentDescription === twitterDescription) {
|
||||
|
@ -408,11 +408,11 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
}
|
||||
|
||||
// If the description entered is different, set it as the new twitter description
|
||||
model.set('twitterDescription', twitterDescription);
|
||||
post.set('twitterDescription', twitterDescription);
|
||||
|
||||
// Make sure the twitter description is valid and if so, save it into the model
|
||||
return model.validate({property: 'twitterDescription'}).then(() => {
|
||||
if (model.get('isNew')) {
|
||||
// Make sure the twitter description is valid and if so, save it into the post
|
||||
return post.validate({property: 'twitterDescription'}).then(() => {
|
||||
if (post.get('isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -421,103 +421,103 @@ export default Component.extend(SettingsMenuMixin, {
|
|||
},
|
||||
|
||||
setCoverImage(image) {
|
||||
this.set('model.featureImage', image);
|
||||
this.set('post.featureImage', image);
|
||||
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
clearCoverImage() {
|
||||
this.set('model.featureImage', '');
|
||||
this.set('post.featureImage', '');
|
||||
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
setOgImage(image) {
|
||||
this.set('model.ogImage', image);
|
||||
this.set('post.ogImage', image);
|
||||
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
clearOgImage() {
|
||||
this.set('model.ogImage', '');
|
||||
this.set('post.ogImage', '');
|
||||
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
setTwitterImage(image) {
|
||||
this.set('model.twitterImage', image);
|
||||
this.set('post.twitterImage', image);
|
||||
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
clearTwitterImage() {
|
||||
this.set('model.twitterImage', '');
|
||||
this.set('post.twitterImage', '');
|
||||
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.get('model').rollbackAttributes();
|
||||
this.get('post').rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
changeAuthor(newAuthor) {
|
||||
let author = this.get('model.author');
|
||||
let model = this.get('model');
|
||||
let author = this.get('post.author');
|
||||
let post = this.get('post');
|
||||
|
||||
// return if nothing changed
|
||||
if (newAuthor.get('id') === author.get('id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
model.set('author', newAuthor);
|
||||
post.set('author', newAuthor);
|
||||
|
||||
// if this is a new post (never been saved before), don't try to save it
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('savePost').perform().catch((error) => {
|
||||
this.showError(error);
|
||||
this.set('selectedAuthor', author);
|
||||
model.rollbackAttributes();
|
||||
post.rollbackAttributes();
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ export default TextArea.extend({
|
|||
_editor: null,
|
||||
|
||||
// default SimpleMDE options, see docs for available config:
|
||||
// https://github.com/NextStepWebs/simplemde-markdown-editor#configuration
|
||||
// https://github.com/sparksuite/simplemde-markdown-editor#configuration
|
||||
defaultOptions: computed(function () {
|
||||
return {
|
||||
autofocus: this.get('autofocus'),
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import ModalComponent from 'ghost-admin/components/modal-base';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {A as emberA} from '@ember/array';
|
||||
import {isInvalidError} from 'ember-ajax/errors';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
export default ModalComponent.extend({
|
||||
|
||||
subscriber: alias('model'),
|
||||
|
||||
addSubscriber: task(function* () {
|
||||
try {
|
||||
yield this.get('confirm')();
|
||||
|
@ -17,8 +20,8 @@ export default ModalComponent.extend({
|
|||
let {message} = firstError;
|
||||
|
||||
if (message && message.match(/email/i)) {
|
||||
this.get('model.errors').add('email', message);
|
||||
this.get('model.hasValidated').pushObject('email');
|
||||
this.get('subscriber.errors').add('email', message);
|
||||
this.get('subscriber.hasValidated').pushObject('email');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +35,9 @@ export default ModalComponent.extend({
|
|||
|
||||
actions: {
|
||||
updateEmail(newEmail) {
|
||||
this.set('model.email', newEmail);
|
||||
this.set('model.hasValidated', emberA());
|
||||
this.get('model.errors').clear();
|
||||
this.set('subscriber.email', newEmail);
|
||||
this.set('subscriber.hasValidated', emberA());
|
||||
this.get('subscriber.errors').clear();
|
||||
},
|
||||
|
||||
confirm() {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import Controller from '@ember/controller';
|
||||
import {computed} from '@ember/object';
|
||||
import {readOnly} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default Controller.extend({
|
||||
upgradeStatus: service(),
|
||||
|
||||
about: readOnly('model'),
|
||||
|
||||
copyrightYear: computed(function () {
|
||||
let date = new Date();
|
||||
return date.getFullYear();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import EditorControllerMixin from 'ghost-admin/mixins/editor-base-controller';
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import EditorControllerMixin from 'ghost-admin/mixins/editor-base-controller';
|
||||
|
||||
export default Controller.extend(EditorControllerMixin, {
|
||||
|
||||
});
|
||||
export default Controller.extend(EditorControllerMixin);
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
import Controller from '@ember/controller';
|
||||
import {computed} from '@ember/object';
|
||||
import {readOnly} from '@ember/object/computed';
|
||||
|
||||
export default Controller.extend({
|
||||
|
||||
error: readOnly('model'),
|
||||
stack: false,
|
||||
|
||||
code: computed('model.status', function () {
|
||||
return this.get('model.status') > 200 ? this.get('model.status') : 500;
|
||||
code: computed('error.status', function () {
|
||||
return this.get('error.status') > 200 ? this.get('error.status') : 500;
|
||||
}),
|
||||
|
||||
message: computed('model.statusText', function () {
|
||||
message: computed('error.statusText', function () {
|
||||
if (this.get('code') === 404) {
|
||||
return 'Page not found';
|
||||
}
|
||||
|
||||
return this.get('model.statusText') !== 'error' ? this.get('model.statusText') : 'Internal Server Error';
|
||||
return this.get('error.statusText') !== 'error' ? this.get('error.statusText') : 'Internal Server Error';
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller, {inject as controller} from '@ember/controller';
|
||||
import {readOnly} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Controller from '@ember/controller';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {get} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
@ -36,6 +37,8 @@ export default Controller.extend({
|
|||
session: service(),
|
||||
store: service(),
|
||||
|
||||
postsInfinityModel: alias('model'),
|
||||
|
||||
queryParams: ['type', 'author', 'tag', 'order'],
|
||||
type: null,
|
||||
author: null,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
|
||||
import {computed} from '@ember/object';
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
@ -7,12 +8,12 @@ export default Controller.extend({
|
|||
notifications: service(),
|
||||
settings: service(),
|
||||
|
||||
model: alias('settings.amp'),
|
||||
ampSettings: alias('settings.amp'),
|
||||
|
||||
leaveSettingsTransition: null,
|
||||
|
||||
save: task(function* () {
|
||||
let amp = this.get('model');
|
||||
let amp = this.get('ampSettings');
|
||||
let settings = this.get('settings');
|
||||
|
||||
settings.set('amp', amp);
|
||||
|
@ -27,7 +28,7 @@ export default Controller.extend({
|
|||
|
||||
actions: {
|
||||
update(value) {
|
||||
this.set('model', value);
|
||||
this.set('ampSettings', value);
|
||||
},
|
||||
|
||||
save() {
|
||||
|
@ -67,7 +68,7 @@ export default Controller.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
// roll back changes on model props
|
||||
// roll back changes on settings model
|
||||
settings.rollbackAttributes();
|
||||
|
||||
return transition.retry();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import boundOneWay from 'ghost-admin/utils/bound-one-way';
|
||||
import {empty} from '@ember/object/computed';
|
||||
|
@ -11,8 +12,8 @@ export default Controller.extend({
|
|||
notifications: service(),
|
||||
settings: service(),
|
||||
|
||||
model: boundOneWay('settings.slack.firstObject'),
|
||||
testNotificationDisabled: empty('model.url'),
|
||||
slackSettings: boundOneWay('settings.slack.firstObject'),
|
||||
testNotificationDisabled: empty('slackSettings.url'),
|
||||
|
||||
leaveSettingsTransition: null,
|
||||
slackArray: null,
|
||||
|
@ -23,7 +24,7 @@ export default Controller.extend({
|
|||
},
|
||||
|
||||
save: task(function* () {
|
||||
let slack = this.get('model');
|
||||
let slack = this.get('slackSettings');
|
||||
let settings = this.get('settings');
|
||||
let slackArray = this.get('slackArray');
|
||||
|
||||
|
@ -66,12 +67,12 @@ export default Controller.extend({
|
|||
|
||||
updateURL(value) {
|
||||
value = typeof value === 'string' ? value.trim() : value;
|
||||
this.set('model.url', value);
|
||||
this.get('model.errors').clear();
|
||||
this.set('slackSettings.url', value);
|
||||
this.get('slackSettings.errors').clear();
|
||||
},
|
||||
|
||||
triggerDirtyState() {
|
||||
let slack = this.get('model');
|
||||
let slack = this.get('slackSettings');
|
||||
let slackArray = this.get('slackArray');
|
||||
let settings = this.get('settings');
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
@ -7,14 +8,14 @@ export default Controller.extend({
|
|||
notifications: service(),
|
||||
settings: service(),
|
||||
|
||||
model: alias('settings.unsplash'),
|
||||
unsplashSettings: alias('settings.unsplash'),
|
||||
dirtyAttributes: null,
|
||||
rollbackValue: null,
|
||||
|
||||
leaveSettingsTransition: null,
|
||||
|
||||
save: task(function* () {
|
||||
let unsplash = this.get('model');
|
||||
let unsplash = this.get('unsplashSettings');
|
||||
let settings = this.get('settings');
|
||||
|
||||
try {
|
||||
|
@ -37,9 +38,9 @@ export default Controller.extend({
|
|||
|
||||
update(value) {
|
||||
if (!this.get('dirtyAttributes')) {
|
||||
this.set('rollbackValue', this.get('model.isActive'));
|
||||
this.set('rollbackValue', this.get('unsplashSettings.isActive'));
|
||||
}
|
||||
this.set('model.isActive', value);
|
||||
this.set('unsplashSettings.isActive', value);
|
||||
this.set('dirtyAttributes', true);
|
||||
},
|
||||
|
||||
|
@ -76,7 +77,7 @@ export default Controller.extend({
|
|||
}
|
||||
|
||||
// roll back changes on model props
|
||||
this.set('model.isActive', this.get('rollbackValue'));
|
||||
this.set('unsplashSettings.isActive', this.get('rollbackValue'));
|
||||
this.set('dirtyAttributes', false);
|
||||
this.set('rollbackValue', null);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
|
||||
export default Controller.extend({
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
export default Controller.extend({
|
||||
notifications: service(),
|
||||
settings: service(),
|
||||
|
||||
save: task(function* () {
|
||||
let notifications = this.get('notifications');
|
||||
|
||||
try {
|
||||
return yield this.get('model').save();
|
||||
return yield this.get('settings').save();
|
||||
} catch (error) {
|
||||
notifications.showAPIError(error, {key: 'code-injection.save'});
|
||||
throw error;
|
||||
|
@ -47,14 +49,14 @@ export default Controller.extend({
|
|||
|
||||
leaveSettings() {
|
||||
let transition = this.get('leaveSettingsTransition');
|
||||
let settings = this.get('model');
|
||||
let settings = this.get('settings');
|
||||
|
||||
if (!transition) {
|
||||
this.get('notifications').showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'});
|
||||
return;
|
||||
}
|
||||
|
||||
// roll back changes on model props
|
||||
// roll back changes on settings props
|
||||
settings.rollbackAttributes();
|
||||
|
||||
return transition.retry();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import $ from 'jquery';
|
||||
import Controller from '@ember/controller';
|
||||
import NavigationItem from 'ghost-admin/models/navigation-item';
|
||||
|
@ -14,6 +15,7 @@ export default Controller.extend({
|
|||
ghostPaths: service(),
|
||||
notifications: service(),
|
||||
session: service(),
|
||||
settings: service(),
|
||||
|
||||
newNavItem: null,
|
||||
|
||||
|
@ -35,7 +37,7 @@ export default Controller.extend({
|
|||
},
|
||||
|
||||
save: task(function* () {
|
||||
let navItems = this.get('model.navigation');
|
||||
let navItems = this.get('settings.navigation');
|
||||
let newNavItem = this.get('newNavItem');
|
||||
let notifications = this.get('notifications');
|
||||
let validationPromises = [];
|
||||
|
@ -51,7 +53,7 @@ export default Controller.extend({
|
|||
try {
|
||||
yield RSVP.all(validationPromises);
|
||||
this.set('dirtyAttributes', false);
|
||||
return yield this.get('model').save();
|
||||
return yield this.get('settings').save();
|
||||
} catch (error) {
|
||||
if (error) {
|
||||
notifications.showAPIError(error);
|
||||
|
@ -61,7 +63,7 @@ export default Controller.extend({
|
|||
}),
|
||||
|
||||
addNewNavItem() {
|
||||
let navItems = this.get('model.navigation');
|
||||
let navItems = this.get('settings.navigation');
|
||||
let newNavItem = this.get('newNavItem');
|
||||
|
||||
newNavItem.set('isNew', false);
|
||||
|
@ -111,7 +113,7 @@ export default Controller.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
let navItems = this.get('model.navigation');
|
||||
let navItems = this.get('settings.navigation');
|
||||
|
||||
navItems.removeObject(item);
|
||||
this.set('dirtyAttributes', true);
|
||||
|
@ -161,15 +163,15 @@ export default Controller.extend({
|
|||
|
||||
leaveSettings() {
|
||||
let transition = this.get('leaveSettingsTransition');
|
||||
let model = this.get('model');
|
||||
let settings = this.get('settings');
|
||||
|
||||
if (!transition) {
|
||||
this.get('notifications').showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'});
|
||||
return;
|
||||
}
|
||||
|
||||
// roll back changes on model props
|
||||
model.rollbackAttributes();
|
||||
// roll back changes on settings props
|
||||
settings.rollbackAttributes();
|
||||
this.set('dirtyAttributes', false);
|
||||
|
||||
return transition.retry();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import $ from 'jquery';
|
||||
import Controller from '@ember/controller';
|
||||
import randomPassword from 'ghost-admin/utils/random-password';
|
||||
|
@ -18,6 +19,7 @@ export default Controller.extend({
|
|||
ghostPaths: service(),
|
||||
notifications: service(),
|
||||
session: service(),
|
||||
settings: service(),
|
||||
|
||||
availableTimezones: null,
|
||||
iconExtensions: null,
|
||||
|
@ -28,31 +30,31 @@ export default Controller.extend({
|
|||
_scratchFacebook: null,
|
||||
_scratchTwitter: null,
|
||||
|
||||
isDatedPermalinks: computed('model.permalinks', {
|
||||
isDatedPermalinks: computed('settings.permalinks', {
|
||||
set(key, value) {
|
||||
this.set('model.permalinks', value ? '/:year/:month/:day/:slug/' : '/:slug/');
|
||||
this.set('settings.permalinks', value ? '/:year/:month/:day/:slug/' : '/:slug/');
|
||||
|
||||
let slugForm = this.get('model.permalinks');
|
||||
let slugForm = this.get('settings.permalinks');
|
||||
return slugForm !== '/:slug/';
|
||||
},
|
||||
|
||||
get() {
|
||||
let slugForm = this.get('model.permalinks');
|
||||
let slugForm = this.get('settings.permalinks');
|
||||
|
||||
return slugForm !== '/:slug/';
|
||||
}
|
||||
}),
|
||||
|
||||
generatePassword: observer('model.isPrivate', function () {
|
||||
this.get('model.errors').remove('password');
|
||||
if (this.get('model.isPrivate') && this.get('model.hasDirtyAttributes')) {
|
||||
this.get('model').set('password', randomPassword());
|
||||
generatePassword: observer('settings.isPrivate', function () {
|
||||
this.get('settings.errors').remove('password');
|
||||
if (this.get('settings.isPrivate') && this.get('settings.hasDirtyAttributes')) {
|
||||
this.get('settings').set('password', randomPassword());
|
||||
}
|
||||
}),
|
||||
|
||||
privateRSSUrl: computed('config.blogUrl', 'model.publicHash', function () {
|
||||
privateRSSUrl: computed('config.blogUrl', 'settings.publicHash', function () {
|
||||
let blogUrl = this.get('config.blogUrl');
|
||||
let publicHash = this.get('model.publicHash');
|
||||
let publicHash = this.get('settings.publicHash');
|
||||
|
||||
return `${blogUrl}/${publicHash}/rss`;
|
||||
}),
|
||||
|
@ -79,14 +81,14 @@ export default Controller.extend({
|
|||
let config = this.get('config');
|
||||
|
||||
try {
|
||||
let model = yield this.get('model').save();
|
||||
config.set('blogTitle', model.get('title'));
|
||||
let settings = yield this.get('settings').save();
|
||||
config.set('blogTitle', settings.get('title'));
|
||||
|
||||
// this forces the document title to recompute after
|
||||
// a blog title change
|
||||
this.send('collectTitleTokens', []);
|
||||
|
||||
return model;
|
||||
return settings;
|
||||
} catch (error) {
|
||||
if (error) {
|
||||
notifications.showAPIError(error, {key: 'settings.save'});
|
||||
|
@ -101,16 +103,16 @@ export default Controller.extend({
|
|||
},
|
||||
|
||||
setTimezone(timezone) {
|
||||
this.set('model.activeTimezone', timezone.name);
|
||||
this.set('settings.activeTimezone', timezone.name);
|
||||
},
|
||||
|
||||
removeImage(image) {
|
||||
// setting `null` here will error as the server treats it as "null"
|
||||
this.get('model').set(image, '');
|
||||
this.get('settings').set(image, '');
|
||||
},
|
||||
|
||||
updateImage(property, image, resetInput) {
|
||||
this.get('model').set(property, image);
|
||||
this.get('settings').set(property, image);
|
||||
resetInput();
|
||||
},
|
||||
|
||||
|
@ -131,13 +133,13 @@ export default Controller.extend({
|
|||
|
||||
/**
|
||||
* Fired after an image upload completes
|
||||
* @param {string} property - Property name to be set on `this.model`
|
||||
* @param {string} property - Property name to be set on `this.settings`
|
||||
* @param {UploadResult[]} results - Array of UploadResult objects
|
||||
* @return {string} The URL that was set on `this.model.property`
|
||||
* @return {string} The URL that was set on `this.settings.property`
|
||||
*/
|
||||
imageUploaded(property, results) {
|
||||
if (results[0]) {
|
||||
return this.get('model').set(property, results[0].url);
|
||||
return this.get('settings').set(property, results[0].url);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -167,31 +169,31 @@ export default Controller.extend({
|
|||
|
||||
leaveSettings() {
|
||||
let transition = this.get('leaveSettingsTransition');
|
||||
let model = this.get('model');
|
||||
let settings = this.get('settings');
|
||||
|
||||
if (!transition) {
|
||||
this.get('notifications').showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'});
|
||||
return;
|
||||
}
|
||||
|
||||
// roll back changes on model props
|
||||
model.rollbackAttributes();
|
||||
// roll back changes on settings props
|
||||
settings.rollbackAttributes();
|
||||
|
||||
return transition.retry();
|
||||
},
|
||||
|
||||
validateFacebookUrl() {
|
||||
let newUrl = this.get('_scratchFacebook');
|
||||
let oldUrl = this.get('model.facebook');
|
||||
let oldUrl = this.get('settings.facebook');
|
||||
let errMessage = '';
|
||||
|
||||
// reset errors and validation
|
||||
this.get('model.errors').remove('facebook');
|
||||
this.get('model.hasValidated').removeObject('facebook');
|
||||
this.get('settings.errors').remove('facebook');
|
||||
this.get('settings.hasValidated').removeObject('facebook');
|
||||
|
||||
if (newUrl === '') {
|
||||
// Clear out the Facebook url
|
||||
this.set('model.facebook', '');
|
||||
this.set('settings.facebook', '');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -218,36 +220,36 @@ export default Controller.extend({
|
|||
throw 'invalid url';
|
||||
}
|
||||
|
||||
this.set('model.facebook', '');
|
||||
this.set('settings.facebook', '');
|
||||
run.schedule('afterRender', this, function () {
|
||||
this.set('model.facebook', newUrl);
|
||||
this.set('settings.facebook', newUrl);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e === 'invalid url') {
|
||||
errMessage = 'The URL must be in a format like '
|
||||
+ 'https://www.facebook.com/yourPage';
|
||||
this.get('model.errors').add('facebook', errMessage);
|
||||
this.get('settings.errors').add('facebook', errMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
throw e;
|
||||
} finally {
|
||||
this.get('model.hasValidated').pushObject('facebook');
|
||||
this.get('settings.hasValidated').pushObject('facebook');
|
||||
}
|
||||
},
|
||||
|
||||
validateTwitterUrl() {
|
||||
let newUrl = this.get('_scratchTwitter');
|
||||
let oldUrl = this.get('model.twitter');
|
||||
let oldUrl = this.get('settings.twitter');
|
||||
let errMessage = '';
|
||||
|
||||
// reset errors and validation
|
||||
this.get('model.errors').remove('twitter');
|
||||
this.get('model.hasValidated').removeObject('twitter');
|
||||
this.get('settings.errors').remove('twitter');
|
||||
this.get('settings.hasValidated').removeObject('twitter');
|
||||
|
||||
if (newUrl === '') {
|
||||
// Clear out the Twitter url
|
||||
this.set('model.twitter', '');
|
||||
this.set('settings.twitter', '');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -269,24 +271,24 @@ export default Controller.extend({
|
|||
if (username.match(/^(http|www)|(\/)/) || !username.match(/^[a-z\d._]{1,15}$/mi)) {
|
||||
errMessage = !username.match(/^[a-z\d._]{1,15}$/mi) ? 'Your Username is not a valid Twitter Username' : 'The URL must be in a format like https://twitter.com/yourUsername';
|
||||
|
||||
this.get('model.errors').add('twitter', errMessage);
|
||||
this.get('model.hasValidated').pushObject('twitter');
|
||||
this.get('settings.errors').add('twitter', errMessage);
|
||||
this.get('settings.hasValidated').pushObject('twitter');
|
||||
return;
|
||||
}
|
||||
|
||||
newUrl = `https://twitter.com/${username}`;
|
||||
|
||||
this.get('model.hasValidated').pushObject('twitter');
|
||||
this.get('settings.hasValidated').pushObject('twitter');
|
||||
|
||||
this.set('model.twitter', '');
|
||||
this.set('settings.twitter', '');
|
||||
run.schedule('afterRender', this, function () {
|
||||
this.set('model.twitter', newUrl);
|
||||
this.set('settings.twitter', newUrl);
|
||||
});
|
||||
} else {
|
||||
errMessage = 'The URL must be in a format like '
|
||||
+ 'https://twitter.com/yourUsername';
|
||||
this.get('model.errors').add('twitter', errMessage);
|
||||
this.get('model.hasValidated').pushObject('twitter');
|
||||
this.get('settings.errors').add('twitter', errMessage);
|
||||
this.get('settings.hasValidated').pushObject('twitter');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import $ from 'jquery';
|
||||
import Controller from '@ember/controller';
|
||||
import Ember from 'ember';
|
||||
|
|
|
@ -6,13 +6,14 @@ export default Controller.extend({
|
|||
|
||||
tagController: controller('settings.tags.tag'),
|
||||
|
||||
tags: alias('model'),
|
||||
selectedTag: alias('tagController.tag'),
|
||||
|
||||
tagListFocused: equal('keyboardFocus', 'tagList'),
|
||||
tagContentFocused: equal('keyboardFocus', 'tagContent'),
|
||||
|
||||
// TODO: replace with ordering by page count once supported by the API
|
||||
sortedTags: sort('model', function (a, b) {
|
||||
sortedTags: sort('tags', function (a, b) {
|
||||
let idA = +a.get('id');
|
||||
let idB = +b.get('id');
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller, {inject as controller} from '@ember/controller';
|
||||
import {computed} from '@ember/object';
|
||||
import {match} from '@ember/object/computed';
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller, {inject as controller} from '@ember/controller';
|
||||
import DS from 'ember-data';
|
||||
import RSVP from 'rsvp';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* eslint-disable camelcase */
|
||||
/* eslint-disable camelcase, ghost/ember/alias-model-in-controller */
|
||||
import Controller, {inject as controller} from '@ember/controller';
|
||||
import RSVP from 'rsvp';
|
||||
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
|
||||
|
|
|
@ -2,6 +2,7 @@ import $ from 'jquery';
|
|||
import Controller, {inject as controller} from '@ember/controller';
|
||||
import RSVP from 'rsvp';
|
||||
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {isArray as isEmberArray} from '@ember/array';
|
||||
import {isVersionMismatchError} from 'ghost-admin/services/ajax';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
@ -21,6 +22,7 @@ export default Controller.extend(ValidationEngine, {
|
|||
settings: service(),
|
||||
|
||||
flowErrors: '',
|
||||
signin: alias('model'),
|
||||
|
||||
// ValidationEngine settings
|
||||
validationType: 'signin',
|
||||
|
@ -56,11 +58,11 @@ export default Controller.extend(ValidationEngine, {
|
|||
this.set('flowErrors', error.payload.errors[0].message.string);
|
||||
|
||||
if (error.payload.errors[0].message.string.match(/user with that email/)) {
|
||||
this.get('model.errors').add('identification', '');
|
||||
this.get('signin.errors').add('identification', '');
|
||||
}
|
||||
|
||||
if (error.payload.errors[0].message.string.match(/password is incorrect/)) {
|
||||
this.get('model.errors').add('password', '');
|
||||
this.get('signin.errors').add('password', '');
|
||||
}
|
||||
} else {
|
||||
// Connection errors don't return proper status message, only req.body
|
||||
|
@ -70,7 +72,7 @@ export default Controller.extend(ValidationEngine, {
|
|||
}).drop(),
|
||||
|
||||
validateAndAuthenticate: task(function* () {
|
||||
let model = this.get('model');
|
||||
let signin = this.get('signin');
|
||||
let authStrategy = 'authenticator:oauth2';
|
||||
|
||||
this.set('flowErrors', '');
|
||||
|
@ -84,14 +86,14 @@ export default Controller.extend(ValidationEngine, {
|
|||
try {
|
||||
yield this.validate({property: 'signin'});
|
||||
return yield this.get('authenticate')
|
||||
.perform(authStrategy, [model.get('identification'), model.get('password')]);
|
||||
.perform(authStrategy, [signin.get('identification'), signin.get('password')]);
|
||||
} catch (error) {
|
||||
this.set('flowErrors', 'Please fill out the form to sign in.');
|
||||
}
|
||||
}).drop(),
|
||||
|
||||
forgotten: task(function* () {
|
||||
let email = this.get('model.identification');
|
||||
let email = this.get('signin.identification');
|
||||
let forgottenUrl = this.get('ghostPaths.url').api('authentication', 'passwordreset');
|
||||
let notifications = this.get('notifications');
|
||||
|
||||
|
@ -123,7 +125,7 @@ export default Controller.extend(ValidationEngine, {
|
|||
this.set('flowErrors', message);
|
||||
|
||||
if (message.match(/no user with that email/)) {
|
||||
this.get('model.errors').add('identification', '');
|
||||
this.get('signin.errors').add('identification', '');
|
||||
}
|
||||
} else {
|
||||
notifications.showAPIError(error, {defaultErrorText: 'There was a problem with the reset, please try again.', key: 'forgot-password.send'});
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
VersionMismatchError,
|
||||
isVersionMismatchError
|
||||
} from 'ghost-admin/services/ajax';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {isArray as isEmberArray} from '@ember/array';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
@ -18,6 +19,7 @@ export default Controller.extend(ValidationEngine, {
|
|||
settings: service(),
|
||||
|
||||
// ValidationEngine settings
|
||||
signupDetails: alias('model'),
|
||||
validationType: 'signup',
|
||||
|
||||
flowErrors: '',
|
||||
|
@ -53,11 +55,11 @@ export default Controller.extend(ValidationEngine, {
|
|||
this.set('flowErrors', error.payload.errors[0].message.string);
|
||||
|
||||
if (error.payload.errors[0].message.string.match(/user with that email/)) {
|
||||
this.get('model.errors').add('identification', '');
|
||||
this.get('signupDetails.errors').add('email', '');
|
||||
}
|
||||
|
||||
if (error.payload.errors[0].message.string.match(/password is incorrect/)) {
|
||||
this.get('model.errors').add('password', '');
|
||||
this.get('signupDetails.errors').add('password', '');
|
||||
}
|
||||
} else {
|
||||
// Connection errors don't return proper status message, only req.body
|
||||
|
@ -103,24 +105,24 @@ export default Controller.extend(ValidationEngine, {
|
|||
|
||||
_completeInvitation() {
|
||||
let authUrl = this.get('ghostPaths.url').api('authentication', 'invitation');
|
||||
let model = this.get('model');
|
||||
let signupDetails = this.get('signupDetails');
|
||||
|
||||
return this.get('ajax').post(authUrl, {
|
||||
dataType: 'json',
|
||||
data: {
|
||||
invitation: [{
|
||||
name: model.get('name'),
|
||||
email: model.get('email'),
|
||||
password: model.get('password'),
|
||||
token: model.get('token')
|
||||
name: signupDetails.get('name'),
|
||||
email: signupDetails.get('email'),
|
||||
password: signupDetails.get('password'),
|
||||
token: signupDetails.get('token')
|
||||
}]
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_authenticateWithPassword() {
|
||||
let email = this.get('model.email');
|
||||
let password = this.get('model.password');
|
||||
let email = this.get('signupDetails.email');
|
||||
let password = this.get('signupDetails.password');
|
||||
|
||||
return this.get('session')
|
||||
.authenticate('authenticator:oauth2', email, password);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import $ from 'jquery';
|
||||
import Controller from '@ember/controller';
|
||||
import PaginationMixin from 'ghost-admin/mixins/pagination';
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {sort} from '@ember/object/computed';
|
||||
|
|
|
@ -36,8 +36,8 @@ export default Controller.extend({
|
|||
user: alias('model'),
|
||||
currentUser: alias('session.user'),
|
||||
|
||||
email: readOnly('model.email'),
|
||||
slugValue: boundOneWay('model.slug'),
|
||||
email: readOnly('user.email'),
|
||||
slugValue: boundOneWay('user.slug'),
|
||||
|
||||
canAssignRoles: or('currentUser.isAdmin', 'currentUser.isOwner'),
|
||||
canChangeEmail: not('isAdminUserOnOwnerProfile'),
|
||||
|
@ -170,17 +170,18 @@ export default Controller.extend({
|
|||
}
|
||||
|
||||
try {
|
||||
let model = yield user.save({format: false});
|
||||
let currentPath,
|
||||
newPath;
|
||||
|
||||
user = yield user.save({format: false});
|
||||
|
||||
// If the user's slug has changed, change the URL and replace
|
||||
// the history so refresh and back button still work
|
||||
if (slugChanged) {
|
||||
currentPath = window.location.hash;
|
||||
|
||||
newPath = currentPath.split('/');
|
||||
newPath[newPath.length - 1] = model.get('slug');
|
||||
newPath[newPath.length - 1] = user.get('slug');
|
||||
newPath = newPath.join('/');
|
||||
|
||||
windowProxy.replaceState({path: newPath}, '', newPath);
|
||||
|
@ -189,7 +190,7 @@ export default Controller.extend({
|
|||
this.set('dirtyAttributes', false);
|
||||
this.get('notifications').closeAlerts('user.update');
|
||||
|
||||
return model;
|
||||
return user;
|
||||
} catch (error) {
|
||||
// validation engine returns undefined so we have to check
|
||||
// before treating the failure as an API error
|
||||
|
@ -415,7 +416,7 @@ export default Controller.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
// roll back changes on model props
|
||||
// roll back changes on user props
|
||||
user.rollbackAttributes();
|
||||
// roll back the slugValue property
|
||||
if (this.get('dirtyAttributes')) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import boundOneWay from 'ghost-admin/utils/bound-one-way';
|
|||
import ghostPaths from 'ghost-admin/utils/ghost-paths';
|
||||
import isNumber from 'ghost-admin/utils/isNumber';
|
||||
import moment from 'moment';
|
||||
import {alias} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as controller} from '@ember/controller';
|
||||
import {htmlSafe} from '@ember/string';
|
||||
|
@ -17,8 +18,8 @@ import {inject as service} from '@ember/service';
|
|||
import {task, taskGroup, timeout} from 'ember-concurrency';
|
||||
|
||||
// this array will hold properties we need to watch
|
||||
// to know if the model has been changed (`controller.hasDirtyAttributes`)
|
||||
const watchedProps = ['model.scratch', 'model.titleScratch', 'model.hasDirtyAttributes', 'model.tags.[]'];
|
||||
// to know if the post has been changed (`controller.hasDirtyAttributes`)
|
||||
const watchedProps = ['post.scratch', 'post.titleScratch', 'post.hasDirtyAttributes', 'post.tags.[]'];
|
||||
|
||||
const DEFAULT_TITLE = '(Untitled)';
|
||||
|
||||
|
@ -28,11 +29,13 @@ const AUTOSAVE_TIMEOUT = 3000;
|
|||
const TIMEDSAVE_TIMEOUT = 60000;
|
||||
|
||||
PostModel.eachAttribute(function (name) {
|
||||
watchedProps.push(`model.${name}`);
|
||||
watchedProps.push(`post.${name}`);
|
||||
});
|
||||
|
||||
export default Mixin.create({
|
||||
|
||||
post: alias('model'),
|
||||
|
||||
showLeaveEditorModal: false,
|
||||
showReAuthenticateModal: false,
|
||||
showDeletePostModal: false,
|
||||
|
@ -64,8 +67,8 @@ export default Mixin.create({
|
|||
};
|
||||
},
|
||||
|
||||
_canAutosave: computed('model.isDraft', function () {
|
||||
return !Ember.testing && this.get('model.isDraft'); // eslint-disable-line
|
||||
_canAutosave: computed('post.isDraft', function () {
|
||||
return !Ember.testing && this.get('post.isDraft'); // eslint-disable-line
|
||||
}),
|
||||
|
||||
// save 3 seconds after the last edit
|
||||
|
@ -75,7 +78,7 @@ export default Mixin.create({
|
|||
}
|
||||
|
||||
// force an instant save on first body edit for new posts
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return this.get('autosave').perform();
|
||||
}
|
||||
|
||||
|
@ -122,8 +125,8 @@ export default Mixin.create({
|
|||
// save tasks cancels autosave before running, although this cancels the
|
||||
// _xSave tasks that will also cancel the autosave task
|
||||
save: task(function* (options = {}) {
|
||||
let prevStatus = this.get('model.status');
|
||||
let isNew = this.get('model.isNew');
|
||||
let prevStatus = this.get('post.status');
|
||||
let isNew = this.get('post.isNew');
|
||||
let status;
|
||||
|
||||
this.send('cancelAutosave');
|
||||
|
@ -139,9 +142,9 @@ export default Mixin.create({
|
|||
if (this.get('post.pastScheduledTime')) {
|
||||
status = (!this.get('willSchedule') && !this.get('willPublish')) ? 'draft' : 'published';
|
||||
} else {
|
||||
if (this.get('willPublish') && !this.get('model.isScheduled') && !this.get('statusFreeze')) {
|
||||
if (this.get('willPublish') && !this.get('post.isScheduled') && !this.get('statusFreeze')) {
|
||||
status = 'published';
|
||||
} else if (this.get('willSchedule') && !this.get('model.isPublished') && !this.get('statusFreeze')) {
|
||||
} else if (this.get('willSchedule') && !this.get('post.isPublished') && !this.get('statusFreeze')) {
|
||||
status = 'scheduled';
|
||||
} else {
|
||||
status = 'draft';
|
||||
|
@ -151,49 +154,49 @@ export default Mixin.create({
|
|||
|
||||
// Set the properties that are indirected
|
||||
// set mobiledoc equal to what's in the editor, minus the image markers.
|
||||
this.set('model.mobiledoc', this.get('model.scratch'));
|
||||
this.set('model.status', status);
|
||||
this.set('post.mobiledoc', this.get('post.scratch'));
|
||||
this.set('post.status', status);
|
||||
|
||||
// Set a default title
|
||||
if (!this.get('model.titleScratch').trim()) {
|
||||
this.set('model.titleScratch', DEFAULT_TITLE);
|
||||
if (!this.get('post.titleScratch').trim()) {
|
||||
this.set('post.titleScratch', DEFAULT_TITLE);
|
||||
}
|
||||
|
||||
this.set('model.title', this.get('model.titleScratch'));
|
||||
this.set('model.customExcerpt', this.get('model.customExcerptScratch'));
|
||||
this.set('model.footerInjection', this.get('model.footerExcerptScratch'));
|
||||
this.set('model.headerInjection', this.get('model.headerExcerptScratch'));
|
||||
this.set('model.metaTitle', this.get('model.metaTitleScratch'));
|
||||
this.set('model.metaDescription', this.get('model.metaDescriptionScratch'));
|
||||
this.set('model.ogTitle', this.get('model.ogTitleScratch'));
|
||||
this.set('model.ogDescription', this.get('model.ogDescriptionScratch'));
|
||||
this.set('model.twitterTitle', this.get('model.twitterTitleScratch'));
|
||||
this.set('model.twitterDescription', this.get('model.twitterDescriptionScratch'));
|
||||
this.set('post.title', this.get('post.titleScratch'));
|
||||
this.set('post.customExcerpt', this.get('post.customExcerptScratch'));
|
||||
this.set('post.footerInjection', this.get('post.footerExcerptScratch'));
|
||||
this.set('post.headerInjection', this.get('post.headerExcerptScratch'));
|
||||
this.set('post.metaTitle', this.get('post.metaTitleScratch'));
|
||||
this.set('post.metaDescription', this.get('post.metaDescriptionScratch'));
|
||||
this.set('post.ogTitle', this.get('post.ogTitleScratch'));
|
||||
this.set('post.ogDescription', this.get('post.ogDescriptionScratch'));
|
||||
this.set('post.twitterTitle', this.get('post.twitterTitleScratch'));
|
||||
this.set('post.twitterDescription', this.get('post.twitterDescriptionScratch'));
|
||||
|
||||
if (!this.get('model.slug')) {
|
||||
if (!this.get('post.slug')) {
|
||||
this.get('saveTitle').cancelAll();
|
||||
|
||||
yield this.get('generateSlug').perform();
|
||||
}
|
||||
|
||||
try {
|
||||
let model = yield this.get('model').save(options);
|
||||
let post = yield this.get('post').save(options);
|
||||
|
||||
if (!options.silent) {
|
||||
this.showSaveNotification(prevStatus, model.get('status'), isNew ? true : false);
|
||||
this.showSaveNotification(prevStatus, post.get('status'), isNew ? true : false);
|
||||
}
|
||||
|
||||
this.get('model').set('statusScratch', null);
|
||||
this.get('post').set('statusScratch', null);
|
||||
|
||||
// redirect to edit route if saving a new record
|
||||
if (isNew && model.get('id')) {
|
||||
if (isNew && post.get('id')) {
|
||||
if (!this.get('leaveEditorTransition')) {
|
||||
this.replaceRoute('editor.edit', model);
|
||||
this.replaceRoute('editor.edit', post);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return model;
|
||||
return post;
|
||||
} catch (error) {
|
||||
// re-throw if we have a general server error
|
||||
if (error && !isInvalidError(error)) {
|
||||
|
@ -201,16 +204,16 @@ export default Mixin.create({
|
|||
return;
|
||||
}
|
||||
|
||||
this.set('model.status', prevStatus);
|
||||
this.set('post.status', prevStatus);
|
||||
|
||||
if (!options.silent) {
|
||||
let errorOrMessages = error || this.get('model.errors.messages');
|
||||
this.showErrorAlert(prevStatus, this.get('model.status'), errorOrMessages);
|
||||
let errorOrMessages = error || this.get('post.errors.messages');
|
||||
this.showErrorAlert(prevStatus, this.get('post.status'), errorOrMessages);
|
||||
// simulate a validation error for upstream tasks
|
||||
throw undefined;
|
||||
}
|
||||
|
||||
return this.get('model');
|
||||
return this.get('post');
|
||||
}
|
||||
}).group('saveTasks'),
|
||||
|
||||
|
@ -218,7 +221,7 @@ export default Mixin.create({
|
|||
* triggered by a user manually changing slug
|
||||
*/
|
||||
updateSlug: task(function* (_newSlug) {
|
||||
let slug = this.get('model.slug');
|
||||
let slug = this.get('post.slug');
|
||||
let newSlug, serverSlug;
|
||||
|
||||
newSlug = _newSlug || slug;
|
||||
|
@ -259,25 +262,25 @@ export default Mixin.create({
|
|||
}
|
||||
}
|
||||
|
||||
this.set('model.slug', serverSlug);
|
||||
this.set('post.slug', serverSlug);
|
||||
|
||||
// If this is a new post. Don't save the model. Defer the save
|
||||
// If this is a new post. Don't save the post. Defer the save
|
||||
// to the user pressing the save button
|
||||
if (this.get('model.isNew')) {
|
||||
if (this.get('post.isNew')) {
|
||||
return;
|
||||
}
|
||||
|
||||
return yield this.get('model').save();
|
||||
return yield this.get('post').save();
|
||||
}).group('saveTasks'),
|
||||
|
||||
// used in the PSM so that saves are sequential and don't trigger collision
|
||||
// detection errors
|
||||
savePost: task(function* () {
|
||||
try {
|
||||
return yield this.get('model').save();
|
||||
return yield this.get('post').save();
|
||||
} catch (error) {
|
||||
if (error) {
|
||||
let status = this.get('model.status');
|
||||
let status = this.get('post.status');
|
||||
this.showErrorAlert(status, status, error);
|
||||
}
|
||||
|
||||
|
@ -290,24 +293,24 @@ export default Mixin.create({
|
|||
* Only with a user-set value (via setSaveType action)
|
||||
* can the post's status change.
|
||||
*/
|
||||
willPublish: boundOneWay('model.isPublished'),
|
||||
willSchedule: boundOneWay('model.isScheduled'),
|
||||
willPublish: boundOneWay('post.isPublished'),
|
||||
willSchedule: boundOneWay('post.isScheduled'),
|
||||
|
||||
// set by the editor route and `hasDirtyAttributes`. useful when checking
|
||||
// whether the number of tags has changed for `hasDirtyAttributes`.
|
||||
previousTagNames: null,
|
||||
|
||||
tagNames: mapBy('model.tags', 'name'),
|
||||
tagNames: mapBy('post.tags', 'name'),
|
||||
|
||||
postOrPage: computed('model.page', function () {
|
||||
return this.get('model.page') ? 'Page' : 'Post';
|
||||
postOrPage: computed('post.page', function () {
|
||||
return this.get('post.page') ? 'Page' : 'Post';
|
||||
}),
|
||||
|
||||
// countdown timer to show the time left until publish time for a scheduled post
|
||||
// starts 15 minutes before scheduled time
|
||||
scheduleCountdown: computed('model.{publishedAtUTC,isScheduled}', 'clock.second', function () {
|
||||
let isScheduled = this.get('model.isScheduled');
|
||||
let publishTime = this.get('model.publishedAtUTC') || moment.utc();
|
||||
scheduleCountdown: computed('post.{publishedAtUTC,isScheduled}', 'clock.second', function () {
|
||||
let isScheduled = this.get('post.isScheduled');
|
||||
let publishTime = this.get('post.publishedAtUTC') || moment.utc();
|
||||
let timeUntilPublished = publishTime.diff(moment.utc(), 'minutes', true);
|
||||
let isPublishedSoon = timeUntilPublished > 0 && timeUntilPublished < 15;
|
||||
|
||||
|
@ -343,41 +346,41 @@ export default Mixin.create({
|
|||
},
|
||||
|
||||
// a hook created in editor-base-route's setupController
|
||||
modelSaved() {
|
||||
let model = this.get('model');
|
||||
postSaved() {
|
||||
let post = this.get('post');
|
||||
|
||||
// safer to updateTags on save in one place
|
||||
// rather than in all other places save is called
|
||||
model.updateTags();
|
||||
post.updateTags();
|
||||
|
||||
// set previousTagNames to current tagNames for hasDirtyAttributes check
|
||||
this.set('previousTagNames', this.get('tagNames'));
|
||||
|
||||
// `updateTags` triggers `hasDirtyAttributes => true`.
|
||||
// for a saved model it would otherwise be false.
|
||||
// for a saved post it would otherwise be false.
|
||||
|
||||
// if the two "scratch" properties (title and content) match the model, then
|
||||
// if the two "scratch" properties (title and content) match the post, then
|
||||
// it's ok to set hasDirtyAttributes to false
|
||||
if (model.get('titleScratch') === model.get('title')
|
||||
&& JSON.stringify(model.get('scratch')) === JSON.stringify(model.get('mobiledoc'))) {
|
||||
if (post.get('titleScratch') === post.get('title')
|
||||
&& JSON.stringify(post.get('scratch')) === JSON.stringify(post.get('mobiledoc'))) {
|
||||
this.set('hasDirtyAttributes', false);
|
||||
}
|
||||
},
|
||||
|
||||
// an ugly hack, but necessary to watch all the model's properties
|
||||
// an ugly hack, but necessary to watch all the post's properties
|
||||
// and more, without having to be explicit and do it manually
|
||||
hasDirtyAttributes: computed.apply(Ember, watchedProps.concat({
|
||||
get() {
|
||||
let model = this.get('model');
|
||||
let post = this.get('post');
|
||||
|
||||
if (!model) {
|
||||
if (!post) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mobiledoc = JSON.stringify(model.get('mobiledoc'));
|
||||
let scratch = JSON.stringify(model.get('scratch'));
|
||||
let title = model.get('title');
|
||||
let titleScratch = model.get('titleScratch');
|
||||
let mobiledoc = JSON.stringify(post.get('mobiledoc'));
|
||||
let scratch = JSON.stringify(post.get('scratch'));
|
||||
let title = post.get('title');
|
||||
let titleScratch = post.get('titleScratch');
|
||||
let changedAttributes;
|
||||
|
||||
if (!this.tagNamesEqual()) {
|
||||
|
@ -388,22 +391,22 @@ export default Mixin.create({
|
|||
return true;
|
||||
}
|
||||
|
||||
// since `scratch` is not model property, we need to check
|
||||
// it explicitly against the model's mobiledoc attribute
|
||||
// since `scratch` is not post property, we need to check
|
||||
// it explicitly against the post's mobiledoc attribute
|
||||
if (mobiledoc !== scratch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the Adapter failed to save the model isError will be true
|
||||
// and we should consider the model still dirty.
|
||||
if (model.get('isError')) {
|
||||
// if the Adapter failed to save the post isError will be true
|
||||
// and we should consider the post still dirty.
|
||||
if (post.get('isError')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// models created on the client always return `hasDirtyAttributes: true`,
|
||||
// posts created on the client always return `hasDirtyAttributes: true`,
|
||||
// so we need to see which properties have actually changed.
|
||||
if (model.get('isNew')) {
|
||||
changedAttributes = Object.keys(model.changedAttributes());
|
||||
if (post.get('isNew')) {
|
||||
changedAttributes = Object.keys(post.changedAttributes());
|
||||
|
||||
if (changedAttributes.length) {
|
||||
return true;
|
||||
|
@ -413,10 +416,10 @@ export default Mixin.create({
|
|||
}
|
||||
|
||||
// even though we use the `scratch` prop to show edits,
|
||||
// which does *not* change the model's `hasDirtyAttributes` property,
|
||||
// which does *not* change the post's `hasDirtyAttributes` property,
|
||||
// `hasDirtyAttributes` will tell us if the other props have changed,
|
||||
// as long as the model is not new (model.isNew === false).
|
||||
return model.get('hasDirtyAttributes');
|
||||
// as long as the post is not new (post.isNew === false).
|
||||
return post.get('hasDirtyAttributes');
|
||||
},
|
||||
set(key, value) {
|
||||
return value;
|
||||
|
@ -485,10 +488,10 @@ export default Mixin.create({
|
|||
|
||||
if (status === 'published') {
|
||||
type = this.get('postOrPage');
|
||||
path = this.get('model.absoluteUrl');
|
||||
path = this.get('post.absoluteUrl');
|
||||
} else {
|
||||
type = 'Preview';
|
||||
path = this.get('model.previewUrl');
|
||||
path = this.get('post.previewUrl');
|
||||
}
|
||||
|
||||
message += ` <a href="${path}" target="_blank">View ${type}</a>`;
|
||||
|
@ -525,9 +528,9 @@ export default Mixin.create({
|
|||
},
|
||||
|
||||
saveTitle: task(function* () {
|
||||
let model = this.get('model');
|
||||
let currentTitle = model.get('title');
|
||||
let newTitle = model.get('titleScratch').trim();
|
||||
let post = this.get('post');
|
||||
let currentTitle = post.get('title');
|
||||
let newTitle = post.get('titleScratch').trim();
|
||||
|
||||
if (currentTitle && newTitle && newTitle === currentTitle) {
|
||||
return;
|
||||
|
@ -538,20 +541,20 @@ export default Mixin.create({
|
|||
|
||||
// generate a slug if a post is new and doesn't have a title yet or
|
||||
// if the title is still '(Untitled)'
|
||||
if ((model.get('isNew') && !currentTitle) || currentTitle === DEFAULT_TITLE) {
|
||||
if ((post.get('isNew') && !currentTitle) || currentTitle === DEFAULT_TITLE) {
|
||||
yield this.get('generateSlug').perform();
|
||||
}
|
||||
|
||||
if (this.get('model.isDraft')) {
|
||||
if (this.get('post.isDraft')) {
|
||||
yield this.get('autosave').perform();
|
||||
}
|
||||
}),
|
||||
|
||||
generateSlug: task(function* () {
|
||||
let title = this.get('model.titleScratch');
|
||||
let title = this.get('post.titleScratch');
|
||||
|
||||
// Only set an "untitled" slug once per post
|
||||
if (title === DEFAULT_TITLE && this.get('model.slug')) {
|
||||
if (title === DEFAULT_TITLE && this.get('post.slug')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -559,7 +562,7 @@ export default Mixin.create({
|
|||
let slug = yield this.get('slugGenerator').generateSlug('post', title);
|
||||
|
||||
if (!isBlank(slug)) {
|
||||
this.set('model.slug', slug);
|
||||
this.set('post.slug', slug);
|
||||
}
|
||||
} catch (error) {
|
||||
// Nothing to do (would be nice to log this somewhere though),
|
||||
|
@ -573,7 +576,7 @@ export default Mixin.create({
|
|||
|
||||
actions: {
|
||||
updateScratch(value) {
|
||||
this.set('model.scratch', value);
|
||||
this.set('post.scratch', value);
|
||||
|
||||
// save 3 seconds after last edit
|
||||
this.get('_autosave').perform();
|
||||
|
@ -639,7 +642,7 @@ export default Mixin.create({
|
|||
|
||||
leaveEditor() {
|
||||
let transition = this.get('leaveEditorTransition');
|
||||
let model = this.get('model');
|
||||
let post = this.get('post');
|
||||
|
||||
if (!transition) {
|
||||
this.get('notifications').showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'});
|
||||
|
@ -647,14 +650,14 @@ export default Mixin.create({
|
|||
}
|
||||
|
||||
// definitely want to clear the data store and post of any unsaved, client-generated tags
|
||||
model.updateTags();
|
||||
post.updateTags();
|
||||
|
||||
if (model.get('isNew')) {
|
||||
if (post.get('isNew')) {
|
||||
// the user doesn't want to save the new, unsaved post, so delete it.
|
||||
model.deleteRecord();
|
||||
post.deleteRecord();
|
||||
} else {
|
||||
// roll back changes on model props
|
||||
model.rollbackAttributes();
|
||||
// roll back changes on post props
|
||||
post.rollbackAttributes();
|
||||
}
|
||||
|
||||
// setting hasDirtyAttributes to false here allows willTransition on the editor route to succeed
|
||||
|
@ -667,11 +670,11 @@ export default Mixin.create({
|
|||
},
|
||||
|
||||
updateTitle(newTitle) {
|
||||
this.set('model.titleScratch', newTitle);
|
||||
this.set('post.titleScratch', newTitle);
|
||||
},
|
||||
|
||||
toggleDeletePostModal() {
|
||||
if (!this.get('model.isNew')) {
|
||||
if (!this.get('post.isNew')) {
|
||||
this.toggleProperty('showDeletePostModal');
|
||||
}
|
||||
},
|
||||
|
|
|
@ -36,10 +36,10 @@ export default Mixin.create(styleBody, ShortcutsRoute, {
|
|||
|
||||
willTransition(transition) {
|
||||
let controller = this.get('controller');
|
||||
let scratch = controller.get('model.scratch');
|
||||
let scratch = controller.get('post.scratch');
|
||||
let controllerIsDirty = controller.get('hasDirtyAttributes');
|
||||
let model = controller.get('model');
|
||||
let state = model.getProperties('isDeleted', 'isSaving', 'hasDirtyAttributes', 'isNew');
|
||||
let post = controller.get('post');
|
||||
let state = post.getProperties('isDeleted', 'isSaving', 'hasDirtyAttributes', 'isNew');
|
||||
|
||||
if (this.get('upgradeStatus.isRequired')) {
|
||||
return this._super(...arguments);
|
||||
|
@ -49,7 +49,7 @@ export default Mixin.create(styleBody, ShortcutsRoute, {
|
|||
&& transition.targetName === 'editor.edit'
|
||||
&& transition.intent.contexts
|
||||
&& transition.intent.contexts[0]
|
||||
&& transition.intent.contexts[0].id === model.get('id');
|
||||
&& transition.intent.contexts[0].id === post.get('id');
|
||||
|
||||
let deletedWithoutChanges = state.isDeleted
|
||||
&& (state.isSaving || !state.hasDirtyAttributes);
|
||||
|
@ -60,11 +60,11 @@ export default Mixin.create(styleBody, ShortcutsRoute, {
|
|||
return;
|
||||
}
|
||||
|
||||
// The controller may hold model state that will be lost in the
|
||||
// The controller may hold post state that will be lost in the
|
||||
// new->edit transition, so we need to apply it now.
|
||||
if (fromNewToEdit && controllerIsDirty) {
|
||||
if (scratch !== model.get('mobiledoc')) {
|
||||
model.set('mobiledoc', scratch);
|
||||
if (scratch !== post.get('mobiledoc')) {
|
||||
post.set('mobiledoc', scratch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,42 +75,42 @@ export default Mixin.create(styleBody, ShortcutsRoute, {
|
|||
controller.send('cancelAutosave');
|
||||
|
||||
if (state.isNew) {
|
||||
model.deleteRecord();
|
||||
post.deleteRecord();
|
||||
}
|
||||
|
||||
// since the transition is now certain to complete..
|
||||
window.onbeforeunload = null;
|
||||
|
||||
// remove model-related listeners created in editor-base-route
|
||||
this.detachModelHooks(controller, model);
|
||||
// remove post-related listeners created in editor-base-route
|
||||
this.detachModelHooks(controller, post);
|
||||
}
|
||||
},
|
||||
|
||||
attachModelHooks(controller, model) {
|
||||
// this will allow us to track when the model is saved and update the controller
|
||||
attachModelHooks(controller, post) {
|
||||
// this will allow us to track when the post is saved and update the controller
|
||||
// so that we can be sure controller.hasDirtyAttributes is correct, without having to update the
|
||||
// controller on each instance of `model.save()`.
|
||||
// controller on each instance of `post.save()`.
|
||||
//
|
||||
// another reason we can't do this on `model.save().then()` is because the post-settings-menu
|
||||
// also saves the model, and passing messages is difficult because we have two
|
||||
// another reason we can't do this on `post.save().then()` is because the post-settings-menu
|
||||
// also saves the post, and passing messages is difficult because we have two
|
||||
// types of editor controllers, and the PSM also exists on the posts.post route.
|
||||
//
|
||||
// The reason we can't just keep this functionality in the editor controller is
|
||||
// because we need to remove these handlers on `willTransition` in the editor route.
|
||||
model.on('didCreate', controller, controller.get('modelSaved'));
|
||||
model.on('didUpdate', controller, controller.get('modelSaved'));
|
||||
post.on('didCreate', controller, controller.get('postSaved'));
|
||||
post.on('didUpdate', controller, controller.get('postSaved'));
|
||||
},
|
||||
|
||||
detachModelHooks(controller, model) {
|
||||
model.off('didCreate', controller, controller.get('modelSaved'));
|
||||
model.off('didUpdate', controller, controller.get('modelSaved'));
|
||||
detachModelHooks(controller, post) {
|
||||
post.off('didCreate', controller, controller.get('postSaved'));
|
||||
post.off('didUpdate', controller, controller.get('postSaved'));
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
let tags = model.get('tags');
|
||||
setupController(controller, post) {
|
||||
let tags = post.get('tags');
|
||||
|
||||
model.set('scratch', model.get('mobiledoc'));
|
||||
model.set('titleScratch', model.get('title'));
|
||||
post.set('scratch', post.get('mobiledoc'));
|
||||
post.set('titleScratch', post.get('title'));
|
||||
|
||||
// reset the leave editor transition so new->edit will still work
|
||||
controller.set('leaveEditorTransition', null);
|
||||
|
@ -124,18 +124,18 @@ export default Mixin.create(styleBody, ShortcutsRoute, {
|
|||
controller.set('previousTagNames', []);
|
||||
}
|
||||
|
||||
// trigger an immediate autosave timeout if model has changed between
|
||||
// trigger an immediate autosave timeout if post has changed between
|
||||
// new->edit (typical as first save will only contain the first char)
|
||||
// so that leaving the route waits for save instead of showing the
|
||||
// "Are you sure you want to leave?" modal unexpectedly
|
||||
if (!model.get('isNew') && model.get('hasDirtyAttributes')) {
|
||||
if (!post.get('isNew') && post.get('hasDirtyAttributes')) {
|
||||
controller.get('_autosave').perform();
|
||||
}
|
||||
|
||||
// reset save-on-first-change (gh-koenig specific)
|
||||
// controller._hasChanged = false;
|
||||
|
||||
// attach model-related listeners created in editor-base-route
|
||||
this.attachModelHooks(controller, model);
|
||||
// attach post-related listeners created in editor-base-route
|
||||
this.attachModelHooks(controller, post);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,10 +24,9 @@ export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
|
|||
});
|
||||
},
|
||||
|
||||
setupController(controller, models) {
|
||||
setupController(controller) {
|
||||
// reset the leave setting transition
|
||||
controller.set('leaveSettingsTransition', null);
|
||||
controller.set('model', models.settings);
|
||||
controller.set('themes', this.get('store').peekAll('theme'));
|
||||
this.get('controller').send('reset');
|
||||
},
|
||||
|
|
|
@ -6,6 +6,10 @@ export default AuthenticatedRoute.extend({
|
|||
return this.get('store').findAll('theme');
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('themes', model);
|
||||
},
|
||||
|
||||
actions: {
|
||||
cancel() {
|
||||
this.transitionTo('settings.design');
|
||||
|
|
|
@ -28,8 +28,6 @@ export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
|
|||
setupController(controller, models) {
|
||||
// reset the leave setting transition
|
||||
controller.set('leaveSettingsTransition', null);
|
||||
controller.set('model', models.settings);
|
||||
controller.set('themes', this.get('store').peekAll('theme'));
|
||||
controller.set('availableTimezones', models.availableTimezones);
|
||||
},
|
||||
|
||||
|
@ -44,10 +42,10 @@ export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
|
|||
|
||||
willTransition(transition) {
|
||||
let controller = this.get('controller');
|
||||
let model = controller.get('model');
|
||||
let modelIsDirty = model.get('hasDirtyAttributes');
|
||||
let settings = this.get('settings');
|
||||
let settingsIsDirty = settings.get('hasDirtyAttributes');
|
||||
|
||||
if (modelIsDirty) {
|
||||
if (settingsIsDirty) {
|
||||
transition.abort();
|
||||
controller.send('toggleLeaveSettingsModal', transition);
|
||||
return;
|
||||
|
|
|
@ -26,7 +26,7 @@ export default Route.extend(UnauthenticatedRouteMixin, styleBody, {
|
|||
this._super(...arguments);
|
||||
|
||||
// clear the properties that hold the credentials when we're no longer on the signin screen
|
||||
controller.set('model.identification', '');
|
||||
controller.set('model.password', '');
|
||||
controller.set('signin.identification', '');
|
||||
controller.set('signin.password', '');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ export default Route.extend(styleBody, UnauthenticatedRouteMixin, {
|
|||
},
|
||||
|
||||
model(params) {
|
||||
let model = EmberObject.create();
|
||||
let signupDetails = EmberObject.create();
|
||||
let re = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2}|[A-Za-z0-9_-]{3})?$/;
|
||||
let email,
|
||||
tokenText;
|
||||
|
@ -42,9 +42,9 @@ export default Route.extend(styleBody, UnauthenticatedRouteMixin, {
|
|||
tokenText = atob(params.token);
|
||||
email = tokenText.split('|')[1];
|
||||
|
||||
model.set('email', email);
|
||||
model.set('token', params.token);
|
||||
model.set('errors', Errors.create());
|
||||
signupDetails.set('email', email);
|
||||
signupDetails.set('token', params.token);
|
||||
signupDetails.set('errors', Errors.create());
|
||||
|
||||
let authUrl = this.get('ghostPaths.url').api('authentication', 'invitation');
|
||||
|
||||
|
@ -60,14 +60,14 @@ export default Route.extend(styleBody, UnauthenticatedRouteMixin, {
|
|||
return resolve(this.transitionTo('signin'));
|
||||
}
|
||||
|
||||
model.set('invitedBy', response.invitation[0].invitedBy);
|
||||
signupDetails.set('invitedBy', response.invitation[0].invitedBy);
|
||||
|
||||
// set blogTitle, so password validation has access to it
|
||||
model.set('blogTitle', this.get('config.blogTitle'));
|
||||
signupDetails.set('blogTitle', this.get('config.blogTitle'));
|
||||
|
||||
resolve(model);
|
||||
resolve(signupDetails);
|
||||
}).catch(() => {
|
||||
resolve(model);
|
||||
resolve(signupDetails);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -76,6 +76,6 @@ export default Route.extend(styleBody, UnauthenticatedRouteMixin, {
|
|||
this._super(...arguments);
|
||||
|
||||
// clear the properties that hold the sensitive data from the controller
|
||||
this.controllerFor('signup').setProperties({email: '', password: '', token: ''});
|
||||
this.controllerFor('signup').get('signupDetails').setProperties({email: '', password: '', token: ''});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,8 +5,12 @@ export default Route.extend({
|
|||
return this.get('store').createRecord('subscriber');
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('subscriber', model);
|
||||
},
|
||||
|
||||
deactivate() {
|
||||
let subscriber = this.controller.get('model');
|
||||
let subscriber = this.controller.get('subscriber');
|
||||
|
||||
this._super(...arguments);
|
||||
|
||||
|
@ -16,13 +20,13 @@ export default Route.extend({
|
|||
},
|
||||
|
||||
rollbackModel() {
|
||||
let subscriber = this.controller.get('model');
|
||||
let subscriber = this.controller.get('subscriber');
|
||||
subscriber.rollbackAttributes();
|
||||
},
|
||||
|
||||
actions: {
|
||||
save() {
|
||||
let subscriber = this.controller.get('model');
|
||||
let subscriber = this.controller.get('subscriber');
|
||||
return subscriber.save().then((saved) => {
|
||||
this.send('addSubscriber', saved);
|
||||
return saved;
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<section class="view-container">
|
||||
<section class="gh-env-details">
|
||||
<ul class="gh-env-list">
|
||||
<li class="gh-env-list-version"><strong>Version</strong> {{model.version}}</li>
|
||||
<li><strong>Environment</strong> {{model.environment}}</li>
|
||||
<li class="gh-env-list-database-type"><strong>Database</strong> {{model.database}}</li>
|
||||
<li><strong>Mail</strong> {{#if model.mail}}{{model.mail}}{{else}}Native{{/if}}</li>
|
||||
<li class="gh-env-list-version"><strong>Version</strong> {{about.version}}</li>
|
||||
<li><strong>Environment</strong> {{about.environment}}</li>
|
||||
<li class="gh-env-list-database-type"><strong>Database</strong> {{about.database}}</li>
|
||||
<li><strong>Mail</strong> {{#if about.mail}}{{about.mail}}{{else}}Native{{/if}}</li>
|
||||
</ul>
|
||||
<div class="gh-env-help">
|
||||
<a class="gh-btn" href="https://help.ghost.org" target="_blank"><span>User Documentation</span></a>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
<div class="settings-menu-content">
|
||||
{{gh-image-uploader-with-preview
|
||||
image=model.featureImage
|
||||
image=post.featureImage
|
||||
text="Upload post image"
|
||||
allowUnsplash=true
|
||||
update=(action "setCoverImage")
|
||||
|
@ -19,13 +19,13 @@
|
|||
<div class="form-group">
|
||||
<label for="url">Post URL</label>
|
||||
{{!-- new posts don't have a preview link --}}
|
||||
{{#unless model.isNew}}
|
||||
{{#if model.isPublished}}
|
||||
<a class="post-view-link" target="_blank" href="{{model.absoluteUrl}}">
|
||||
{{#unless post.isNew}}
|
||||
{{#if post.isPublished}}
|
||||
<a class="post-view-link" target="_blank" href="{{post.absoluteUrl}}">
|
||||
View post {{inline-svg "external"}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a class="post-view-link" target="_blank" href="{{model.previewUrl}}">
|
||||
<a class="post-view-link" target="_blank" href="{{post.previewUrl}}">
|
||||
Preview {{inline-svg "external"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
|
@ -45,32 +45,32 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{{#if (or model.isDraft model.isPublished model.pastScheduledTime)}}
|
||||
{{#if (or post.isDraft post.isPublished post.pastScheduledTime)}}
|
||||
<label>Publish Date</label>
|
||||
{{else}}
|
||||
<label>Scheduled Date</label>
|
||||
<p>Use the publish menu to re-schedule</p>
|
||||
{{/if}}
|
||||
{{gh-date-time-picker
|
||||
date=model.publishedAtBlogDate
|
||||
time=model.publishedAtBlogTime
|
||||
date=post.publishedAtBlogDate
|
||||
time=post.publishedAtBlogTime
|
||||
setDate=(action "setPublishedAtBlogDate")
|
||||
setTime=(action "setPublishedAtBlogTime")
|
||||
errors=model.errors
|
||||
errors=post.errors
|
||||
dateErrorProperty="publishedAtBlogDate"
|
||||
timeErrorProperty="publishedAtBlogTime"
|
||||
maxDate='now'
|
||||
disabled=model.isScheduled
|
||||
disabled=post.isScheduled
|
||||
static=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="tag-input">Tags</label>
|
||||
{{gh-psm-tags-input post=model triggerId="tag-input"}}
|
||||
{{gh-psm-tags-input post=post triggerId="tag-input"}}
|
||||
</div>
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="customExcerpt"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="customExcerpt"}}
|
||||
<label for="custom-excerpt">Excerpt</label>
|
||||
{{gh-textarea customExcerptScratch
|
||||
class="post-setting-custom-excerpt"
|
||||
|
@ -80,7 +80,7 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut customExcerptScratch))
|
||||
data-test-field="custom-excerpt"}}
|
||||
{{gh-error-message errors=model.errors property="customExcerpt" data-test-error="custom-excerpt"}}
|
||||
{{gh-error-message errors=post.errors property="customExcerpt" data-test-error="custom-excerpt"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#unless session.user.isAuthor}}
|
||||
|
@ -137,11 +137,11 @@
|
|||
|
||||
<div class="form-group for-checkbox">
|
||||
<label class="checkbox" for="static-page" {{action "togglePage" bubbles="false"}}>
|
||||
{{one-way-checkbox model.page
|
||||
{{one-way-checkbox post.page
|
||||
name="static-page"
|
||||
id="static-page"
|
||||
class="gh-input post-setting-static-page"
|
||||
update=(action (mut model.page))
|
||||
update=(action (mut post.page))
|
||||
data-test-checkbox="static-page"
|
||||
}}
|
||||
<span class="input-toggle-component"></span>
|
||||
|
@ -149,11 +149,11 @@
|
|||
</label>
|
||||
|
||||
<label class="checkbox" for="featured" {{action "toggleFeatured" bubbles="false"}}>
|
||||
{{one-way-checkbox model.featured
|
||||
{{one-way-checkbox post.featured
|
||||
name="featured"
|
||||
id="featured"
|
||||
class="gh-input post-setting-featured"
|
||||
update=(action (mut model.featured))
|
||||
update=(action (mut post.featured))
|
||||
data-test-checkbox="featured"
|
||||
}}
|
||||
<span class="input-toggle-component"></span>
|
||||
|
@ -162,10 +162,10 @@
|
|||
</div>
|
||||
|
||||
{{gh-psm-template-select
|
||||
post=model
|
||||
onTemplateSelect=(action (mut model.customTemplate))}}
|
||||
post=post
|
||||
onTemplateSelect=(action (mut post.customTemplate))}}
|
||||
|
||||
{{#unless model.isNew}}
|
||||
{{#unless post.isNew}}
|
||||
<button type="button" class="gh-btn gh-btn-link gh-btn-icon settings-menu-delete-button" {{action "deletePost"}}><span>{{inline-svg "trash"}} Delete Post</span></button>
|
||||
{{/unless}}
|
||||
|
||||
|
@ -185,7 +185,7 @@
|
|||
|
||||
<div class="settings-menu-content">
|
||||
<form {{action "discardEnter" on="submit"}}>
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="metaTitle"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="metaTitle"}}
|
||||
<label for="meta-title">Meta Title</label>
|
||||
{{gh-input metaTitleScratch
|
||||
class="post-setting-meta-title"
|
||||
|
@ -196,10 +196,10 @@
|
|||
update=(action (mut metaTitleScratch))
|
||||
data-test-field="meta-title"}}
|
||||
<p>Recommended: <b>70</b> characters. You’ve used {{gh-count-down-characters metaTitleScratch 70}}</p>
|
||||
{{gh-error-message errors=model.errors property="meta-title"}}
|
||||
{{gh-error-message errors=post.errors property="meta-title"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="metaDescription"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="metaDescription"}}
|
||||
<label for="meta-description">Meta Description</label>
|
||||
{{gh-textarea metaDescriptionScratch
|
||||
class="post-setting-meta-description"
|
||||
|
@ -210,7 +210,7 @@
|
|||
update=(action (mut metaDescriptionScratch))
|
||||
data-test-field="meta-description"}}
|
||||
<p>Recommended: <b>156</b> characters. You’ve used {{gh-count-down-characters metaDescriptionScratch 156}}</p>
|
||||
{{gh-error-message errors=model.errors property="meta-description"}}
|
||||
{{gh-error-message errors=post.errors property="meta-description"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -236,13 +236,13 @@
|
|||
|
||||
<form {{action "discardEnter" on="submit"}}>
|
||||
{{gh-image-uploader-with-preview
|
||||
image=model.twitterImage
|
||||
image=post.twitterImage
|
||||
text="Add Twitter image"
|
||||
allowUnsplash=true
|
||||
update=(action "setTwitterImage")
|
||||
remove=(action "clearTwitterImage")
|
||||
}}
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="twitterTitle"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="twitterTitle"}}
|
||||
<label for="twitter-title">Twitter Title</label>
|
||||
{{gh-input twitterTitleScratch
|
||||
class="post-setting-twitter-title"
|
||||
|
@ -253,10 +253,10 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut twitterTitleScratch))
|
||||
data-test-field="twitter-title"}}
|
||||
{{gh-error-message errors=model.errors property="twitterTitle" data-test-error="twitter-title"}}
|
||||
{{gh-error-message errors=post.errors property="twitterTitle" data-test-error="twitter-title"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="twitterDescription"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="twitterDescription"}}
|
||||
<label for="twitter-description">Twitter Description</label>
|
||||
{{gh-textarea twitterDescriptionScratch
|
||||
class="post-setting-twitter-description"
|
||||
|
@ -267,7 +267,7 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut twitterDescriptionScratch))
|
||||
data-test-field="twitter-description"}}
|
||||
{{gh-error-message errors=model.errors property="twitterDescription" data-test-error="twitter-description"}}
|
||||
{{gh-error-message errors=post.errors property="twitterDescription" data-test-error="twitter-description"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -304,13 +304,13 @@
|
|||
<div class="settings-menu-content">
|
||||
<form {{action "discardEnter" on="submit"}}>
|
||||
{{gh-image-uploader-with-preview
|
||||
image=model.ogImage
|
||||
image=post.ogImage
|
||||
text="Add Facebook image"
|
||||
allowUnsplash=true
|
||||
update=(action "setOgImage")
|
||||
remove=(action "clearOgImage")
|
||||
}}
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="ogTitle"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="ogTitle"}}
|
||||
<label for="og-title">Facebook Title</label>
|
||||
{{gh-input ogTitleScratch
|
||||
class="post-setting-og-title"
|
||||
|
@ -321,10 +321,10 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut ogTitleScratch))
|
||||
data-test-field="og-title"}}
|
||||
{{gh-error-message errors=model.errors property="ogTitle" data-test-error="og-title"}}
|
||||
{{gh-error-message errors=post.errors property="ogTitle" data-test-error="og-title"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="ogDescription"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="ogDescription"}}
|
||||
<label for="og-description">Facebook Description</label>
|
||||
{{gh-textarea ogDescriptionScratch
|
||||
class="post-setting-og-description"
|
||||
|
@ -335,7 +335,7 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut ogDescriptionScratch))
|
||||
data-test-field="og-description"}}
|
||||
{{gh-error-message errors=model.errors property="ogDescription" data-test-error="og-description"}}
|
||||
{{gh-error-message errors=post.errors property="ogDescription" data-test-error="og-description"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -349,7 +349,7 @@
|
|||
<div class="gh-og-preview-description">{{truncate facebookDescription 300}}</div>
|
||||
<div class="gh-og-preview-footer">
|
||||
<div class="gh-og-preview-footer-left">
|
||||
{{config.blogDomain}} <span class="gh-og-preview-footer-left-divider">|</span> by <span class="gh-og-preview-footer-author">{{model.author.name}}</span>
|
||||
{{config.blogDomain}} <span class="gh-og-preview-footer-left-divider">|</span> by <span class="gh-og-preview-footer-author">{{post.author.name}}</span>
|
||||
</div>
|
||||
<div class="gh-og-preview-footer-right">
|
||||
</div>
|
||||
|
@ -371,7 +371,7 @@
|
|||
|
||||
<div class="settings-menu-content settings-menu-content-codeinjection">
|
||||
<form {{action "discardEnter" on="submit"}}>
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="codeinjectionHead"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="codeinjectionHead"}}
|
||||
<label for="codeinjection-head">Post Header <code>\{{ghost_head}}</code></label>
|
||||
{{gh-cm-editor codeinjectionHeadScratch
|
||||
id="post-setting-codeinjection-head"
|
||||
|
@ -381,10 +381,10 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut codeinjectionHeadScratch))
|
||||
data-test-field="codeinjection-head"}}
|
||||
{{gh-error-message errors=model.errors property="codeinjectionHead" data-test-error="codeinjection-head"}}
|
||||
{{gh-error-message errors=post.errors property="codeinjectionHead" data-test-error="codeinjection-head"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="codeinjectionFoot"}}
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="codeinjectionFoot"}}
|
||||
<label for="codeinjection-foot">Post Footer <code>\{{ghost_foot}}</code></label>
|
||||
{{gh-cm-editor codeinjectionFootScratch
|
||||
id="post-setting-codeinjection-foot"
|
||||
|
@ -394,7 +394,7 @@
|
|||
stopEnterKeyDownPropagation="true"
|
||||
update=(action (mut codeinjectionFootScratch))
|
||||
data-test-field="codeinjection-foot"}}
|
||||
{{gh-error-message errors=model.errors property="codeinjectionFoot" data-test-error="codeinjection-foot"}}
|
||||
{{gh-error-message errors=post.errors property="codeinjectionFoot" data-test-error="codeinjection-foot"}}
|
||||
{{/gh-form-group}}
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
<div class="modal-body">
|
||||
<fieldset>
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="email"}}
|
||||
{{#gh-form-group errors=subscriber.errors hasValidated=subscriber.hasValidated property="email"}}
|
||||
<label for="new-subscriber-email">Email Address</label>
|
||||
<input type="email"
|
||||
value={{model.email}}
|
||||
value={{subscriber.email}}
|
||||
oninput={{action "updateEmail" value="target.value"}}
|
||||
id="new-subscriber-email"
|
||||
class="gh-input email"
|
||||
|
@ -17,7 +17,7 @@
|
|||
autofocus="autofocus"
|
||||
autocapitalize="off"
|
||||
autocorrect="off">
|
||||
{{gh-error-message errors=model.errors property="email"}}
|
||||
{{gh-error-message errors=subscriber.errors property="email"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
</fieldset>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<header class="gh-editor-header {{editor.headerClass}}">
|
||||
<div class="gh-editor-status">
|
||||
{{gh-editor-post-status
|
||||
post=model
|
||||
post=post
|
||||
isSaving=(or autosave.isRunning saveTasks.isRunning)
|
||||
}}
|
||||
</div>
|
||||
|
@ -17,9 +17,9 @@
|
|||
</time>
|
||||
{{/if}}
|
||||
<section class="view-actions">
|
||||
{{#unless model.isNew}}
|
||||
{{#unless post.isNew}}
|
||||
{{gh-publishmenu
|
||||
post=model
|
||||
post=post
|
||||
saveTask=save
|
||||
setSaveType=(action "setSaveType")
|
||||
onOpen=(action "cancelAutosave")}}
|
||||
|
@ -40,7 +40,7 @@
|
|||
placeholder="Begin writing your story..."
|
||||
autofocus=shouldFocusEditor
|
||||
uploadedImageUrls=editor.uploadedImageUrls
|
||||
mobiledoc=(readonly model.scratch)
|
||||
mobiledoc=(readonly post.scratch)
|
||||
isFullScreen=editor.isFullScreen
|
||||
onChange=(action "updateScratch")
|
||||
onFullScreenToggle=(action editor.toggleFullScreen)
|
||||
|
@ -51,7 +51,7 @@
|
|||
as |markdown|
|
||||
}}
|
||||
<div class="gh-markdown-editor-pane">
|
||||
{{gh-textarea model.titleScratch
|
||||
{{gh-textarea post.titleScratch
|
||||
class="gh-editor-title"
|
||||
placeholder="Post Title"
|
||||
tabindex="1"
|
||||
|
@ -69,7 +69,7 @@
|
|||
|
||||
{{#if markdown.isSplitScreen}}
|
||||
<div class="gh-markdown-editor-preview">
|
||||
<h1 class="gh-markdown-editor-preview-title">{{model.titleScratch}}</h1>
|
||||
<h1 class="gh-markdown-editor-preview-title">{{post.titleScratch}}</h1>
|
||||
<div class="gh-markdown-editor-preview-content"></div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -129,7 +129,7 @@
|
|||
|
||||
{{#if showDeletePostModal}}
|
||||
{{gh-fullscreen-modal "delete-post"
|
||||
model=(hash post=model onSuccess=(route-action 'redirectToContentScreen'))
|
||||
model=(hash post=post onSuccess=(route-action 'redirectToContentScreen'))
|
||||
close=(action "toggleDeletePostModal")
|
||||
modifier="action wide"}}
|
||||
{{/if}}
|
||||
|
@ -149,7 +149,7 @@
|
|||
|
||||
{{#liquid-wormhole}}
|
||||
{{gh-post-settings-menu
|
||||
model=model
|
||||
post=post
|
||||
showSettingsMenu=ui.showSettingsMenu
|
||||
deletePost=(action "toggleDeletePostModal")
|
||||
updateSlug=updateSlug
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
|
||||
<section class="content-list">
|
||||
<ol class="posts-list">
|
||||
{{#each model as |post|}}
|
||||
{{#each postsInfinityModel as |post|}}
|
||||
{{gh-posts-list-item
|
||||
post=post
|
||||
onDoubleClick=(action "openEditor")
|
||||
|
@ -105,7 +105,7 @@
|
|||
</ol>
|
||||
|
||||
{{infinity-loader
|
||||
infinityModel=model
|
||||
infinityModel=postsInfinityModel
|
||||
scrollable=".gh-main"
|
||||
triggerOffset=1000}}
|
||||
</section>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<div class="gh-setting-action">
|
||||
<div class="for-checkbox">
|
||||
<label for="amp" class="checkbox">
|
||||
{{one-way-checkbox model id="amp" name="amp" type="checkbox" update=(action "update") data-test-amp-checkbox=true}}
|
||||
{{one-way-checkbox ampSettings id="amp" name="amp" type="checkbox" update=(action "update") data-test-amp-checkbox=true}}
|
||||
<span class="input-toggle-component"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
<div class="gh-setting-title">Webhook URL</div>
|
||||
<div class="gh-setting-desc">Automatically send newly published posts to a channel in Slack or any Slack-compatible service like Discord or Mattermost.</div>
|
||||
<div class="gh-setting-content-extended">
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="url"}}
|
||||
{{gh-input model.url name="slack[url]" update=(action "updateURL") onenter=(action "save") focusOut=(action "triggerDirtyState") placeholder="https://hooks.slack.com/services/..." data-test-slack-url-input=true}}
|
||||
{{#unless model.errors.url}}
|
||||
{{#gh-form-group errors=slackSettings.errors hasValidated=slackSettings.hasValidated property="url"}}
|
||||
{{gh-input slackSettings.url name="slack[url]" update=(action "updateURL") onenter=(action "save") focusOut=(action "triggerDirtyState") placeholder="https://hooks.slack.com/services/..." data-test-slack-url-input=true}}
|
||||
{{#unless slackSettings.errors.url}}
|
||||
<p>Set up a new incoming webhook <a href="https://my.slack.com/apps/new/A0F7XDUAZ-incoming-webhooks" target="_blank">here</a>, and grab the URL.</p>
|
||||
{{else}}
|
||||
{{gh-error-message errors=model.errors property="url"}}
|
||||
{{gh-error-message errors=slackSettings.errors property="url"}}
|
||||
{{/unless}}
|
||||
{{/gh-form-group}}
|
||||
</div>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<div class="form-group right">
|
||||
<div class="for-checkbox">
|
||||
<label for="isActive" class="checkbox">
|
||||
{{one-way-checkbox model.isActive id="isActive" name="isActive" type="checkbox" update=(action "update") data-test-checkbox="unsplash"}}
|
||||
{{one-way-checkbox unsplashSettings.isActive id="isActive" name="isActive" type="checkbox" update=(action "update") data-test-checkbox="unsplash"}}
|
||||
<span class="input-toggle-component"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -23,13 +23,13 @@
|
|||
<div class="form-group settings-code">
|
||||
<label for="ghost-head">Blog Header</label>
|
||||
<p>Code here will be injected into the <code>\{{ghost_head}}</code> tag on every page of your blog</p>
|
||||
{{gh-cm-editor model.ghostHead id="ghost-head" class="gh-input settings-code-editor" name="codeInjection[ghost_head]" type="text" update=(action (mut model.ghostHead))}}
|
||||
{{gh-cm-editor settings.ghostHead id="ghost-head" class="gh-input settings-code-editor" name="codeInjection[ghost_head]" type="text" update=(action (mut settings.ghostHead))}}
|
||||
</div>
|
||||
|
||||
<div class="form-group settings-code">
|
||||
<label for="ghost-foot">Blog Footer</label>
|
||||
<p>Code here will be injected into the <code>\{{ghost_foot}}</code> tag on every page of your blog</p>
|
||||
{{gh-cm-editor model.ghostFoot id="ghost-foot" class="gh-input settings-code-editor" name="codeInjection[ghost_foot]" type="text" update=(action (mut model.ghostFoot))}}
|
||||
{{gh-cm-editor settings.ghostFoot id="ghost-foot" class="gh-input settings-code-editor" name="codeInjection[ghost_foot]" type="text" update=(action (mut settings.ghostFoot))}}
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
<div class="gh-setting-header">Navigation</div>
|
||||
<div class="gh-blognav-container">
|
||||
<form id="settings-navigation" class="gh-blognav" novalidate="novalidate">
|
||||
{{#sortable-objects sortableObjectList=model.navigation useSwap=false}}
|
||||
{{#each model.navigation as |navItem|}}
|
||||
{{#sortable-objects sortableObjectList=settings.navigation useSwap=false}}
|
||||
{{#each settings.navigation as |navItem|}}
|
||||
{{#draggable-object content=navItem dragHandle=".gh-blognav-grab" isSortable=true}}
|
||||
{{gh-navitem navItem=navItem baseUrl=blogUrl addItem=(action "addNavItem") deleteItem=(action "deleteNavItem") updateUrl=(action "updateUrl") updateLabel=(action "updateLabel")}}
|
||||
{{/draggable-object}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{gh-fullscreen-modal "upload-theme"
|
||||
model=(hash
|
||||
themes=model
|
||||
themes=themes
|
||||
activate=(route-action 'activateTheme')
|
||||
)
|
||||
close=(route-action "cancel")
|
||||
|
|
|
@ -22,15 +22,15 @@
|
|||
<div class="gh-setting-desc">The details used to identify your publication around the web</div>
|
||||
{{#liquid-if pubInfoOpen}}
|
||||
<div class="gh-setting-content-extended">
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="title"}}
|
||||
{{gh-input model.title type="text" focusOut=(action "validate" "title" target=model) update=(action (mut model.title)) data-test-title-input=true}}
|
||||
{{gh-error-message errors=model.errors property="title"}}
|
||||
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="title"}}
|
||||
{{gh-input settings.title type="text" focusOut=(action "validate" "title" target=settings) update=(action (mut settings.title)) data-test-title-input=true}}
|
||||
{{gh-error-message errors=settings.errors property="title"}}
|
||||
<p>The name of your site</p>
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="description" class="description-container"}}
|
||||
{{gh-input model.description type="text" focusOut=(action "validate" "description" target=model) update=(action (mut model.description)) data-test-description-input=true}}
|
||||
{{gh-error-message errors=model.errors property="description"}}
|
||||
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="description" class="description-container"}}
|
||||
{{gh-input settings.description type="text" focusOut=(action "validate" "description" target=settings) update=(action (mut settings.description)) data-test-description-input=true}}
|
||||
{{gh-error-message errors=settings.errors property="description"}}
|
||||
<p>Used in your theme, meta data and search results</p>
|
||||
{{/gh-form-group}}
|
||||
</div>
|
||||
|
@ -47,7 +47,7 @@
|
|||
{{#liquid-if timezoneOpen}}
|
||||
<div class="gh-setting-content-extended">
|
||||
{{gh-timezone-select
|
||||
activeTimezone=model.activeTimezone
|
||||
activeTimezone=settings.activeTimezone
|
||||
availableTimezones=availableTimezones
|
||||
update=(action "setTimezone")}}
|
||||
</div>
|
||||
|
@ -63,9 +63,9 @@
|
|||
<div class="gh-setting-desc">Set the language/locale which is used on your site</div>
|
||||
{{#liquid-if defaultLocaleOpen}}
|
||||
<div class="gh-setting-content-extended">
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="defaultLocale"}}
|
||||
{{gh-input model.defaultLocale type="text" focusOut=(action "validate" "defaultLocale" target=model) update=(action (mut model.defaultLocale)) data-test-default-locale-input=true}}
|
||||
{{gh-error-message errors=model.errors property="defaultLocale"}}
|
||||
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="defaultLocale"}}
|
||||
{{gh-input settings.defaultLocale type="text" focusOut=(action "validate" "defaultLocale" target=settings) update=(action (mut settings.defaultLocale)) data-test-default-locale-input=true}}
|
||||
{{gh-error-message errors=settings.errors property="defaultLocale"}}
|
||||
<p>Default: English (<strong>en</strong>); you can add translation files to your theme for <a href="https://themes.ghost.org/v1.20.0/docs/i18n" target="_blank" rel="noopener">any language</a></p>
|
||||
{{/gh-form-group}}
|
||||
</div>
|
||||
|
@ -94,8 +94,8 @@
|
|||
<div class="gh-setting-action gh-setting-action-smallimg">
|
||||
{{#if uploader.isUploading}}
|
||||
{{uploader.progressBar}}
|
||||
{{else if model.icon}}
|
||||
<img class="blog-icon" src="{{model.icon}}" onclick={{action "triggerFileDialog"}} alt="icon" data-test-icon-img>
|
||||
{{else if settings.icon}}
|
||||
<img class="blog-icon" src="{{settings.icon}}" onclick={{action "triggerFileDialog"}} alt="icon" data-test-icon-img>
|
||||
<button type="button" class="gh-setting-action-smallimg-delete" {{action "removeImage" "icon"}} data-test-delete-image="icon">
|
||||
<span>delete</span>
|
||||
</button>
|
||||
|
@ -126,8 +126,8 @@
|
|||
<div class="gh-setting-action gh-setting-action-smallimg">
|
||||
{{#if uploader.isUploading}}
|
||||
{{uploader.progressBar}}
|
||||
{{else if model.logo}}
|
||||
<img class="blog-logo" src="{{model.logo}}" onclick={{action "triggerFileDialog"}} alt="logo" data-test-logo-img>
|
||||
{{else if settings.logo}}
|
||||
<img class="blog-logo" src="{{settings.logo}}" onclick={{action "triggerFileDialog"}} alt="logo" data-test-logo-img>
|
||||
<button type="button" class="gh-setting-action-smallimg-delete" {{action "removeImage" "logo"}} data-test-delete-image="logo">
|
||||
<span>delete</span>
|
||||
</button>
|
||||
|
@ -158,8 +158,8 @@
|
|||
<div class="gh-setting-action gh-setting-action-largeimg">
|
||||
{{#if uploader.isUploading}}
|
||||
{{uploader.progressBar}}
|
||||
{{else if model.coverImage}}
|
||||
<img class="blog-cover" src="{{model.coverImage}}" onclick={{action "triggerFileDialog"}} alt="cover photo" data-test-cover-img>
|
||||
{{else if settings.coverImage}}
|
||||
<img class="blog-cover" src="{{settings.coverImage}}" onclick={{action "triggerFileDialog"}} alt="cover photo" data-test-cover-img>
|
||||
<button type="button" class="gh-setting-action-largeimg-delete" {{action "removeImage" "coverImage"}} data-test-delete-image="coverImage">
|
||||
<span>delete</span>
|
||||
</button>
|
||||
|
@ -182,14 +182,14 @@
|
|||
<div class="gh-setting-desc">Link your social accounts for full structured data and rich card support</div>
|
||||
{{#liquid-if socialOpen}}
|
||||
<div class="gh-setting-content-extended">
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="facebook"}}
|
||||
<input value={{model.facebook}} oninput={{action (mut _scratchFacebook) value="target.value"}} {{action "validateFacebookUrl" on="focusOut"}} type="url" class="gh-input" placeholder="https://www.facebook.com/ghost" autocorrect="off" data-test-facebook-input />
|
||||
{{gh-error-message errors=model.errors property="facebook" data-test-facebook-error=true}}
|
||||
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="facebook"}}
|
||||
<input value={{settings.facebook}} oninput={{action (mut _scratchFacebook) value="target.value"}} {{action "validateFacebookUrl" on="focusOut"}} type="url" class="gh-input" placeholder="https://www.facebook.com/ghost" autocorrect="off" data-test-facebook-input />
|
||||
{{gh-error-message errors=settings.errors property="facebook" data-test-facebook-error=true}}
|
||||
<p>URL of your publication's Facebook Page</p>
|
||||
{{/gh-form-group}}
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="twitter"}}
|
||||
<input value={{model.twitter}} oninput={{action (mut _scratchTwitter) value="target.value"}} {{action "validateTwitterUrl" on="focusOut"}} type="url" class="gh-input" placeholder="https://twitter.com/tryghost" autocorrect="off" data-test-twitter-input />
|
||||
{{gh-error-message errors=model.errors property="twitter" data-test-twitter-error=true}}
|
||||
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="twitter"}}
|
||||
<input value={{settings.twitter}} oninput={{action (mut _scratchTwitter) value="target.value"}} {{action "validateTwitterUrl" on="focusOut"}} type="url" class="gh-input" placeholder="https://twitter.com/tryghost" autocorrect="off" data-test-twitter-input />
|
||||
{{gh-error-message errors=settings.errors property="twitter" data-test-twitter-error=true}}
|
||||
<p>URL of your publication's Twitter profile</p>
|
||||
{{/gh-form-group}}
|
||||
</div>
|
||||
|
@ -221,7 +221,7 @@
|
|||
<div class="gh-setting-desc">
|
||||
Enable protection with simple shared password, All search engine optimization and social features will be disabled.
|
||||
|
||||
{{#if model.isPrivate}}
|
||||
{{#if settings.isPrivate}}
|
||||
<span class="avoid-break-out">
|
||||
<br><br>
|
||||
A private RSS feed is available at
|
||||
|
@ -230,11 +230,11 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if model.isPrivate}}
|
||||
{{#if settings.isPrivate}}
|
||||
<div class="gh-setting-content-extended">
|
||||
{{#gh-form-group errors=model.errors hasValidated=model.hasValidated property="password"}}
|
||||
{{gh-input model.password name="general[password]" type="text" focusOut=(action "validate" "password" target=model) update=(action (mut model.password)) data-test-password-input=true}}
|
||||
{{gh-error-message errors=model.errors property="password" data-test-password-error=true}}
|
||||
{{#gh-form-group errors=settings.errors hasValidated=settings.hasValidated property="password"}}
|
||||
{{gh-input settings.password name="general[password]" type="text" focusOut=(action "validate" "password" target=settings) update=(action (mut settings.password)) data-test-password-input=true}}
|
||||
{{gh-error-message errors=settings.errors property="password" data-test-password-error=true}}
|
||||
<p>Set the password for this site</p>
|
||||
{{/gh-form-group}}
|
||||
</div>
|
||||
|
@ -243,7 +243,7 @@
|
|||
<div class="gh-setting-action">
|
||||
<div class="for-checkbox">
|
||||
<label class="checkbox" for="settings-private">
|
||||
{{one-way-checkbox model.isPrivate id="settings-private" type="checkbox" update=(action (mut model.isPrivate)) data-test-private-checkbox=true}}
|
||||
{{one-way-checkbox settings.isPrivate id="settings-private" type="checkbox" update=(action (mut settings.isPrivate)) data-test-private-checkbox=true}}
|
||||
<span class="input-toggle-component"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div class="gh-flow-content-wrap">
|
||||
<section class="gh-flow-content">
|
||||
<form id="login" method="post" class="gh-signin" novalidate="novalidate" {{action "authenticate" on="submit"}}>
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="identification"}}
|
||||
{{#gh-form-group errors=signin.errors hasValidated=hasValidated property="identification"}}
|
||||
<span class="gh-input-icon gh-icon-mail">
|
||||
{{inline-svg "email"}}
|
||||
{{gh-trim-focus-input model.identification
|
||||
{{gh-trim-focus-input signin.identification
|
||||
class="email"
|
||||
type="email"
|
||||
placeholder="Email Address"
|
||||
|
@ -14,20 +14,20 @@
|
|||
autocorrect="off"
|
||||
tabindex="1"
|
||||
focusOut=(action "validate" "identification")
|
||||
update=(action (mut model.identification))}}
|
||||
update=(action (mut signin.identification))}}
|
||||
</span>
|
||||
{{/gh-form-group}}
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="password"}}
|
||||
{{#gh-form-group errors=signin.errors hasValidated=hasValidated property="password"}}
|
||||
<span class="gh-input-icon gh-icon-lock forgotten-wrap">
|
||||
{{inline-svg "lock"}}
|
||||
{{gh-input model.password
|
||||
{{gh-input signin.password
|
||||
class="password"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
name="password"
|
||||
tabindex="2"
|
||||
autocorrect="off"
|
||||
update=(action (mut model.password))}}
|
||||
update=(action (mut signin.password))}}
|
||||
|
||||
{{#gh-task-button
|
||||
task=forgotten
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
<input style="display:none;" type="text" name="fakeusernameremembered"/>
|
||||
<input style="display:none;" type="password" name="fakepasswordremembered"/>
|
||||
|
||||
{{gh-profile-image email=model.email setImage=(action "setImage")}}
|
||||
{{gh-profile-image email=signupDetails.email setImage=(action "setImage")}}
|
||||
|
||||
{{#gh-form-group}}
|
||||
{{#gh-form-group errors=signupDetails.errors hasValidated=hasValidated property="email"}}
|
||||
<label for="email-address">Email address</label>
|
||||
<span class="gh-input-icon gh-icon-mail">
|
||||
{{inline-svg "email"}}
|
||||
{{gh-input model.email
|
||||
{{gh-input signupDetails.email
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Eg. john@example.com"
|
||||
|
@ -26,11 +26,11 @@
|
|||
</span>
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="name"}}
|
||||
{{#gh-form-group errors=signupDetails.errors hasValidated=hasValidated property="name"}}
|
||||
<label for="full-name">Full name</label>
|
||||
<span class="gh-input-icon gh-icon-user">
|
||||
{{inline-svg "user-circle"}}
|
||||
{{gh-trim-focus-input model.name
|
||||
{{gh-trim-focus-input signupDetails.name
|
||||
tabindex="1"
|
||||
type="text"
|
||||
name="name"
|
||||
|
@ -38,16 +38,16 @@
|
|||
autocorrect="off"
|
||||
onenter=(action "signup")
|
||||
focusOut=(action "validate" "name")
|
||||
update=(action (mut model.name))}}
|
||||
update=(action (mut signupDetails.name))}}
|
||||
</span>
|
||||
{{gh-error-message errors=model.errors property="name"}}
|
||||
{{gh-error-message errors=signupDetails.errors property="name"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="password"}}
|
||||
{{#gh-form-group errors=signupDetails.errors hasValidated=hasValidated property="password"}}
|
||||
<label for="password">Password</label>
|
||||
<span class="gh-input-icon gh-icon-lock">
|
||||
{{inline-svg "lock"}}
|
||||
{{gh-input model.password
|
||||
{{gh-input signupDetails.password
|
||||
tabindex="2"
|
||||
type="password"
|
||||
name="password"
|
||||
|
@ -55,9 +55,9 @@
|
|||
onenter=(action "signup")
|
||||
autocorrect="off"
|
||||
focusOut=(action "validate" "password")
|
||||
update=(action (mut model.password))}}
|
||||
update=(action (mut signupDetails.password))}}
|
||||
</span>
|
||||
{{gh-error-message errors=model.errors property="password"}}
|
||||
{{gh-error-message errors=signupDetails.errors property="password"}}
|
||||
{{/gh-form-group}}
|
||||
</form>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{{gh-fullscreen-modal "new-subscriber"
|
||||
model=model
|
||||
model=subscriber
|
||||
confirm=(route-action "save")
|
||||
close=(route-action "cancel")
|
||||
modifier="action wide"}}
|
||||
|
|
|
@ -156,7 +156,7 @@ describe('Acceptance: Settings - Design', function () {
|
|||
|
||||
expect(
|
||||
find('.gh-blognav-url:last input').val()
|
||||
).to.equal(`${window.location.protocol}//${window.location.host}/new`);
|
||||
).to.equal(`${window.location.origin}/new`);
|
||||
|
||||
await click('.gh-blognav-add');
|
||||
|
||||
|
@ -173,7 +173,7 @@ describe('Acceptance: Settings - Design', function () {
|
|||
expect(
|
||||
find('.gh-blognav-url:last input').val(),
|
||||
'new item url value after successful add'
|
||||
).to.equal(`${window.location.protocol}//${window.location.host}/`);
|
||||
).to.equal(`${window.location.origin}/`);
|
||||
|
||||
expect(
|
||||
find('.gh-blognav-item .response:visible').length,
|
||||
|
|
|
@ -362,7 +362,7 @@ describe('Acceptance: Team', function () {
|
|||
await visit('/team');
|
||||
await click(`[data-test-user-id="${suspendedUser.id}"]`);
|
||||
|
||||
expect('[data-test-suspended-badge]').to.exist;
|
||||
expect(find('[data-test-suspended-badge]')).to.exist;
|
||||
|
||||
await click('[data-test-user-actions]');
|
||||
await click('[data-test-unsuspend-button]');
|
||||
|
@ -376,7 +376,6 @@ describe('Acceptance: Team', function () {
|
|||
// });
|
||||
|
||||
await click('[data-test-team-link]');
|
||||
|
||||
// suspendedUser is now in active list
|
||||
expect(
|
||||
find(`[data-test-active-users] [data-test-user-id="${suspendedUser.id}"]`)
|
||||
|
@ -392,8 +391,7 @@ describe('Acceptance: Team', function () {
|
|||
await click('[data-test-user-actions]');
|
||||
await click('[data-test-suspend-button]');
|
||||
await click('[data-test-modal-confirm]');
|
||||
|
||||
expect('[data-test-suspended-badge]').to.exist;
|
||||
expect(find('[data-test-suspended-badge]')).to.exist;
|
||||
});
|
||||
|
||||
it('can delete users', async function () {
|
||||
|
|
|
@ -17,18 +17,18 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
needs: ['service:notifications', 'service:slug-generator', 'service:settings']
|
||||
});
|
||||
|
||||
it('slugValue is one-way bound to model.slug', function () {
|
||||
it('slugValue is one-way bound to post.slug', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'a-slug'
|
||||
})
|
||||
});
|
||||
|
||||
expect(component.get('model.slug')).to.equal('a-slug');
|
||||
expect(component.get('post.slug')).to.equal('a-slug');
|
||||
expect(component.get('slugValue')).to.equal('a-slug');
|
||||
|
||||
run(function () {
|
||||
component.set('model.slug', 'changed-slug');
|
||||
component.set('post.slug', 'changed-slug');
|
||||
|
||||
expect(component.get('slugValue')).to.equal('changed-slug');
|
||||
});
|
||||
|
@ -36,31 +36,31 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.set('slugValue', 'changed-directly');
|
||||
|
||||
expect(component.get('model.slug')).to.equal('changed-slug');
|
||||
expect(component.get('post.slug')).to.equal('changed-slug');
|
||||
expect(component.get('slugValue')).to.equal('changed-directly');
|
||||
});
|
||||
|
||||
run(function () {
|
||||
// test that the one-way binding is still in place
|
||||
component.set('model.slug', 'should-update');
|
||||
component.set('post.slug', 'should-update');
|
||||
|
||||
expect(component.get('slugValue')).to.equal('should-update');
|
||||
});
|
||||
});
|
||||
|
||||
it('metaTitleScratch is one-way bound to model.metaTitle', function () {
|
||||
it('metaTitleScratch is one-way bound to post.metaTitle', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
metaTitle: 'a title',
|
||||
metaTitleScratch: boundOneWay('metaTitle')
|
||||
}).create()
|
||||
});
|
||||
|
||||
expect(component.get('model.metaTitle')).to.equal('a title');
|
||||
expect(component.get('post.metaTitle')).to.equal('a title');
|
||||
expect(component.get('metaTitleScratch')).to.equal('a title');
|
||||
|
||||
run(function () {
|
||||
component.set('model.metaTitle', 'a different title');
|
||||
component.set('post.metaTitle', 'a different title');
|
||||
|
||||
expect(component.get('metaTitleScratch')).to.equal('a different title');
|
||||
});
|
||||
|
@ -68,31 +68,31 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.set('metaTitleScratch', 'changed directly');
|
||||
|
||||
expect(component.get('model.metaTitle')).to.equal('a different title');
|
||||
expect(component.get('model.metaTitleScratch')).to.equal('changed directly');
|
||||
expect(component.get('post.metaTitle')).to.equal('a different title');
|
||||
expect(component.get('post.metaTitleScratch')).to.equal('changed directly');
|
||||
});
|
||||
|
||||
run(function () {
|
||||
// test that the one-way binding is still in place
|
||||
component.set('model.metaTitle', 'should update');
|
||||
component.set('post.metaTitle', 'should update');
|
||||
|
||||
expect(component.get('metaTitleScratch')).to.equal('should update');
|
||||
});
|
||||
});
|
||||
|
||||
it('metaDescriptionScratch is one-way bound to model.metaDescription', function () {
|
||||
it('metaDescriptionScratch is one-way bound to post.metaDescription', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
metaDescription: 'a description',
|
||||
metaDescriptionScratch: boundOneWay('metaDescription')
|
||||
}).create()
|
||||
});
|
||||
|
||||
expect(component.get('model.metaDescription')).to.equal('a description');
|
||||
expect(component.get('post.metaDescription')).to.equal('a description');
|
||||
expect(component.get('metaDescriptionScratch')).to.equal('a description');
|
||||
|
||||
run(function () {
|
||||
component.set('model.metaDescription', 'a different description');
|
||||
component.set('post.metaDescription', 'a different description');
|
||||
|
||||
expect(component.get('metaDescriptionScratch')).to.equal('a different description');
|
||||
});
|
||||
|
@ -100,13 +100,13 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.set('metaDescriptionScratch', 'changed directly');
|
||||
|
||||
expect(component.get('model.metaDescription')).to.equal('a different description');
|
||||
expect(component.get('post.metaDescription')).to.equal('a different description');
|
||||
expect(component.get('metaDescriptionScratch')).to.equal('changed directly');
|
||||
});
|
||||
|
||||
run(function () {
|
||||
// test that the one-way binding is still in place
|
||||
component.set('model.metaDescription', 'should update');
|
||||
component.set('post.metaDescription', 'should update');
|
||||
|
||||
expect(component.get('metaDescriptionScratch')).to.equal('should update');
|
||||
});
|
||||
|
@ -115,7 +115,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
describe('seoTitle', function () {
|
||||
it('should be the metaTitle if one exists', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
metaTitle: 'a meta-title',
|
||||
metaTitleScratch: boundOneWay('metaTitle'),
|
||||
titleScratch: 'should not be used'
|
||||
|
@ -127,7 +127,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
|
||||
it('should default to the title if an explicit meta-title does not exist', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
titleScratch: 'should be the meta-title'
|
||||
})
|
||||
});
|
||||
|
@ -137,7 +137,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
|
||||
it('should be the metaTitle if both title and metaTitle exist', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
metaTitle: 'a meta-title',
|
||||
metaTitleScratch: boundOneWay('metaTitle'),
|
||||
titleScratch: 'a title'
|
||||
|
@ -149,7 +149,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
|
||||
it('should revert to the title if explicit metaTitle is removed', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
metaTitle: 'a meta-title',
|
||||
metaTitleScratch: boundOneWay('metaTitle'),
|
||||
titleScratch: 'a title'
|
||||
|
@ -159,7 +159,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
expect(component.get('seoTitle')).to.equal('a meta-title');
|
||||
|
||||
run(function () {
|
||||
component.set('model.metaTitle', '');
|
||||
component.set('post.metaTitle', '');
|
||||
|
||||
expect(component.get('seoTitle')).to.equal('a title');
|
||||
});
|
||||
|
@ -168,7 +168,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
it('should truncate to 70 characters with an appended ellipsis', function () {
|
||||
let longTitle = new Array(100).join('a');
|
||||
let component = this.subject({
|
||||
model: EmberObject.create()
|
||||
post: EmberObject.create()
|
||||
});
|
||||
|
||||
expect(longTitle.length).to.equal(99);
|
||||
|
@ -187,7 +187,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
describe('seoDescription', function () {
|
||||
it('should be the metaDescription if one exists', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
metaDescription: 'a description',
|
||||
metaDescriptionScratch: boundOneWay('metaDescription')
|
||||
}).create()
|
||||
|
@ -198,7 +198,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
|
||||
it('should be generated from the rendered mobiledoc if not explicitly set', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.extend({
|
||||
post: EmberObject.extend({
|
||||
author: RSVP.resolve(),
|
||||
metaDescription: null,
|
||||
metaDescriptionScratch: boundOneWay('metaDescription'),
|
||||
|
@ -222,7 +222,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
it('should truncate to 156 characters with an appended ellipsis', function () {
|
||||
let longDescription = new Array(200).join('a');
|
||||
let component = this.subject({
|
||||
model: EmberObject.create()
|
||||
post: EmberObject.create()
|
||||
});
|
||||
|
||||
expect(longDescription.length).to.equal(199);
|
||||
|
@ -242,7 +242,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
it('should be the URL of the blog if no post slug exists', function () {
|
||||
let component = this.subject({
|
||||
config: EmberObject.create({blogUrl: 'http://my-ghost-blog.com'}),
|
||||
model: EmberObject.create()
|
||||
post: EmberObject.create()
|
||||
});
|
||||
|
||||
expect(component.get('seoURL')).to.equal('http://my-ghost-blog.com/');
|
||||
|
@ -251,7 +251,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
it('should be the URL of the blog plus the post slug', function () {
|
||||
let component = this.subject({
|
||||
config: EmberObject.create({blogUrl: 'http://my-ghost-blog.com'}),
|
||||
model: EmberObject.create({slug: 'post-slug'})
|
||||
post: EmberObject.create({slug: 'post-slug'})
|
||||
});
|
||||
|
||||
expect(component.get('seoURL')).to.equal('http://my-ghost-blog.com/post-slug/');
|
||||
|
@ -260,13 +260,13 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
it('should update when the post slug changes', function () {
|
||||
let component = this.subject({
|
||||
config: EmberObject.create({blogUrl: 'http://my-ghost-blog.com'}),
|
||||
model: EmberObject.create({slug: 'post-slug'})
|
||||
post: EmberObject.create({slug: 'post-slug'})
|
||||
});
|
||||
|
||||
expect(component.get('seoURL')).to.equal('http://my-ghost-blog.com/post-slug/');
|
||||
|
||||
run(function () {
|
||||
component.set('model.slug', 'changed-slug');
|
||||
component.set('post.slug', 'changed-slug');
|
||||
|
||||
expect(component.get('seoURL')).to.equal('http://my-ghost-blog.com/changed-slug/');
|
||||
});
|
||||
|
@ -277,7 +277,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
let longSlug = new Array(75).join('a');
|
||||
let component = this.subject({
|
||||
config: EmberObject.create({blogUrl: blogURL}),
|
||||
model: EmberObject.create({slug: longSlug})
|
||||
post: EmberObject.create({slug: longSlug})
|
||||
});
|
||||
let expected;
|
||||
|
||||
|
@ -294,24 +294,24 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
describe('togglePage', function () {
|
||||
it('should toggle the page property', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
page: false,
|
||||
isNew: true
|
||||
})
|
||||
});
|
||||
|
||||
expect(component.get('model.page')).to.not.be.ok;
|
||||
expect(component.get('post.page')).to.not.be.ok;
|
||||
|
||||
run(function () {
|
||||
component.send('togglePage');
|
||||
|
||||
expect(component.get('model.page')).to.be.ok;
|
||||
expect(component.get('post.page')).to.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
it('should not save the post if it is still new', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
page: false,
|
||||
isNew: true,
|
||||
save() {
|
||||
|
@ -324,14 +324,14 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.send('togglePage');
|
||||
|
||||
expect(component.get('model.page')).to.be.ok;
|
||||
expect(component.get('model.saved')).to.not.be.ok;
|
||||
expect(component.get('post.page')).to.be.ok;
|
||||
expect(component.get('post.saved')).to.not.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
it('should save the post if it is not new', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
page: false,
|
||||
isNew: false,
|
||||
save() {
|
||||
|
@ -344,8 +344,8 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.send('togglePage');
|
||||
|
||||
expect(component.get('model.page')).to.be.ok;
|
||||
expect(component.get('model.saved')).to.equal(1);
|
||||
expect(component.get('post.page')).to.be.ok;
|
||||
expect(component.get('post.saved')).to.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -353,7 +353,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
describe('toggleFeatured', function () {
|
||||
it('should toggle the featured property', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
featured: false,
|
||||
isNew: true
|
||||
})
|
||||
|
@ -362,13 +362,13 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.send('toggleFeatured');
|
||||
|
||||
expect(component.get('model.featured')).to.be.ok;
|
||||
expect(component.get('post.featured')).to.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
it('should not save the post if it is still new', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
featured: false,
|
||||
isNew: true,
|
||||
save() {
|
||||
|
@ -381,14 +381,14 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.send('toggleFeatured');
|
||||
|
||||
expect(component.get('model.featured')).to.be.ok;
|
||||
expect(component.get('model.saved')).to.not.be.ok;
|
||||
expect(component.get('post.featured')).to.be.ok;
|
||||
expect(component.get('post.saved')).to.not.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
it('should save the post if it is not new', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
featured: false,
|
||||
isNew: false,
|
||||
save() {
|
||||
|
@ -401,8 +401,8 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
run(function () {
|
||||
component.send('toggleFeatured');
|
||||
|
||||
expect(component.get('model.featured')).to.be.ok;
|
||||
expect(component.get('model.saved')).to.equal(1);
|
||||
expect(component.get('post.featured')).to.be.ok;
|
||||
expect(component.get('post.saved')).to.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -410,7 +410,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
describe('updateSlug', function () {
|
||||
it('should reset slugValue to the previous slug when the new slug is blank or unchanged', function () {
|
||||
let component = this.subject({
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'slug'
|
||||
})
|
||||
});
|
||||
|
@ -420,7 +420,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.set('slugValue', 'slug');
|
||||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
expect(component.get('model.slug')).to.equal('slug');
|
||||
expect(component.get('post.slug')).to.equal('slug');
|
||||
expect(component.get('slugValue')).to.equal('slug');
|
||||
});
|
||||
|
||||
|
@ -429,7 +429,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.set('slugValue', 'slug ');
|
||||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
expect(component.get('model.slug')).to.equal('slug');
|
||||
expect(component.get('post.slug')).to.equal('slug');
|
||||
expect(component.get('slugValue')).to.equal('slug');
|
||||
});
|
||||
|
||||
|
@ -438,7 +438,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.set('slugValue', '');
|
||||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
expect(component.get('model.slug')).to.equal('slug');
|
||||
expect(component.get('post.slug')).to.equal('slug');
|
||||
expect(component.get('slugValue')).to.equal('slug');
|
||||
});
|
||||
});
|
||||
|
@ -452,7 +452,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
return promise;
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'whatever'
|
||||
})
|
||||
});
|
||||
|
@ -462,7 +462,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
RSVP.resolve(component.get('lastPromise')).then(function () {
|
||||
expect(component.get('model.slug')).to.equal('whatever');
|
||||
expect(component.get('post.slug')).to.equal('whatever');
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -479,7 +479,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
return promise;
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'whatever'
|
||||
})
|
||||
});
|
||||
|
@ -489,7 +489,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
RSVP.resolve(component.get('lastPromise')).then(function () {
|
||||
expect(component.get('model.slug')).to.equal('whatever');
|
||||
expect(component.get('post.slug')).to.equal('whatever');
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -505,7 +505,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
return promise;
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'whatever',
|
||||
save: K
|
||||
})
|
||||
|
@ -516,7 +516,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
RSVP.resolve(component.get('lastPromise')).then(function () {
|
||||
expect(component.get('model.slug')).to.equal('changed');
|
||||
expect(component.get('post.slug')).to.equal('changed');
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -532,7 +532,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
return promise;
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'whatever',
|
||||
saved: 0,
|
||||
isNew: false,
|
||||
|
@ -547,8 +547,8 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
RSVP.resolve(component.get('lastPromise')).then(function () {
|
||||
expect(component.get('model.slug')).to.equal('changed');
|
||||
expect(component.get('model.saved')).to.equal(1);
|
||||
expect(component.get('post.slug')).to.equal('changed');
|
||||
expect(component.get('post.saved')).to.equal(1);
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -564,7 +564,7 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
return promise;
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'whatever',
|
||||
saved: 0,
|
||||
isNew: true,
|
||||
|
@ -579,8 +579,8 @@ describe.skip('Unit: Component: post-settings-menu', function () {
|
|||
component.send('updateSlug', component.get('slugValue'));
|
||||
|
||||
RSVP.resolve(component.get('lastPromise')).then(function () {
|
||||
expect(component.get('model.slug')).to.equal('changed');
|
||||
expect(component.get('model.saved')).to.equal(0);
|
||||
expect(component.get('post.slug')).to.equal('changed');
|
||||
expect(component.get('post.saved')).to.equal(0);
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
|
|
@ -26,7 +26,8 @@ describe('Unit: Controller: settings/design', function () {
|
|||
'service:ghostPaths',
|
||||
'service:notifications',
|
||||
'service:session',
|
||||
'service:upgrade-status'
|
||||
'service:upgrade-status',
|
||||
'service:settings'
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -55,19 +56,19 @@ describe('Unit: Controller: settings/design', function () {
|
|||
let ctrl = this.subject();
|
||||
|
||||
run(() => {
|
||||
ctrl.set('model', EmberObject.create({navigation: [
|
||||
ctrl.set('settings', EmberObject.create({navigation: [
|
||||
NavItem.create({label: 'First', url: '/'}),
|
||||
NavItem.create({label: '', url: '/second'}),
|
||||
NavItem.create({label: 'Third', url: ''})
|
||||
]}));
|
||||
// blank item won't get added because the last item is incomplete
|
||||
expect(ctrl.get('model.navigation.length')).to.equal(3);
|
||||
expect(ctrl.get('settings.navigation.length')).to.equal(3);
|
||||
|
||||
ctrl.get('save').perform().then(function passedValidation() {
|
||||
assert(false, 'navigationItems weren\'t validated on save');
|
||||
done();
|
||||
}).catch(function failedValidation() {
|
||||
let navItems = ctrl.get('model.navigation');
|
||||
let navItems = ctrl.get('settings.navigation');
|
||||
expect(navItems[0].get('errors').toArray()).to.be.empty;
|
||||
expect(navItems[1].get('errors.firstObject.attribute')).to.equal('label');
|
||||
expect(navItems[2].get('errors.firstObject.attribute')).to.equal('url');
|
||||
|
@ -80,18 +81,18 @@ describe('Unit: Controller: settings/design', function () {
|
|||
let ctrl = this.subject();
|
||||
|
||||
run(() => {
|
||||
ctrl.set('model', EmberObject.create({navigation: [
|
||||
ctrl.set('settings', EmberObject.create({navigation: [
|
||||
NavItem.create({label: 'First', url: '/'}),
|
||||
NavItem.create({label: '', url: ''})
|
||||
]}));
|
||||
|
||||
expect(ctrl.get('model.navigation.length')).to.equal(2);
|
||||
expect(ctrl.get('settings.navigation.length')).to.equal(2);
|
||||
|
||||
ctrl.get('save').perform().then(function passedValidation() {
|
||||
assert(false, 'navigationItems weren\'t validated on save');
|
||||
done();
|
||||
}).catch(function failedValidation() {
|
||||
let navItems = ctrl.get('model.navigation');
|
||||
let navItems = ctrl.get('settings.navigation');
|
||||
expect(navItems[0].get('errors').toArray()).to.be.empty;
|
||||
done();
|
||||
});
|
||||
|
@ -102,12 +103,12 @@ describe('Unit: Controller: settings/design', function () {
|
|||
let ctrl = this.subject();
|
||||
|
||||
run(() => {
|
||||
ctrl.set('model', EmberObject.create({navigation: [
|
||||
ctrl.set('settings', EmberObject.create({navigation: [
|
||||
NavItem.create({label: 'First', url: '/first', last: true})
|
||||
]}));
|
||||
});
|
||||
|
||||
expect(ctrl.get('model.navigation.length')).to.equal(1);
|
||||
expect(ctrl.get('settings.navigation.length')).to.equal(1);
|
||||
|
||||
ctrl.set('newNavItem.label', 'New');
|
||||
ctrl.set('newNavItem.url', '/new');
|
||||
|
@ -116,10 +117,10 @@ describe('Unit: Controller: settings/design', function () {
|
|||
ctrl.send('addNavItem');
|
||||
});
|
||||
|
||||
expect(ctrl.get('model.navigation.length')).to.equal(2);
|
||||
expect(ctrl.get('model.navigation.lastObject.label')).to.equal('New');
|
||||
expect(ctrl.get('model.navigation.lastObject.url')).to.equal('/new');
|
||||
expect(ctrl.get('model.navigation.lastObject.isNew')).to.be.false;
|
||||
expect(ctrl.get('settings.navigation.length')).to.equal(2);
|
||||
expect(ctrl.get('settings.navigation.lastObject.label')).to.equal('New');
|
||||
expect(ctrl.get('settings.navigation.lastObject.url')).to.equal('/new');
|
||||
expect(ctrl.get('settings.navigation.lastObject.isNew')).to.be.false;
|
||||
expect(ctrl.get('newNavItem.label')).to.be.blank;
|
||||
expect(ctrl.get('newNavItem.url')).to.be.blank;
|
||||
expect(ctrl.get('newNavItem.isNew')).to.be.true;
|
||||
|
@ -129,12 +130,12 @@ describe('Unit: Controller: settings/design', function () {
|
|||
let ctrl = this.subject();
|
||||
|
||||
run(() => {
|
||||
ctrl.set('model', EmberObject.create({navigation: [
|
||||
ctrl.set('settings', EmberObject.create({navigation: [
|
||||
NavItem.create({label: '', url: '', last: true})
|
||||
]}));
|
||||
expect(ctrl.get('model.navigation.length')).to.equal(1);
|
||||
expect(ctrl.get('settings.navigation.length')).to.equal(1);
|
||||
ctrl.send('addNavItem');
|
||||
expect(ctrl.get('model.navigation.length')).to.equal(1);
|
||||
expect(ctrl.get('settings.navigation.length')).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -146,10 +147,10 @@ describe('Unit: Controller: settings/design', function () {
|
|||
];
|
||||
|
||||
run(() => {
|
||||
ctrl.set('model', EmberObject.create({navigation: navItems}));
|
||||
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['First', 'Second']);
|
||||
ctrl.send('deleteNavItem', ctrl.get('model.navigation.firstObject'));
|
||||
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['Second']);
|
||||
ctrl.set('settings', EmberObject.create({navigation: navItems}));
|
||||
expect(ctrl.get('settings.navigation').mapBy('label')).to.deep.equal(['First', 'Second']);
|
||||
ctrl.send('deleteNavItem', ctrl.get('settings.navigation.firstObject'));
|
||||
expect(ctrl.get('settings.navigation').mapBy('label')).to.deep.equal(['Second']);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -161,10 +162,10 @@ describe('Unit: Controller: settings/design', function () {
|
|||
];
|
||||
|
||||
run(() => {
|
||||
ctrl.set('model', EmberObject.create({navigation: navItems}));
|
||||
expect(ctrl.get('model.navigation').mapBy('url')).to.deep.equal(['/first', '/second']);
|
||||
ctrl.send('updateUrl', '/new', ctrl.get('model.navigation.firstObject'));
|
||||
expect(ctrl.get('model.navigation').mapBy('url')).to.deep.equal(['/new', '/second']);
|
||||
ctrl.set('settings', EmberObject.create({navigation: navItems}));
|
||||
expect(ctrl.get('settings.navigation').mapBy('url')).to.deep.equal(['/first', '/second']);
|
||||
ctrl.send('updateUrl', '/new', ctrl.get('settings.navigation.firstObject'));
|
||||
expect(ctrl.get('settings.navigation').mapBy('url')).to.deep.equal(['/new', '/second']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,13 +9,14 @@ describe('Unit: Controller: settings/general', function () {
|
|||
'service:config',
|
||||
'service:ghostPaths',
|
||||
'service:notifications',
|
||||
'service:session'
|
||||
'service:session',
|
||||
'service:settings'
|
||||
]
|
||||
});
|
||||
|
||||
it('isDatedPermalinks should be correct', function () {
|
||||
let controller = this.subject({
|
||||
model: EmberObject.create({
|
||||
settings: EmberObject.create({
|
||||
permalinks: '/:year/:month/:day/:slug/'
|
||||
})
|
||||
});
|
||||
|
@ -23,7 +24,7 @@ describe('Unit: Controller: settings/general', function () {
|
|||
expect(controller.get('isDatedPermalinks')).to.be.ok;
|
||||
|
||||
run(function () {
|
||||
controller.set('model.permalinks', '/:slug/');
|
||||
controller.set('settings.permalinks', '/:slug/');
|
||||
|
||||
expect(controller.get('isDatedPermalinks')).to.not.be.ok;
|
||||
});
|
||||
|
@ -31,7 +32,7 @@ describe('Unit: Controller: settings/general', function () {
|
|||
|
||||
it('setting isDatedPermalinks should switch between dated and slug', function () {
|
||||
let controller = this.subject({
|
||||
model: EmberObject.create({
|
||||
settings: EmberObject.create({
|
||||
permalinks: '/:year/:month/:day/:slug/'
|
||||
})
|
||||
});
|
||||
|
@ -40,14 +41,14 @@ describe('Unit: Controller: settings/general', function () {
|
|||
controller.set('isDatedPermalinks', false);
|
||||
|
||||
expect(controller.get('isDatedPermalinks')).to.not.be.ok;
|
||||
expect(controller.get('model.permalinks')).to.equal('/:slug/');
|
||||
expect(controller.get('settings.permalinks')).to.equal('/:slug/');
|
||||
});
|
||||
|
||||
run(function () {
|
||||
controller.set('isDatedPermalinks', true);
|
||||
|
||||
expect(controller.get('isDatedPermalinks')).to.be.ok;
|
||||
expect(controller.get('model.permalinks')).to.equal('/:year/:month/:day/:slug/');
|
||||
expect(controller.get('settings.permalinks')).to.equal('/:year/:month/:day/:slug/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ import {task} from 'ember-concurrency';
|
|||
|
||||
describe('Unit: Mixin: editor-base-controller', function () {
|
||||
describe('generateSlug', function () {
|
||||
it('should generate a slug and set it on the model', function (done) {
|
||||
it('should generate a slug and set it on the post', function (done) {
|
||||
let object;
|
||||
|
||||
run(() => {
|
||||
|
@ -22,19 +22,19 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
return RSVP.resolve(`${str}-slug`);
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({slug: ''})
|
||||
post: EmberObject.create({slug: ''})
|
||||
}).create();
|
||||
|
||||
object.set('model.titleScratch', 'title');
|
||||
object.set('post.titleScratch', 'title');
|
||||
|
||||
expect(object.get('model.slug')).to.equal('');
|
||||
expect(object.get('post.slug')).to.equal('');
|
||||
|
||||
run(() => {
|
||||
object.get('generateSlug').perform();
|
||||
});
|
||||
|
||||
wait().then(() => {
|
||||
expect(object.get('model.slug')).to.equal('title-slug');
|
||||
expect(object.get('post.slug')).to.equal('title-slug');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -50,22 +50,22 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
return RSVP.resolve(`${str}-slug`);
|
||||
}
|
||||
}),
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
slug: 'whatever'
|
||||
})
|
||||
}).create();
|
||||
});
|
||||
|
||||
expect(object.get('model.slug')).to.equal('whatever');
|
||||
expect(object.get('post.slug')).to.equal('whatever');
|
||||
|
||||
object.set('model.titleScratch', '(Untitled)');
|
||||
object.set('post.titleScratch', '(Untitled)');
|
||||
|
||||
run(() => {
|
||||
object.get('generateSlug').perform();
|
||||
});
|
||||
|
||||
wait().then(() => {
|
||||
expect(object.get('model.slug')).to.equal('whatever');
|
||||
expect(object.get('post.slug')).to.equal('whatever');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -77,26 +77,26 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
|
||||
run(() => {
|
||||
object = EmberObject.extend(EditorBaseControllerMixin, {
|
||||
model: EmberObject.create({isNew: true}),
|
||||
post: EmberObject.create({isNew: true}),
|
||||
generateSlug: task(function* () {
|
||||
this.set('model.slug', 'test-slug');
|
||||
this.set('post.slug', 'test-slug');
|
||||
yield RSVP.resolve();
|
||||
})
|
||||
}).create();
|
||||
});
|
||||
|
||||
expect(object.get('model.isNew')).to.be.true;
|
||||
expect(object.get('model.titleScratch')).to.not.be.ok;
|
||||
expect(object.get('post.isNew')).to.be.true;
|
||||
expect(object.get('post.titleScratch')).to.not.be.ok;
|
||||
|
||||
object.set('model.titleScratch', 'test');
|
||||
object.set('post.titleScratch', 'test');
|
||||
|
||||
run(() => {
|
||||
object.get('saveTitle').perform();
|
||||
});
|
||||
|
||||
wait().then(() => {
|
||||
expect(object.get('model.titleScratch')).to.equal('test');
|
||||
expect(object.get('model.slug')).to.equal('test-slug');
|
||||
expect(object.get('post.titleScratch')).to.equal('test');
|
||||
expect(object.get('post.slug')).to.equal('test-slug');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -106,26 +106,26 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
|
||||
run(() => {
|
||||
object = EmberObject.extend(EditorBaseControllerMixin, {
|
||||
model: EmberObject.create({isNew: false, title: '(Untitled)'}),
|
||||
post: EmberObject.create({isNew: false, title: '(Untitled)'}),
|
||||
generateSlug: task(function* () {
|
||||
this.set('model.slug', 'test-slug');
|
||||
this.set('post.slug', 'test-slug');
|
||||
yield RSVP.resolve();
|
||||
})
|
||||
}).create();
|
||||
});
|
||||
|
||||
expect(object.get('model.isNew')).to.be.false;
|
||||
expect(object.get('model.titleScratch')).to.not.be.ok;
|
||||
expect(object.get('post.isNew')).to.be.false;
|
||||
expect(object.get('post.titleScratch')).to.not.be.ok;
|
||||
|
||||
object.set('model.titleScratch', 'New Title');
|
||||
object.set('post.titleScratch', 'New Title');
|
||||
|
||||
run(() => {
|
||||
object.get('saveTitle').perform();
|
||||
});
|
||||
|
||||
wait().then(() => {
|
||||
expect(object.get('model.titleScratch')).to.equal('New Title');
|
||||
expect(object.get('model.slug')).to.equal('test-slug');
|
||||
expect(object.get('post.titleScratch')).to.equal('New Title');
|
||||
expect(object.get('post.slug')).to.equal('test-slug');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -135,7 +135,7 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
|
||||
run(() => {
|
||||
object = EmberObject.extend(EditorBaseControllerMixin, {
|
||||
model: EmberObject.create({
|
||||
post: EmberObject.create({
|
||||
isNew: true,
|
||||
title: 'a title'
|
||||
}),
|
||||
|
@ -147,19 +147,19 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
}).create();
|
||||
});
|
||||
|
||||
expect(object.get('model.isNew')).to.be.true;
|
||||
expect(object.get('model.title')).to.equal('a title');
|
||||
expect(object.get('model.titleScratch')).to.not.be.ok;
|
||||
expect(object.get('post.isNew')).to.be.true;
|
||||
expect(object.get('post.title')).to.equal('a title');
|
||||
expect(object.get('post.titleScratch')).to.not.be.ok;
|
||||
|
||||
object.set('model.titleScratch', 'test');
|
||||
object.set('post.titleScratch', 'test');
|
||||
|
||||
run(() => {
|
||||
object.get('saveTitle').perform();
|
||||
});
|
||||
|
||||
wait().then(() => {
|
||||
expect(object.get('model.titleScratch')).to.equal('test');
|
||||
expect(object.get('model.slug')).to.not.be.ok;
|
||||
expect(object.get('post.titleScratch')).to.equal('test');
|
||||
expect(object.get('post.slug')).to.not.be.ok;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -169,7 +169,7 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
|
||||
run(() => {
|
||||
object = EmberObject.extend(EditorBaseControllerMixin, {
|
||||
model: EmberObject.create({isNew: false}),
|
||||
post: EmberObject.create({isNew: false}),
|
||||
generateSlug: task(function* () {
|
||||
expect(false, 'generateSlug should not be called').to.equal(true);
|
||||
|
||||
|
@ -178,18 +178,18 @@ describe('Unit: Mixin: editor-base-controller', function () {
|
|||
}).create();
|
||||
});
|
||||
|
||||
expect(object.get('model.isNew')).to.be.false;
|
||||
expect(object.get('model.title')).to.not.be.ok;
|
||||
expect(object.get('post.isNew')).to.be.false;
|
||||
expect(object.get('post.title')).to.not.be.ok;
|
||||
|
||||
object.set('model.titleScratch', 'title');
|
||||
object.set('post.titleScratch', 'title');
|
||||
|
||||
run(() => {
|
||||
object.get('saveTitle').perform();
|
||||
});
|
||||
|
||||
wait().then(() => {
|
||||
expect(object.get('model.titleScratch')).to.equal('title');
|
||||
expect(object.get('model.slug')).to.not.be.ok;
|
||||
expect(object.get('post.titleScratch')).to.equal('title');
|
||||
expect(object.get('post.slug')).to.not.be.ok;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue