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

custom slugging capabilities for individual user pages

closes #3401
- modifying slug-generator to be more generic
- adding slugging capabilities for /settings/users/:slug
- modified posts to use the updated slug-generator
This commit is contained in:
Maurice Williams 2014-07-31 00:25:42 -04:00
parent a6c205ac53
commit 489cd08d97
5 changed files with 70 additions and 7 deletions

View file

@ -59,7 +59,8 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
//Lazy load the slug generator for slugPlaceholder //Lazy load the slug generator for slugPlaceholder
slugGenerator: Ember.computed(function () { slugGenerator: Ember.computed(function () {
return SlugGenerator.create({ return SlugGenerator.create({
ghostPaths: this.get('ghostPaths') ghostPaths: this.get('ghostPaths'),
slugType: 'post'
}); });
}), }),
//Requests slug from title //Requests slug from title

View file

@ -1,3 +1,6 @@
import SlugGenerator from 'ghost/models/slug-generator';
import boundOneWay from 'ghost/utils/bound-one-way';
var SettingsUserController = Ember.ObjectController.extend({ var SettingsUserController = Ember.ObjectController.extend({
user: Ember.computed.alias('model'), user: Ember.computed.alias('model'),
@ -43,7 +46,17 @@ var SettingsUserController = Ember.ObjectController.extend({
return createdAt ? createdAt.fromNow() : ''; return createdAt ? createdAt.fromNow() : '';
}.property('user.created_at'), }.property('user.created_at'),
//Lazy load the slug generator for slugPlaceholder
slugGenerator: Ember.computed(function () {
return SlugGenerator.create({
ghostPaths: this.get('ghostPaths'),
slugType: 'user'
});
}),
slugValue: boundOneWay('user.slug'),
actions: { actions: {
changeRole: function (newRole) { changeRole: function (newRole) {
this.set('model.role', newRole); this.set('model.role', newRole);
@ -120,6 +133,49 @@ var SettingsUserController = Ember.ObjectController.extend({
} else { } else {
self.notifications.showErrors(user.get('passwordValidationErrors')); self.notifications.showErrors(user.get('passwordValidationErrors'));
} }
},
updateSlug: function (newSlug) {
var slug = this.get('user.slug'),
self = this;
newSlug = newSlug || slug;
newSlug = newSlug.trim();
// Ignore unchanged slugs or candidate slugs that are empty
if (!newSlug || slug === newSlug) {
return;
}
this.get('slugGenerator').generateSlug(newSlug).then(function (serverSlug) {
// 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
if (serverSlug === slug) {
return;
}
// Because the server transforms the candidate slug by stripping
// certain characters and appending a number onto the end of slugs
// to enforce uniqueness, there are cases where we can get back a
// candidate slug that is a duplicate of the original except for
// the trailing incrementor (e.g., this-is-a-slug and this-is-a-slug-2)
// get the last token out of the slug candidate and see if it's a number
var slugTokens = serverSlug.split('-'),
check = Number(slugTokens.pop());
// if the candidate slug is the same as the existing slug except
// for the incrementor then the existing slug should be used
if (_.isNumber(check) && check > 0) {
if (slug === slugTokens.join('-') && serverSlug !== newSlug) {
return;
}
}
self.set('user.slug', serverSlug);
});
} }
} }
}); });

View file

@ -1,5 +1,6 @@
var SlugGenerator = Ember.Object.extend({ var SlugGenerator = Ember.Object.extend({
ghostPaths: null, ghostPaths: null,
slugType: null,
value: null, value: null,
toString: function () { toString: function () {
return this.get('value'); return this.get('value');
@ -12,7 +13,7 @@ var SlugGenerator = Ember.Object.extend({
return Ember.RSVP.resolve(''); return Ember.RSVP.resolve('');
} }
url = this.get('ghostPaths.url').api('slugs', 'post', encodeURIComponent(textToSlugify)); url = this.get('ghostPaths.url').api('slugs', this.get('slugType'), encodeURIComponent(textToSlugify));
return ic.ajax.request(url, { return ic.ajax.request(url, {
type: 'GET' type: 'GET'

View file

@ -58,11 +58,12 @@
<fieldset class="user-details-bottom"> <fieldset class="user-details-bottom">
{{!-- <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"}} {{!-- {{input value=user.slug id="user-slug" placeholder="Slug" autocorrect="off"}} --}}
<p>http://blog-url.com/user/{{user.slug}}</p> {{gh-blur-input class="user-name" id="user-slug" value=slugValue name="user" action="updateSlug" placeholder="Slug" selectOnClick="true" autocorrect="off"}}
</div> --}} <p>http://blog-url.com/user/{{slugValue}}</p>
</div>
<div class="form-group"> <div class="form-group">
<label for="user-email">Email</label> <label for="user-email">Email</label>

View file

@ -329,6 +329,10 @@ User = ghostBookshelf.Model.extend({
delete data.role; delete data.role;
} }
if (data.status === 'all') {
delete data.status;
}
return ghostBookshelf.Model.findOne.call(this, data, options); return ghostBookshelf.Model.findOne.call(this, data, options);
}, },