mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-07 11:30:55 +03:00
commit
4c96fba67f
@ -9,6 +9,7 @@ export default Ember.Component.extend({
|
|||||||
isPublished: null,
|
isPublished: null,
|
||||||
willPublish: null,
|
willPublish: null,
|
||||||
postOrPage: null,
|
postOrPage: null,
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
// Tracks whether we're going to change the state of the post on save
|
// Tracks whether we're going to change the state of the post on save
|
||||||
isDangerous: Ember.computed('isPublished', 'willPublish', function () {
|
isDangerous: Ember.computed('isPublished', 'willPublish', function () {
|
||||||
|
38
core/client/app/components/gh-spin-button.js
Normal file
38
core/client/app/components/gh-spin-button.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: 'button',
|
||||||
|
buttonText: '',
|
||||||
|
submitting: false,
|
||||||
|
autoWidth: true,
|
||||||
|
|
||||||
|
// Disable Button when isLoading equals true
|
||||||
|
attributeBindings: ['disabled'],
|
||||||
|
|
||||||
|
// Must be set on the controller
|
||||||
|
disabled: Ember.computed.equal('submitting', true),
|
||||||
|
|
||||||
|
click: function () {
|
||||||
|
if (this.get('action')) {
|
||||||
|
this.sendAction('action');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
setSize: function () {
|
||||||
|
if (!this.get('submitting') && this.get('autoWidth')) {
|
||||||
|
// this exists so that the spinner doesn't change the size of the button
|
||||||
|
this.$().width(this.$().width()); // sets width of button
|
||||||
|
this.$().height(this.$().height()); // sets height of button
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
width: Ember.observer('buttonText', 'autoWidth', function () {
|
||||||
|
this.setSize();
|
||||||
|
}),
|
||||||
|
|
||||||
|
didInsertElement: function () {
|
||||||
|
this.setSize();
|
||||||
|
}
|
||||||
|
});
|
@ -3,6 +3,7 @@ import ValidationEngine from 'ghost/mixins/validation-engine';
|
|||||||
|
|
||||||
export default Ember.Controller.extend(ValidationEngine, {
|
export default Ember.Controller.extend(ValidationEngine, {
|
||||||
validationType: 'signin',
|
validationType: 'signin',
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
application: Ember.inject.controller(),
|
application: Ember.inject.controller(),
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
@ -28,6 +29,7 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
// it needs to be caught so it doesn't generate an exception in the console,
|
// it needs to be caught so it doesn't generate an exception in the console,
|
||||||
// but it's actually "handled" by the sessionAuthenticationFailed action handler.
|
// but it's actually "handled" by the sessionAuthenticationFailed action handler.
|
||||||
}).finally(function () {
|
}).finally(function () {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
appController.set('skipAuthSuccessHandler', undefined);
|
appController.set('skipAuthSuccessHandler', undefined);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -35,6 +37,8 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
validateAndAuthenticate: function () {
|
validateAndAuthenticate: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
|
||||||
// Manually trigger events for input fields, ensuring legacy compatibility with
|
// Manually trigger events for input fields, ensuring legacy compatibility with
|
||||||
// browsers and password managers that don't send proper events on autofill
|
// browsers and password managers that don't send proper events on autofill
|
||||||
$('#login').find('input').trigger('change');
|
$('#login').find('input').trigger('change');
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import SettingsSaveMixin from 'ghost/mixins/settings-save';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend(SettingsSaveMixin, {
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
|
|
||||||
actions: {
|
save: function () {
|
||||||
save: function () {
|
var notifications = this.get('notifications');
|
||||||
var notifications = this.get('notifications');
|
|
||||||
|
|
||||||
return this.get('model').save().then(function (model) {
|
return this.get('model').save().catch(function (error) {
|
||||||
return model;
|
notifications.showAPIError(error);
|
||||||
}).catch(function (error) {
|
});
|
||||||
notifications.showAPIError(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import SettingsSaveMixin from 'ghost/mixins/settings-save';
|
||||||
import randomPassword from 'ghost/utils/random-password';
|
import randomPassword from 'ghost/utils/random-password';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend(SettingsSaveMixin, {
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
config: Ember.inject.service(),
|
config: Ember.inject.service(),
|
||||||
|
|
||||||
@ -62,26 +63,26 @@ export default Ember.Controller.extend({
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
save: function () {
|
||||||
|
var notifications = this.get('notifications'),
|
||||||
|
config = this.get('config');
|
||||||
|
|
||||||
|
return this.get('model').save().then(function (model) {
|
||||||
|
config.set('blogTitle', model.get('title'));
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}).catch(function (error) {
|
||||||
|
if (error) {
|
||||||
|
notifications.showAPIError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
validate: function () {
|
validate: function () {
|
||||||
this.get('model').validate(arguments);
|
this.get('model').validate(arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
save: function () {
|
|
||||||
var notifications = this.get('notifications'),
|
|
||||||
config = this.get('config');
|
|
||||||
|
|
||||||
return this.get('model').save().then(function (model) {
|
|
||||||
config.set('blogTitle', model.get('title'));
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}).catch(function (error) {
|
|
||||||
if (error) {
|
|
||||||
notifications.showAPIError(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
checkPostsPerPage: function () {
|
checkPostsPerPage: function () {
|
||||||
var postsPerPage = this.get('model.postsPerPage');
|
var postsPerPage = this.get('model.postsPerPage');
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import {request as ajax} from 'ic-ajax';
|
|||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
uploadButtonText: 'Import',
|
uploadButtonText: 'Import',
|
||||||
importErrors: '',
|
importErrors: '',
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
ghostPaths: Ember.inject.service('ghost-paths'),
|
ghostPaths: Ember.inject.service('ghost-paths'),
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
@ -78,18 +79,23 @@ export default Ember.Controller.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
sendTestEmail: function () {
|
sendTestEmail: function () {
|
||||||
var notifications = this.get('notifications');
|
var notifications = this.get('notifications'),
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
|
||||||
ajax(this.get('ghostPaths.url').api('mail', 'test'), {
|
ajax(this.get('ghostPaths.url').api('mail', 'test'), {
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
notifications.showAlert('Check your email for the test message.', {type: 'info'});
|
notifications.showAlert('Check your email for the test message.', {type: 'info'});
|
||||||
|
self.toggleProperty('submitting');
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
if (typeof error.jqXHR !== 'undefined') {
|
if (typeof error.jqXHR !== 'undefined') {
|
||||||
notifications.showAPIError(error);
|
notifications.showAPIError(error);
|
||||||
} else {
|
} else {
|
||||||
notifications.showErrors(error);
|
notifications.showErrors(error);
|
||||||
}
|
}
|
||||||
|
self.toggleProperty('submitting');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import SettingsSaveMixin from 'ghost/mixins/settings-save';
|
||||||
|
|
||||||
var NavItem = Ember.Object.extend({
|
var NavItem = Ember.Object.extend({
|
||||||
label: '',
|
label: '',
|
||||||
@ -10,7 +11,7 @@ var NavItem = Ember.Object.extend({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend(SettingsSaveMixin, {
|
||||||
config: Ember.inject.service(),
|
config: Ember.inject.service(),
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
|
|
||||||
@ -54,6 +55,65 @@ export default Ember.Controller.extend({
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
save: function () {
|
||||||
|
var navSetting,
|
||||||
|
blogUrl = this.get('config').blogUrl,
|
||||||
|
blogUrlRegex = new RegExp('^' + blogUrl + '(.*)', 'i'),
|
||||||
|
navItems = this.get('navigationItems'),
|
||||||
|
message = 'One of your navigation items has an empty label. ' +
|
||||||
|
'<br /> Please enter a new label or delete the item before saving.',
|
||||||
|
match,
|
||||||
|
notifications = this.get('notifications');
|
||||||
|
|
||||||
|
// Don't save if there's a blank label.
|
||||||
|
if (navItems.find(function (item) {return !item.get('isComplete') && !item.get('last');})) {
|
||||||
|
notifications.showAlert(message.htmlSafe(), {type: 'error'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
navSetting = navItems.map(function (item) {
|
||||||
|
var label,
|
||||||
|
url;
|
||||||
|
|
||||||
|
if (!item || !item.get('isComplete')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
label = item.get('label').trim();
|
||||||
|
url = item.get('url').trim();
|
||||||
|
|
||||||
|
// is this an internal URL?
|
||||||
|
match = url.match(blogUrlRegex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
url = match[1];
|
||||||
|
|
||||||
|
// if the last char is not a slash, then add one,
|
||||||
|
// as long as there is no # or . in the URL (anchor or file extension)
|
||||||
|
// this also handles the empty case for the homepage
|
||||||
|
if (url[url.length - 1] !== '/' && url.indexOf('#') === -1 && url.indexOf('.') === -1) {
|
||||||
|
url += '/';
|
||||||
|
}
|
||||||
|
} else if (!validator.isURL(url) && url !== '' && url[0] !== '/' && url.indexOf('mailto:') !== 0) {
|
||||||
|
url = '/' + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {label: label, url: url};
|
||||||
|
}).compact();
|
||||||
|
|
||||||
|
this.set('model.navigation', JSON.stringify(navSetting));
|
||||||
|
|
||||||
|
// trigger change event because even if the final JSON is unchanged
|
||||||
|
// we need to have navigationItems recomputed.
|
||||||
|
this.get('model').notifyPropertyChange('navigation');
|
||||||
|
|
||||||
|
notifications.closeNotifications();
|
||||||
|
|
||||||
|
return this.get('model').save().catch(function (err) {
|
||||||
|
notifications.showErrors(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
addItem: function () {
|
addItem: function () {
|
||||||
var navItems = this.get('navigationItems'),
|
var navItems = this.get('navigationItems'),
|
||||||
@ -94,65 +154,6 @@ export default Ember.Controller.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
navItem.set('url', url);
|
navItem.set('url', url);
|
||||||
},
|
|
||||||
|
|
||||||
save: function () {
|
|
||||||
var navSetting,
|
|
||||||
blogUrl = this.get('config').blogUrl,
|
|
||||||
blogUrlRegex = new RegExp('^' + blogUrl + '(.*)', 'i'),
|
|
||||||
navItems = this.get('navigationItems'),
|
|
||||||
message = 'One of your navigation items has an empty label. ' +
|
|
||||||
'<br /> Please enter a new label or delete the item before saving.',
|
|
||||||
match,
|
|
||||||
notifications = this.get('notifications');
|
|
||||||
|
|
||||||
// Don't save if there's a blank label.
|
|
||||||
if (navItems.find(function (item) {return !item.get('isComplete') && !item.get('last');})) {
|
|
||||||
notifications.showAlert(message.htmlSafe(), {type: 'error'});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
navSetting = navItems.map(function (item) {
|
|
||||||
var label,
|
|
||||||
url;
|
|
||||||
|
|
||||||
if (!item || !item.get('isComplete')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
label = item.get('label').trim();
|
|
||||||
url = item.get('url').trim();
|
|
||||||
|
|
||||||
// is this an internal URL?
|
|
||||||
match = url.match(blogUrlRegex);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
url = match[1];
|
|
||||||
|
|
||||||
// if the last char is not a slash, then add one,
|
|
||||||
// as long as there is no # or . in the URL (anchor or file extension)
|
|
||||||
// this also handles the empty case for the homepage
|
|
||||||
if (url[url.length - 1] !== '/' && url.indexOf('#') === -1 && url.indexOf('.') === -1) {
|
|
||||||
url += '/';
|
|
||||||
}
|
|
||||||
} else if (!validator.isURL(url) && url !== '' && url[0] !== '/' && url.indexOf('mailto:') !== 0) {
|
|
||||||
url = '/' + url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {label: label, url: url};
|
|
||||||
}).compact();
|
|
||||||
|
|
||||||
this.set('model.navigation', JSON.stringify(navSetting));
|
|
||||||
|
|
||||||
// trigger change event because even if the final JSON is unchanged
|
|
||||||
// we need to have navigationItems recomputed.
|
|
||||||
this.get('model').notifyPropertyChange('navigation');
|
|
||||||
|
|
||||||
notifications.closeNotifications();
|
|
||||||
|
|
||||||
this.get('model').save().catch(function (err) {
|
|
||||||
notifications.showErrors(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,7 @@ export default Ember.Controller.extend({
|
|||||||
users: '',
|
users: '',
|
||||||
|
|
||||||
ownerEmail: Ember.computed.alias('two.email'),
|
ownerEmail: Ember.computed.alias('two.email'),
|
||||||
|
submitting: false,
|
||||||
usersArray: Ember.computed('users', function () {
|
usersArray: Ember.computed('users', function () {
|
||||||
var users = this.get('users').split('\n').filter(function (email) {
|
var users = this.get('users').split('\n').filter(function (email) {
|
||||||
return email.trim().length > 0;
|
return email.trim().length > 0;
|
||||||
@ -75,6 +76,7 @@ export default Ember.Controller.extend({
|
|||||||
this.get('errors').clear();
|
this.get('errors').clear();
|
||||||
|
|
||||||
if (validationErrors === true && users.length > 0) {
|
if (validationErrors === true && users.length > 0) {
|
||||||
|
this.toggleProperty('submitting');
|
||||||
this.get('authorRole').then(function (authorRole) {
|
this.get('authorRole').then(function (authorRole) {
|
||||||
Ember.RSVP.Promise.all(
|
Ember.RSVP.Promise.all(
|
||||||
users.map(function (user) {
|
users.map(function (user) {
|
||||||
@ -123,6 +125,8 @@ export default Ember.Controller.extend({
|
|||||||
self.send('loadServerNotifications');
|
self.send('loadServerNotifications');
|
||||||
self.transitionTo('posts.index');
|
self.transitionTo('posts.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.toggleProperty('submitting');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (users.length === 0) {
|
} else if (users.length === 0) {
|
||||||
|
@ -11,6 +11,7 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
password: null,
|
password: null,
|
||||||
image: null,
|
image: null,
|
||||||
blogCreated: false,
|
blogCreated: false,
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
ghostPaths: Ember.inject.service('ghost-paths'),
|
ghostPaths: Ember.inject.service('ghost-paths'),
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
@ -54,6 +55,8 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
config = this.get('config'),
|
config = this.get('config'),
|
||||||
method = this.get('blogCreated') ? 'PUT' : 'POST';
|
method = this.get('blogCreated') ? 'PUT' : 'POST';
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
|
||||||
this.validate().then(function () {
|
this.validate().then(function () {
|
||||||
self.set('showError', false);
|
self.set('showError', false);
|
||||||
ajax({
|
ajax({
|
||||||
@ -80,18 +83,23 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
if (data.image) {
|
if (data.image) {
|
||||||
self.sendImage(result.users[0])
|
self.sendImage(result.users[0])
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
self.transitionToRoute('setup.three');
|
self.transitionToRoute('setup.three');
|
||||||
}).catch(function (resp) {
|
}).catch(function (resp) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
notifications.showAPIError(resp);
|
notifications.showAPIError(resp);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
self.transitionToRoute('setup.three');
|
self.transitionToRoute('setup.three');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).catch(function (resp) {
|
}).catch(function (resp) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
notifications.showAPIError(resp);
|
notifications.showAPIError(resp);
|
||||||
});
|
});
|
||||||
}).catch(function () {
|
}).catch(function () {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
self.set('showError', true);
|
self.set('showError', true);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,7 @@ import {request as ajax} from 'ic-ajax';
|
|||||||
|
|
||||||
export default Ember.Controller.extend(ValidationEngine, {
|
export default Ember.Controller.extend(ValidationEngine, {
|
||||||
submitting: false,
|
submitting: false,
|
||||||
|
loggingIn: false,
|
||||||
|
|
||||||
ghostPaths: Ember.inject.service('ghost-paths'),
|
ghostPaths: Ember.inject.service('ghost-paths'),
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
@ -19,12 +20,15 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
authStrategy = 'simple-auth-authenticator:oauth2-password-grant',
|
authStrategy = 'simple-auth-authenticator:oauth2-password-grant',
|
||||||
data = model.getProperties('identification', 'password');
|
data = model.getProperties('identification', 'password');
|
||||||
|
|
||||||
this.get('session').authenticate(authStrategy, data).catch(function (err) {
|
this.get('session').authenticate(authStrategy, data).then(function () {
|
||||||
|
self.toggleProperty('loggingIn');
|
||||||
|
}).catch(function (err) {
|
||||||
|
self.toggleProperty('loggingIn');
|
||||||
|
|
||||||
if (err.errors) {
|
if (err.errors) {
|
||||||
self.set('flowErrors', err.errors[0].message.string);
|
self.set('flowErrors', err.errors[0].message.string);
|
||||||
}
|
}
|
||||||
|
// if authentication fails a rejected promise will be returned.
|
||||||
// If authentication fails a rejected promise will be returned.
|
|
||||||
// it needs to be caught so it doesn't generate an exception in the console,
|
// it needs to be caught so it doesn't generate an exception in the console,
|
||||||
// but it's actually "handled" by the sessionAuthenticationFailed action handler.
|
// but it's actually "handled" by the sessionAuthenticationFailed action handler.
|
||||||
});
|
});
|
||||||
@ -39,6 +43,7 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
|
|
||||||
this.validate().then(function () {
|
this.validate().then(function () {
|
||||||
self.get('notifications').closeNotifications();
|
self.get('notifications').closeNotifications();
|
||||||
|
self.toggleProperty('loggingIn');
|
||||||
self.send('authenticate');
|
self.send('authenticate');
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -56,7 +61,7 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
|
|
||||||
this.set('flowErrors', '');
|
this.set('flowErrors', '');
|
||||||
this.validate({property: 'identification'}).then(function () {
|
this.validate({property: 'identification'}).then(function () {
|
||||||
self.set('submitting', true);
|
self.toggleProperty('submitting');
|
||||||
|
|
||||||
ajax({
|
ajax({
|
||||||
url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
|
url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
|
||||||
@ -67,10 +72,10 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
self.set('submitting', false);
|
self.toggleProperty('submitting');
|
||||||
notifications.showAlert('Please check your email for instructions.', {type: 'info'});
|
notifications.showAlert('Please check your email for instructions.', {type: 'info'});
|
||||||
}).catch(function (resp) {
|
}).catch(function (resp) {
|
||||||
self.set('submitting', false);
|
self.toggleProperty('submitting');
|
||||||
if (resp && resp.jqXHR && resp.jqXHR.responseJSON && resp.jqXHR.responseJSON.errors) {
|
if (resp && resp.jqXHR && resp.jqXHR.responseJSON && resp.jqXHR.responseJSON.errors) {
|
||||||
self.set('flowErrors', resp.jqXHR.responseJSON.errors[0].message);
|
self.set('flowErrors', resp.jqXHR.responseJSON.errors[0].message);
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,6 +7,7 @@ import ValidationEngine from 'ghost/mixins/validation-engine';
|
|||||||
export default Ember.Controller.extend(ValidationEngine, {
|
export default Ember.Controller.extend(ValidationEngine, {
|
||||||
// ValidationEngine settings
|
// ValidationEngine settings
|
||||||
validationType: 'user',
|
validationType: 'user',
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
ghostPaths: Ember.inject.service('ghost-paths'),
|
ghostPaths: Ember.inject.service('ghost-paths'),
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
@ -103,6 +104,8 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
user.set('slug', slugValue);
|
user.set('slug', slugValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
|
||||||
promise = Ember.RSVP.resolve(afterUpdateSlug).then(function () {
|
promise = Ember.RSVP.resolve(afterUpdateSlug).then(function () {
|
||||||
return user.save({format: false});
|
return user.save({format: false});
|
||||||
}).then(function (model) {
|
}).then(function (model) {
|
||||||
@ -121,11 +124,15 @@ export default Ember.Controller.extend(ValidationEngine, {
|
|||||||
window.history.replaceState({path: newPath}, '', newPath);
|
window.history.replaceState({path: newPath}, '', newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}).catch(function (errors) {
|
}).catch(function (errors) {
|
||||||
if (errors) {
|
if (errors) {
|
||||||
self.get('notifications').showErrors(errors);
|
self.get('notifications').showErrors(errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('lastPromise', promise);
|
this.set('lastPromise', promise);
|
||||||
|
@ -17,6 +17,7 @@ export default Ember.Mixin.create({
|
|||||||
autoSaveId: null,
|
autoSaveId: null,
|
||||||
timedSaveId: null,
|
timedSaveId: null,
|
||||||
editor: null,
|
editor: null,
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
notifications: Ember.inject.service(),
|
notifications: Ember.inject.service(),
|
||||||
|
|
||||||
@ -247,6 +248,8 @@ export default Ember.Mixin.create({
|
|||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
|
||||||
if (options.backgroundSave) {
|
if (options.backgroundSave) {
|
||||||
// do not allow a post's status to be set to published by a background save
|
// do not allow a post's status to be set to published by a background save
|
||||||
status = 'draft';
|
status = 'draft';
|
||||||
@ -294,6 +297,7 @@ export default Ember.Mixin.create({
|
|||||||
self.showSaveNotification(prevStatus, model.get('status'), isNew ? true : false);
|
self.showSaveNotification(prevStatus, model.get('status'), isNew ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.toggleProperty('submitting');
|
||||||
return model;
|
return model;
|
||||||
});
|
});
|
||||||
}).catch(function (errors) {
|
}).catch(function (errors) {
|
||||||
@ -303,6 +307,7 @@ export default Ember.Mixin.create({
|
|||||||
|
|
||||||
self.set('model.status', prevStatus);
|
self.set('model.status', prevStatus);
|
||||||
|
|
||||||
|
self.toggleProperty('submitting');
|
||||||
return self.get('model');
|
return self.get('model');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
17
core/client/app/mixins/settings-save.js
Normal file
17
core/client/app/mixins/settings-save.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Mixin.create({
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
save: function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.set('submitting', true);
|
||||||
|
|
||||||
|
this.save().then(function () {
|
||||||
|
self.set('submitting', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -200,3 +200,27 @@ input[type="reset"].btn-block,
|
|||||||
input[type="button"].btn-block {
|
input[type="button"].btn-block {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Spin Buttons!
|
||||||
|
/* ---------------------------------------------------------- */
|
||||||
|
.spinner {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: -2px 0;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border: rgba(0,0,0,0.2) solid 4px;
|
||||||
|
border-radius: 100px;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner:before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
margin-top: 6px;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background: rgba(0,0,0,0.6);
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
@ -406,6 +406,15 @@ img {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.fade-in {
|
.fade-in {
|
||||||
animation: fade-in 0.2s;
|
animation: fade-in 0.2s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
<button type="button" {{action "save"}} class="btn btn-sm js-publish-button {{if isDangerous 'btn-red' 'btn-blue'}}">
|
{{gh-spin-button type="button" classNameBindings=":btn :btn-sm :js-publish-button isDangerous:btn-red:btn-blue" action="save" buttonText=saveText submitting=submitting}}
|
||||||
{{saveText}}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{{#gh-dropdown-button dropdownName="post-save-menu" classNameBindings=":btn :btn-sm isDangerous:btn-red:btn-blue btnopen:active :dropdown-toggle :up"}}
|
{{#gh-dropdown-button dropdownName="post-save-menu" classNameBindings=":btn :btn-sm isDangerous:btn-red:btn-blue btnopen:active :dropdown-toggle :up"}}
|
||||||
<i class="options icon-arrow2"></i>
|
<i class="options icon-arrow2"></i>
|
||||||
|
9
core/client/app/templates/components/gh-spin-button.hbs
Normal file
9
core/client/app/templates/components/gh-spin-button.hbs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{{#unless submitting}}
|
||||||
|
{{#if buttonText}}
|
||||||
|
{{buttonText}}
|
||||||
|
{{else}}
|
||||||
|
{{{yield}}}
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
<span class="spinner"></span>
|
||||||
|
{{/unless}}
|
@ -16,6 +16,7 @@
|
|||||||
save="save"
|
save="save"
|
||||||
setSaveType="setSaveType"
|
setSaveType="setSaveType"
|
||||||
delete="openDeleteModal"
|
delete="openDeleteModal"
|
||||||
|
submitting=submitting
|
||||||
}}
|
}}
|
||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="password-wrap">
|
<div class="password-wrap">
|
||||||
{{input class="gh-input password" type="password" placeholder="Password" name="password" value=password}}
|
{{input class="gh-input password" type="password" placeholder="Password" name="password" value=password}}
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-blue" type="submit" {{action "validateAndAuthenticate"}} disabled={{submitting}}>Log in</button>
|
{{gh-spin-button class="btn btn-blue" type="submit" action="validateAndAuthenticate" submitting=submitting buttonText="Log in"}}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{/gh-modal-dialog}}
|
{{/gh-modal-dialog}}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
{{input value=ne2Password class="gh-input password" type="password" placeholder="Confirm Password" name="ne2password" focusOut=(action "validate" "ne2Password")}}
|
{{input value=ne2Password class="gh-input password" type="password" placeholder="Confirm Password" name="ne2password" focusOut=(action "validate" "ne2Password")}}
|
||||||
{{gh-error-message errors=errors property="ne2Password"}}
|
{{gh-error-message errors=errors property="ne2Password"}}
|
||||||
{{/gh-form-group}}
|
{{/gh-form-group}}
|
||||||
<button class="btn btn-blue btn-block" type="submit" disabled={{submitting}}>Reset Password</button>
|
{{gh-spin-button class="btn btn-blue btn-block" type="submit" submitting=submitting buttonText="Reset Password" autoWidth=false}}
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<header class="view-header">
|
<header class="view-header">
|
||||||
{{#gh-view-title openMobileMenu="openMobileMenu"}}Code Injection{{/gh-view-title}}
|
{{#gh-view-title openMobileMenu="openMobileMenu"}}Code Injection{{/gh-view-title}}
|
||||||
<section class="view-actions">
|
<section class="view-actions">
|
||||||
<button type="button" class="btn btn-blue" {{action "save"}}>Save</button>
|
{{gh-spin-button type="button" class="btn btn-blue" action="save" buttonText="Save" submitting=submitting}}
|
||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<header class="view-header">
|
<header class="view-header">
|
||||||
{{#gh-view-title openMobileMenu="openMobileMenu"}}General{{/gh-view-title}}
|
{{#gh-view-title openMobileMenu="openMobileMenu"}}General{{/gh-view-title}}
|
||||||
<section class="view-actions">
|
<section class="view-actions">
|
||||||
<button type="button" class="btn btn-blue" {{action "save"}}>Save</button>
|
{{gh-spin-button type="button" class="btn btn-blue" action="save" buttonText="Save" submitting=submitting}}
|
||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Send a test email</label>
|
<label>Send a test email</label>
|
||||||
<button type="button" id="sendtestmail" class="btn btn-blue" {{action "sendTestEmail"}}>Send</button>
|
{{gh-spin-button type="button" id="sendtestemail" class="btn btn-blue" action="sendTestEmail" buttonText="Send" submitting=submitting}}
|
||||||
<p>Sends a test email to your address.</p>
|
<p>Sends a test email to your address.</p>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<header class="view-header">
|
<header class="view-header">
|
||||||
{{#gh-view-title openMobileMenu="openMobileMenu"}}Navigation{{/gh-view-title}}
|
{{#gh-view-title openMobileMenu="openMobileMenu"}}Navigation{{/gh-view-title}}
|
||||||
<section class="view-actions">
|
<section class="view-actions">
|
||||||
<button type="button" class="btn btn-blue" {{action "save"}}>Save</button>
|
{{gh-spin-button type="button" class="btn btn-blue" action="save" buttonText="Save" submitting=submitting}}
|
||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -11,9 +11,8 @@
|
|||||||
{{gh-error-message errors=errors property="users"}}
|
{{gh-error-message errors=errors property="users"}}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button {{action 'invite'}} class="btn btn-default btn-lg btn-block {{buttonClass}}">
|
{{gh-spin-button type="button" classNameBindings=":btn :btn-default :btn-lg :btn-block buttonClass" action="invite" buttonText=buttonText submitting=submitting autoWidth=false}}
|
||||||
{{buttonText}}
|
|
||||||
</button>
|
|
||||||
<button class="gh-flow-skip" {{action "skipInvite"}}>
|
<button class="gh-flow-skip" {{action "skipInvite"}}>
|
||||||
I'll do this later, take me to my blog!
|
I'll do this later, take me to my blog!
|
||||||
</button>
|
</button>
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
{{gh-error-message errors=errors property="blogTitle"}}
|
{{gh-error-message errors=errors property="blogTitle"}}
|
||||||
{{/gh-form-group}}
|
{{/gh-form-group}}
|
||||||
</form>
|
</form>
|
||||||
|
{{#gh-spin-button type="button" class="btn btn-green btn-lg btn-block" action="setup" submitting=submitting autoWidth=false}}
|
||||||
<button type="submit" class="btn btn-green btn-lg btn-block" {{action "setup"}}>Last step: Invite your team <i class="icon-chevron"></i></button>
|
Last step: Invite your team <i class="icon-chevron"></i>
|
||||||
|
{{/gh-spin-button}}
|
||||||
<p class="main-error">{{#if showError}}{{invalidMessage}}{{/if}}</p>
|
<p class="main-error">{{#if showError}}{{invalidMessage}}{{/if}}</p>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</span>
|
</span>
|
||||||
{{gh-error-message errors=model.errors property="password"}}
|
{{gh-error-message errors=model.errors property="password"}}
|
||||||
{{/gh-form-group}}
|
{{/gh-form-group}}
|
||||||
<button id="login-button" class="login btn btn-blue btn-block" type="submit" tabindex="3" disabled={{submitting}}>Sign in</button>
|
{{gh-spin-button class="login btn btn-blue btn-block" type="submit" tabindex="3" buttonText="Sign in" submitting=loggingIn autoWidth=false}}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p class="main-error">{{{flowErrors}}}</p>
|
<p class="main-error">{{{flowErrors}}}</p>
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
{{/gh-form-group}}
|
{{/gh-form-group}}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-green btn-lg btn-block" {{action "signup"}} disabled={{submitting}}>Create Account</button>
|
{{gh-spin-button type="submit" class="btn btn-green btn-lg btn-block" action="signup" submitting=submitting autoWidth=false}}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<button class="btn btn-blue" {{action "save"}}>Save</button>
|
{{gh-spin-button class="btn btn-blue" action="save" buttonText="Save" submitting=submitting}}
|
||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ describeComponent(
|
|||||||
needs: [
|
needs: [
|
||||||
'component:gh-dropdown-button',
|
'component:gh-dropdown-button',
|
||||||
'component:gh-dropdown',
|
'component:gh-dropdown',
|
||||||
|
'component:gh-spin-button',
|
||||||
'service:dropdown'
|
'service:dropdown'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
27
core/client/tests/unit/components/gh-spin-button-test.js
Normal file
27
core/client/tests/unit/components/gh-spin-button-test.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* jshint expr:true */
|
||||||
|
import {expect} from 'chai';
|
||||||
|
import {
|
||||||
|
describeComponent,
|
||||||
|
it
|
||||||
|
} from 'ember-mocha';
|
||||||
|
|
||||||
|
describeComponent(
|
||||||
|
'gh-spin-button',
|
||||||
|
'GhSpinButtonComponent',
|
||||||
|
{
|
||||||
|
// specify the other units that are required for this test
|
||||||
|
// needs: ['component:foo', 'helper:bar']
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
it('renders', function () {
|
||||||
|
// creates the component instance
|
||||||
|
var component = this.subject();
|
||||||
|
|
||||||
|
expect(component._state).to.equal('preRender');
|
||||||
|
|
||||||
|
// renders the component on the page
|
||||||
|
this.render();
|
||||||
|
expect(component._state).to.equal('inDOM');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -273,13 +273,13 @@ CasperTest.begin('Publish menu - new post', 10, function suite(test) {
|
|||||||
// Open the publish options menu;
|
// Open the publish options menu;
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
|
|
||||||
// Select the publish post button
|
// Select the publish post button
|
||||||
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
||||||
|
|
||||||
// ... check status, label, class
|
// ... check status, label, class
|
||||||
casper.waitForSelector('.js-publish-splitbutton', function onSuccess() {
|
casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() {
|
||||||
test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red');
|
test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red');
|
||||||
test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now');
|
test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now');
|
||||||
}, function onTimeout() {
|
}, function onTimeout() {
|
||||||
@ -291,7 +291,7 @@ CasperTest.begin('Publish menu - new post', 10, function suite(test) {
|
|||||||
casper.thenClick('.js-publish-button');
|
casper.thenClick('.js-publish-button');
|
||||||
|
|
||||||
// ... check status, label, class
|
// ... check status, label, class
|
||||||
casper.waitForSelector('.js-publish-splitbutton', function onSuccess() {
|
casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() {
|
||||||
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
|
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
|
||||||
test.assertSelectorHasText('.js-publish-button', 'Update Post', '.js-publish-button says Update Post');
|
test.assertSelectorHasText('.js-publish-button', 'Update Post', '.js-publish-button says Update Post');
|
||||||
}, function onTimeout() {
|
}, function onTimeout() {
|
||||||
@ -329,13 +329,13 @@ CasperTest.begin('Publish menu - new page', 10, function suite(test) {
|
|||||||
// Open the publish options menu;
|
// Open the publish options menu;
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
|
|
||||||
// Select the publish post button
|
// Select the publish post button
|
||||||
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
||||||
|
|
||||||
// ... check status, label, class
|
// ... check status, label, class
|
||||||
casper.waitForSelector('.js-publish-splitbutton', function onSuccess() {
|
casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() {
|
||||||
test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red');
|
test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red');
|
||||||
test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now');
|
test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now');
|
||||||
}, function onTimeout() {
|
}, function onTimeout() {
|
||||||
@ -347,7 +347,7 @@ CasperTest.begin('Publish menu - new page', 10, function suite(test) {
|
|||||||
casper.thenClick('.js-publish-button');
|
casper.thenClick('.js-publish-button');
|
||||||
|
|
||||||
// ... check status, label, class
|
// ... check status, label, class
|
||||||
casper.waitForSelector('.js-publish-splitbutton', function onSuccess() {
|
casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() {
|
||||||
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
|
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
|
||||||
test.assertSelectorHasText('.js-publish-button', 'Update Page', '.js-publish-button says Update Page');
|
test.assertSelectorHasText('.js-publish-button', 'Update Page', '.js-publish-button says Update Page');
|
||||||
}, function onTimeout() {
|
}, function onTimeout() {
|
||||||
@ -399,7 +399,7 @@ CasperTest.begin('Publish menu - existing post', 23, function suite(test) {
|
|||||||
|
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open', function onSuccess() {
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu', function onSuccess() {
|
||||||
test.assert(true, 'delete post button should be visible for saved drafts');
|
test.assert(true, 'delete post button should be visible for saved drafts');
|
||||||
test.assertVisible(
|
test.assertVisible(
|
||||||
'.js-publish-splitbutton .delete', 'delete post button should be visible on saved drafts'
|
'.js-publish-splitbutton .delete', 'delete post button should be visible on saved drafts'
|
||||||
@ -412,7 +412,7 @@ CasperTest.begin('Publish menu - existing post', 23, function suite(test) {
|
|||||||
// Open the publish options menu;
|
// Open the publish options menu;
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
|
|
||||||
// Select the publish post button
|
// Select the publish post button
|
||||||
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
||||||
@ -445,7 +445,7 @@ CasperTest.begin('Publish menu - existing post', 23, function suite(test) {
|
|||||||
// Open the publish options menu;
|
// Open the publish options menu;
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
|
|
||||||
// Select the publish post button
|
// Select the publish post button
|
||||||
casper.thenClick('.js-publish-splitbutton li:nth-child(2) a');
|
casper.thenClick('.js-publish-splitbutton li:nth-child(2) a');
|
||||||
@ -488,7 +488,7 @@ CasperTest.begin('Publish menu - delete post', 6, function testDeleteModal(test)
|
|||||||
|
|
||||||
// Open post settings menu
|
// Open post settings menu
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
casper.thenClick('.js-publish-splitbutton li:nth-child(4) a');
|
casper.thenClick('.js-publish-splitbutton li:nth-child(4) a');
|
||||||
|
|
||||||
casper.waitUntilVisible('.modal-container', function onSuccess() {
|
casper.waitUntilVisible('.modal-container', function onSuccess() {
|
||||||
@ -506,7 +506,7 @@ CasperTest.begin('Publish menu - delete post', 6, function testDeleteModal(test)
|
|||||||
|
|
||||||
// Test delete
|
// Test delete
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
casper.thenClick('.js-publish-splitbutton li:nth-child(4) a');
|
casper.thenClick('.js-publish-splitbutton li:nth-child(4) a');
|
||||||
|
|
||||||
casper.waitForSelector('.modal-container .modal-content', function onSuccess() {
|
casper.waitForSelector('.modal-container .modal-content', function onSuccess() {
|
||||||
@ -536,7 +536,7 @@ CasperTest.begin('Publish menu - new post status is correct after failed save',
|
|||||||
// Open the publish options menu;
|
// Open the publish options menu;
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
|
|
||||||
// Select the publish post button
|
// Select the publish post button
|
||||||
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
||||||
@ -581,7 +581,7 @@ CasperTest.begin('Publish menu - existing post status is correct after failed sa
|
|||||||
// Open the publish options menu;
|
// Open the publish options menu;
|
||||||
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
|
||||||
|
|
||||||
casper.waitForOpaque('.js-publish-splitbutton .open');
|
casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu');
|
||||||
|
|
||||||
// Select the publish post button
|
// Select the publish post button
|
||||||
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
casper.thenClick('.js-publish-splitbutton li:first-child a');
|
||||||
|
Loading…
Reference in New Issue
Block a user