0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00

Merge pull request #3766 from jaswilli/user-slug

Correct behavior on updating user slug.
This commit is contained in:
Hannah Wolfe 2014-08-18 20:55:54 +01:00
commit 02ca955a00
3 changed files with 124 additions and 37 deletions

View file

@ -2,16 +2,14 @@ import SlugGenerator from 'ghost/models/slug-generator';
var SettingsUserController = Ember.ObjectController.extend({ var SettingsUserController = Ember.ObjectController.extend({
_lastSlug: null,
updateLastSlug: Ember.observer(function () {
this.set('_lastSlug', this.get('user.slug'));
}),
user: Ember.computed.alias('model'), user: Ember.computed.alias('model'),
email: Ember.computed.readOnly('user.email'), email: Ember.computed.readOnly('user.email'),
slugValue: Ember.computed.oneWay('user.slug'),
lastPromise: null,
coverDefault: function () { coverDefault: function () {
return this.get('ghostPaths.url').asset('/shared/img/user-cover.png'); return this.get('ghostPaths.url').asset('/shared/img/user-cover.png');
}.property('ghostPaths'), }.property('ghostPaths'),
@ -106,15 +104,43 @@ var SettingsUserController = Ember.ObjectController.extend({
save: function () { save: function () {
var user = this.get('user'), var user = this.get('user'),
slugValue = this.get('slugValue'),
afterUpdateSlug = this.get('lastPromise'),
promise,
slugChanged,
self = this; self = this;
user.save({ format: false }).then(function (model) { if (user.get('slug') !== slugValue) {
slugChanged = true;
user.set('slug', slugValue);
}
promise = Ember.RSVP.resolve(afterUpdateSlug).then(function () {
return user.save({ format: false });
}).then(function (model) {
var currentPath,
newPath;
self.notifications.showSuccess('Settings successfully saved.'); self.notifications.showSuccess('Settings successfully saved.');
// 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.history.state.path;
newPath = currentPath.split('/');
newPath[newPath.length - 2] = model.get('slug');
newPath = newPath.join('/');
window.history.replaceState({ path: newPath }, '', newPath);
}
return model; return model;
}).catch(function (errors) { }).catch(function (errors) {
self.notifications.showErrors(errors); self.notifications.showErrors(errors);
}); });
this.set('lastPromise', promise);
}, },
password: function () { password: function () {
@ -143,8 +169,12 @@ var SettingsUserController = Ember.ObjectController.extend({
}, },
updateSlug: function (newSlug) { updateSlug: function (newSlug) {
var slug = this.get('_lastSlug'), var self = this,
self = this; afterSave = this.get('lastPromise'),
promise;
promise = Ember.RSVP.resolve(afterSave).then(function () {
var slug = self.get('slug');
newSlug = newSlug || slug; newSlug = newSlug || slug;
@ -152,10 +182,12 @@ var SettingsUserController = Ember.ObjectController.extend({
// Ignore unchanged slugs or candidate slugs that are empty // Ignore unchanged slugs or candidate slugs that are empty
if (!newSlug || slug === newSlug) { if (!newSlug || slug === newSlug) {
self.set('slugValue', slug);
return; return;
} }
this.get('slugGenerator').generateSlug(newSlug).then(function (serverSlug) { return self.get('slugGenerator').generateSlug(newSlug).then(function (serverSlug) {
// If after getting the sanitized and unique slug back from the API // If after getting the sanitized and unique slug back from the API
// we end up with a slug that matches the existing slug, abort the change // we end up with a slug that matches the existing slug, abort the change
@ -177,12 +209,17 @@ var SettingsUserController = Ember.ObjectController.extend({
// for the incrementor then the existing slug should be used // for the incrementor then the existing slug should be used
if (_.isNumber(check) && check > 0) { if (_.isNumber(check) && check > 0) {
if (slug === slugTokens.join('-') && serverSlug !== newSlug) { if (slug === slugTokens.join('-') && serverSlug !== newSlug) {
self.set('slugValue', slug);
return; return;
} }
} }
self.set('_lastSlug', serverSlug); self.set('slugValue', serverSlug);
}); });
});
this.set('lastPromise', promise);
} }
} }
}); });

View file

@ -52,9 +52,8 @@
<div class="form-group"> <div class="form-group">
<label for="user-slug">Slug</label> <label for="user-slug">Slug</label>
{{!-- {{input value=user.slug id="user-slug" placeholder="Slug" autocorrect="off"}} --}} {{gh-blur-input class="user-name" id="user-slug" value=slugValue name="user" action="updateSlug" placeholder="Slug" selectOnClick="true" autocorrect="off"}}
{{gh-blur-input class="user-name" id="user-slug" value=user.slug name="user" action="updateSlug" placeholder="Slug" selectOnClick="true" autocorrect="off"}} <p>{{gh-blog-url}}/author/{{slugValue}}</p>
<p>{{gh-blog-url}}/author/{{user.slug}}</p>
</div> </div>
<div class="form-group"> <div class="form-group">

View file

@ -283,6 +283,57 @@ CasperTest.begin('Can save settings', 7, function suite(test) {
}); });
}); });
CasperTest.begin('User settings screen resets all whitespace slug to original value', 3, function suite(test) {
var slug;
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.then(function setSlugToAllWhitespace() {
slug = casper.getElementInfo('#user-slug').attributes.value;
casper.fillSelectors('.user-profile', {
'#user-slug': ' '
}, false);
});
casper.thenClick('.content.settings-user');
casper.then(function checkSlugInputValue() {
casper.wait(250);
test.assertField('user', slug);
});
});
CasperTest.begin('User settings screen change slug handles duplicate slug', 4, function suite(test) {
var slug;
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.then(function changeSlug() {
slug = casper.getElementInfo('#user-slug').attributes.value;
casper.fillSelectors('.user-profile', {
'#user-slug': slug + '!'
}, false);
});
casper.thenClick('.content.settings-user');
casper.waitForResource(/\/slugs\/user\//, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
casper.then(function checkSlugInputValue() {
test.assertField('user', slug);
});
});
CasperTest.begin('User settings screen validates email', 6, function suite(test) { CasperTest.begin('User settings screen validates email', 6, function suite(test) {
var email, brokenEmail; var email, brokenEmail;