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:
parent
a6c205ac53
commit
489cd08d97
5 changed files with 70 additions and 7 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue