mirror of
https://github.com/TryGhost/Ghost-Admin.git
synced 2023-12-14 02:33:04 +01:00
parent
5388686217
commit
be1bf27285
|
@ -1,7 +1,6 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import {parseDateString} from 'ghost/utils/date-formatting';
|
import {parseDateString} from 'ghost/utils/date-formatting';
|
||||||
import SettingsMenuMixin from 'ghost/mixins/settings-menu-controller';
|
import SettingsMenuMixin from 'ghost/mixins/settings-menu-controller';
|
||||||
import SlugGenerator from 'ghost/models/slug-generator';
|
|
||||||
import boundOneWay from 'ghost/utils/bound-one-way';
|
import boundOneWay from 'ghost/utils/bound-one-way';
|
||||||
import isNumber from 'ghost/utils/isNumber';
|
import isNumber from 'ghost/utils/isNumber';
|
||||||
|
|
||||||
|
@ -18,6 +17,7 @@ export default Controller.extend(SettingsMenuMixin, {
|
||||||
ghostPaths: inject.service('ghost-paths'),
|
ghostPaths: inject.service('ghost-paths'),
|
||||||
notifications: inject.service(),
|
notifications: inject.service(),
|
||||||
session: inject.service(),
|
session: inject.service(),
|
||||||
|
slugGenerator: inject.service('slug-generator'),
|
||||||
|
|
||||||
initializeSelectedAuthor: observer('model', function () {
|
initializeSelectedAuthor: observer('model', function () {
|
||||||
return this.get('model.author').then((author) => {
|
return this.get('model.author').then((author) => {
|
||||||
|
@ -45,14 +45,6 @@ export default Controller.extend(SettingsMenuMixin, {
|
||||||
|
|
||||||
slugValue: boundOneWay('model.slug'),
|
slugValue: boundOneWay('model.slug'),
|
||||||
|
|
||||||
// Lazy load the slug generator
|
|
||||||
slugGenerator: computed(function () {
|
|
||||||
return SlugGenerator.create({
|
|
||||||
ghostPaths: this.get('ghostPaths'),
|
|
||||||
slugType: 'post'
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
|
|
||||||
// Requests slug from title
|
// Requests slug from title
|
||||||
generateAndSetSlug(destination) {
|
generateAndSetSlug(destination) {
|
||||||
let title = this.get('model.titleScratch');
|
let title = this.get('model.titleScratch');
|
||||||
|
@ -65,7 +57,7 @@ export default Controller.extend(SettingsMenuMixin, {
|
||||||
}
|
}
|
||||||
|
|
||||||
promise = RSVP.resolve(afterSave).then(() => {
|
promise = RSVP.resolve(afterSave).then(() => {
|
||||||
return this.get('slugGenerator').generateSlug(title).then((slug) => {
|
return this.get('slugGenerator').generateSlug('post', title).then((slug) => {
|
||||||
if (!isBlank(slug)) {
|
if (!isBlank(slug)) {
|
||||||
this.set(destination, slug);
|
this.set(destination, slug);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +224,7 @@ export default Controller.extend(SettingsMenuMixin, {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.get('slugGenerator').generateSlug(newSlug).then((serverSlug) => {
|
this.get('slugGenerator').generateSlug('post', newSlug).then((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
|
||||||
if (serverSlug === slug) {
|
if (serverSlug === slug) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import {request as ajax} from 'ic-ajax';
|
import {request as ajax} from 'ic-ajax';
|
||||||
import SlugGenerator from 'ghost/models/slug-generator';
|
|
||||||
import isNumber from 'ghost/utils/isNumber';
|
import isNumber from 'ghost/utils/isNumber';
|
||||||
import boundOneWay from 'ghost/utils/bound-one-way';
|
import boundOneWay from 'ghost/utils/bound-one-way';
|
||||||
import ValidationEngine from 'ghost/mixins/validation-engine';
|
import ValidationEngine from 'ghost/mixins/validation-engine';
|
||||||
|
@ -22,6 +21,7 @@ export default Controller.extend(ValidationEngine, {
|
||||||
ghostPaths: inject.service('ghost-paths'),
|
ghostPaths: inject.service('ghost-paths'),
|
||||||
notifications: inject.service(),
|
notifications: inject.service(),
|
||||||
session: inject.service(),
|
session: inject.service(),
|
||||||
|
slugGenerator: inject.service('slug-generator'),
|
||||||
|
|
||||||
user: alias('model'),
|
user: alias('model'),
|
||||||
currentUser: alias('session.user'),
|
currentUser: alias('session.user'),
|
||||||
|
@ -74,14 +74,6 @@ export default Controller.extend(ValidationEngine, {
|
||||||
return `${this.get('user.name')}'s Cover Image`;
|
return `${this.get('user.name')}'s Cover Image`;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Lazy load the slug generator for slugPlaceholder
|
|
||||||
slugGenerator: computed(function () {
|
|
||||||
return SlugGenerator.create({
|
|
||||||
ghostPaths: this.get('ghostPaths'),
|
|
||||||
slugType: 'user'
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
|
|
||||||
roles: computed(function () {
|
roles: computed(function () {
|
||||||
return this.store.query('role', {permissions: 'assign'});
|
return this.store.query('role', {permissions: 'assign'});
|
||||||
}),
|
}),
|
||||||
|
@ -210,7 +202,7 @@ export default Controller.extend(ValidationEngine, {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.get('slugGenerator').generateSlug(newSlug).then((serverSlug) => {
|
return this.get('slugGenerator').generateSlug('user', newSlug).then((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
|
||||||
if (serverSlug === slug) {
|
if (serverSlug === slug) {
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import Ember from 'ember';
|
|
||||||
import {request as ajax} from 'ic-ajax';
|
|
||||||
|
|
||||||
const {RSVP, inject} = Ember;
|
|
||||||
|
|
||||||
export default Ember.Object.extend({
|
|
||||||
slugType: null,
|
|
||||||
value: null,
|
|
||||||
|
|
||||||
ghostPaths: inject.service('ghost-paths'),
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return this.get('value');
|
|
||||||
},
|
|
||||||
|
|
||||||
generateSlug(textToSlugify) {
|
|
||||||
let url;
|
|
||||||
|
|
||||||
if (!textToSlugify) {
|
|
||||||
return RSVP.resolve('');
|
|
||||||
}
|
|
||||||
|
|
||||||
url = this.get('ghostPaths.url').api('slugs', this.get('slugType'), encodeURIComponent(textToSlugify));
|
|
||||||
|
|
||||||
return ajax(url, {
|
|
||||||
type: 'GET'
|
|
||||||
}).then((response) => {
|
|
||||||
let [firstSlug] = response.slugs;
|
|
||||||
let {slug} = firstSlug;
|
|
||||||
|
|
||||||
this.set('value', slug);
|
|
||||||
|
|
||||||
return slug;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
25
app/services/slug-generator.js
Normal file
25
app/services/slug-generator.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
import {request as ajax} from 'ic-ajax';
|
||||||
|
|
||||||
|
const {RSVP, inject, Service} = Ember;
|
||||||
|
|
||||||
|
export default Service.extend({
|
||||||
|
ghostPaths: inject.service('ghost-paths'),
|
||||||
|
|
||||||
|
generateSlug(slugType, textToSlugify) {
|
||||||
|
let url;
|
||||||
|
|
||||||
|
if (!textToSlugify) {
|
||||||
|
return RSVP.resolve('');
|
||||||
|
}
|
||||||
|
|
||||||
|
url = this.get('ghostPaths.url').api('slugs', slugType, encodeURIComponent(textToSlugify));
|
||||||
|
|
||||||
|
return ajax(url).then((response) => {
|
||||||
|
let [firstSlug] = response.slugs;
|
||||||
|
let {slug} = firstSlug;
|
||||||
|
|
||||||
|
return slug;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
62
tests/integration/services/slug-generator-test.js
Normal file
62
tests/integration/services/slug-generator-test.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import {
|
||||||
|
describeModule,
|
||||||
|
it
|
||||||
|
} from 'ember-mocha';
|
||||||
|
import Pretender from 'pretender';
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
const {dasherize} = Ember.String;
|
||||||
|
|
||||||
|
function stubSlugEndpoint(server, type, slug) {
|
||||||
|
server.get('/ghost/api/v0.1/slugs/:type/:slug/', function (request) {
|
||||||
|
expect(request.params.type).to.equal(type);
|
||||||
|
expect(request.params.slug).to.equal(slug);
|
||||||
|
|
||||||
|
return [
|
||||||
|
200,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
JSON.stringify({slugs: [{slug: dasherize(slug)}]})
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describeModule(
|
||||||
|
'service:slug-generator',
|
||||||
|
'Integration: Service: slug-generator',
|
||||||
|
{
|
||||||
|
integration: true
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
let server;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
server = new Pretender();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
server.shutdown();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty if no slug is provided', function (done) {
|
||||||
|
let service = this.subject();
|
||||||
|
|
||||||
|
service.generateSlug('post', '').then(function (slug) {
|
||||||
|
expect(slug).to.equal('');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls correct endpoint and returns correct data', function (done) {
|
||||||
|
let rawSlug = 'a test post';
|
||||||
|
stubSlugEndpoint(server, 'post', rawSlug);
|
||||||
|
|
||||||
|
let service = this.subject();
|
||||||
|
|
||||||
|
service.generateSlug('post', rawSlug).then(function (slug) {
|
||||||
|
expect(slug).to.equal(dasherize(rawSlug));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
|
@ -15,7 +15,7 @@ describeModule(
|
||||||
'controller:post-settings-menu',
|
'controller:post-settings-menu',
|
||||||
'Unit: Controller: post-settings-menu',
|
'Unit: Controller: post-settings-menu',
|
||||||
{
|
{
|
||||||
needs: ['controller:application', 'service:notifications']
|
needs: ['controller:application', 'service:notifications', 'service:slug-generator']
|
||||||
},
|
},
|
||||||
|
|
||||||
function () {
|
function () {
|
||||||
|
@ -389,7 +389,7 @@ describeModule(
|
||||||
it('should generate a slug and set it on the destination', function (done) {
|
it('should generate a slug and set it on the destination', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
return Ember.RSVP.resolve(`${str}-slug`);
|
return Ember.RSVP.resolve(`${str}-slug`);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -413,7 +413,7 @@ describeModule(
|
||||||
it('should not set the destination if the title is "(Untitled)" and the post already has a slug', function (done) {
|
it('should not set the destination if the title is "(Untitled)" and the post already has a slug', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
return Ember.RSVP.resolve(`${str}-slug`);
|
return Ember.RSVP.resolve(`${str}-slug`);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -567,7 +567,7 @@ describeModule(
|
||||||
it('should not set a new slug if the server-generated slug matches existing slug', function (done) {
|
it('should not set a new slug if the server-generated slug matches existing slug', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
let promise = Ember.RSVP.resolve(str.split('#')[0]);
|
let promise = Ember.RSVP.resolve(str.split('#')[0]);
|
||||||
this.set('lastPromise', promise);
|
this.set('lastPromise', promise);
|
||||||
return promise;
|
return promise;
|
||||||
|
@ -593,7 +593,7 @@ describeModule(
|
||||||
it('should not set a new slug if the only change is to the appended increment value', function (done) {
|
it('should not set a new slug if the only change is to the appended increment value', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
let sanitizedStr = str.replace(/[^a-zA-Z]/g, '');
|
let sanitizedStr = str.replace(/[^a-zA-Z]/g, '');
|
||||||
let promise = Ember.RSVP.resolve(`${sanitizedStr}-2`);
|
let promise = Ember.RSVP.resolve(`${sanitizedStr}-2`);
|
||||||
this.set('lastPromise', promise);
|
this.set('lastPromise', promise);
|
||||||
|
@ -620,7 +620,7 @@ describeModule(
|
||||||
it('should set the slug if the new slug is different', function (done) {
|
it('should set the slug if the new slug is different', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
let promise = Ember.RSVP.resolve(str);
|
let promise = Ember.RSVP.resolve(str);
|
||||||
this.set('lastPromise', promise);
|
this.set('lastPromise', promise);
|
||||||
return promise;
|
return promise;
|
||||||
|
@ -647,7 +647,7 @@ describeModule(
|
||||||
it('should save the post when the slug changes and the post is not new', function (done) {
|
it('should save the post when the slug changes and the post is not new', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
let promise = Ember.RSVP.resolve(str);
|
let promise = Ember.RSVP.resolve(str);
|
||||||
this.set('lastPromise', promise);
|
this.set('lastPromise', promise);
|
||||||
return promise;
|
return promise;
|
||||||
|
@ -679,7 +679,7 @@ describeModule(
|
||||||
it('should not save the post when the slug changes and the post is new', function (done) {
|
it('should not save the post when the slug changes and the post is new', function (done) {
|
||||||
let controller = this.subject({
|
let controller = this.subject({
|
||||||
slugGenerator: Ember.Object.create({
|
slugGenerator: Ember.Object.create({
|
||||||
generateSlug(str) {
|
generateSlug(slugType, str) {
|
||||||
let promise = Ember.RSVP.resolve(str);
|
let promise = Ember.RSVP.resolve(str);
|
||||||
this.set('lastPromise', promise);
|
this.set('lastPromise', promise);
|
||||||
return promise;
|
return promise;
|
||||||
|
|
Loading…
Reference in a new issue