mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-30 11:54:33 +03:00
5c0cfca479
no issue - removed unused `<GhTagsManagementContainer>` component and related `isMobile` CPs - un-nested `tag` and `tag.new` routes - nested routes in Ember are used for nested UI but these are both separate screens - removes usage of `selectedTag` property in favour of using Ember's built-in model handling - removed unnecessary `tags/new` controller - sets up `tag.new` route which extends the `tag` route to avoid duplicate code
229 lines
6.9 KiB
JavaScript
229 lines
6.9 KiB
JavaScript
/* eslint-disable camelcase */
|
|
import Component from '@ember/component';
|
|
import RSVP from 'rsvp';
|
|
import {computed} from '@ember/object';
|
|
import {isBlank, isEmpty} from '@ember/utils';
|
|
import {inject as service} from '@ember/service';
|
|
import {task, timeout, waitForProperty} from 'ember-concurrency';
|
|
|
|
export function computedGroup(category) {
|
|
return computed('content', 'currentSearch', function () {
|
|
if (!this.currentSearch || !this.content) {
|
|
return [];
|
|
}
|
|
|
|
return this.content.filter((item) => {
|
|
let search = this.currentSearch.toString().toLowerCase();
|
|
|
|
return (item.category === category) && (item.title.toString().toLowerCase().indexOf(search) >= 0);
|
|
});
|
|
});
|
|
}
|
|
|
|
export default Component.extend({
|
|
ajax: service(),
|
|
notifications: service(),
|
|
router: service(),
|
|
store: service(),
|
|
|
|
content: null,
|
|
contentExpiresAt: false,
|
|
contentExpiry: 30000,
|
|
currentSearch: '',
|
|
selection: null,
|
|
|
|
onSelected() {},
|
|
|
|
posts: computedGroup('Posts'),
|
|
pages: computedGroup('Pages'),
|
|
users: computedGroup('Users'),
|
|
tags: computedGroup('Tags'),
|
|
|
|
groupedContent: computed('posts', 'pages', 'users', 'tags', function () {
|
|
let groups = [];
|
|
|
|
if (!isEmpty(this.posts)) {
|
|
groups.pushObject({groupName: 'Posts', options: this.posts});
|
|
}
|
|
|
|
if (!isEmpty(this.pages)) {
|
|
groups.pushObject({groupName: 'Pages', options: this.pages});
|
|
}
|
|
|
|
if (!isEmpty(this.users)) {
|
|
groups.pushObject({groupName: 'Users', options: this.users});
|
|
}
|
|
|
|
if (!isEmpty(this.tags)) {
|
|
groups.pushObject({groupName: 'Tags', options: this.tags});
|
|
}
|
|
|
|
return groups;
|
|
}),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
this.content = [];
|
|
},
|
|
|
|
didRender() {
|
|
this._super(...arguments);
|
|
|
|
// force the search box to be focused at all times. Fixes disappearing
|
|
// caret when pressing Escape
|
|
let input = this.element.querySelector('input');
|
|
if (input) {
|
|
input.focus();
|
|
}
|
|
},
|
|
|
|
actions: {
|
|
openSelected(selected) {
|
|
if (!selected) {
|
|
return;
|
|
}
|
|
|
|
this.onSelected(selected);
|
|
|
|
if (selected.category === 'Posts') {
|
|
let id = selected.id.replace('post.', '');
|
|
this.router.transitionTo('editor.edit', 'post', id);
|
|
}
|
|
|
|
if (selected.category === 'Pages') {
|
|
let id = selected.id.replace('page.', '');
|
|
this.router.transitionTo('editor.edit', 'page', id);
|
|
}
|
|
|
|
if (selected.category === 'Users') {
|
|
let id = selected.id.replace('user.', '');
|
|
this.router.transitionTo('staff.user', id);
|
|
}
|
|
|
|
if (selected.category === 'Tags') {
|
|
let id = selected.id.replace('tag.', '');
|
|
this.router.transitionTo('tag', id);
|
|
}
|
|
},
|
|
|
|
search(term) {
|
|
return this.performSearch.perform(term);
|
|
}
|
|
},
|
|
|
|
performSearch: task(function* (term) {
|
|
if (isBlank(term)) {
|
|
return [];
|
|
}
|
|
|
|
// start loading immediately in the background
|
|
this.refreshContent.perform();
|
|
|
|
// debounce searches to 200ms to avoid thrashing CPU
|
|
yield timeout(200);
|
|
|
|
// wait for any on-going refresh to finish
|
|
if (this.refreshContent.isRunning) {
|
|
yield waitForProperty(this, 'refreshContent.isIdle');
|
|
}
|
|
|
|
// set dependent CP term and re-calculate CP
|
|
this.set('currentSearch', term);
|
|
return this.groupedContent;
|
|
}).restartable(),
|
|
|
|
refreshContent: task(function* () {
|
|
let promises = [];
|
|
let now = new Date();
|
|
let contentExpiresAt = this.contentExpiresAt;
|
|
|
|
if (contentExpiresAt > now) {
|
|
return true;
|
|
}
|
|
|
|
this.set('content', []);
|
|
promises.pushObject(this._loadPosts());
|
|
promises.pushObject(this._loadPages());
|
|
promises.pushObject(this._loadUsers());
|
|
promises.pushObject(this._loadTags());
|
|
|
|
try {
|
|
yield RSVP.all(promises);
|
|
} catch (error) {
|
|
// eslint-disable-next-line
|
|
console.error(error);
|
|
}
|
|
|
|
let contentExpiry = this.contentExpiry;
|
|
this.set('contentExpiresAt', new Date(now.getTime() + contentExpiry));
|
|
}).drop(),
|
|
|
|
_loadPosts() {
|
|
let store = this.store;
|
|
let postsUrl = `${store.adapterFor('post').urlForQuery({}, 'post')}/`;
|
|
let postsQuery = {fields: 'id,title,page', limit: 'all'};
|
|
let content = this.content;
|
|
|
|
return this.ajax.request(postsUrl, {data: postsQuery}).then((posts) => {
|
|
content.pushObjects(posts.posts.map(post => ({
|
|
id: `post.${post.id}`,
|
|
title: post.title,
|
|
category: 'Posts'
|
|
})));
|
|
}).catch((error) => {
|
|
this.notifications.showAPIError(error, {key: 'search.loadPosts.error'});
|
|
});
|
|
},
|
|
|
|
_loadPages() {
|
|
let store = this.store;
|
|
let pagesUrl = `${store.adapterFor('page').urlForQuery({}, 'page')}/`;
|
|
let pagesQuery = {fields: 'id,title,page', limit: 'all'};
|
|
let content = this.content;
|
|
|
|
return this.ajax.request(pagesUrl, {data: pagesQuery}).then((pages) => {
|
|
content.pushObjects(pages.pages.map(page => ({
|
|
id: `page.${page.id}`,
|
|
title: page.title,
|
|
category: 'Pages'
|
|
})));
|
|
}).catch((error) => {
|
|
this.notifications.showAPIError(error, {key: 'search.loadPosts.error'});
|
|
});
|
|
},
|
|
|
|
_loadUsers() {
|
|
let store = this.store;
|
|
let usersUrl = `${store.adapterFor('user').urlForQuery({}, 'user')}/`;
|
|
let usersQuery = {fields: 'name,slug', limit: 'all'};
|
|
let content = this.content;
|
|
|
|
return this.ajax.request(usersUrl, {data: usersQuery}).then((users) => {
|
|
content.pushObjects(users.users.map(user => ({
|
|
id: `user.${user.slug}`,
|
|
title: user.name,
|
|
category: 'Users'
|
|
})));
|
|
}).catch((error) => {
|
|
this.notifications.showAPIError(error, {key: 'search.loadUsers.error'});
|
|
});
|
|
},
|
|
|
|
_loadTags() {
|
|
let store = this.store;
|
|
let tagsUrl = `${store.adapterFor('tag').urlForQuery({}, 'tag')}/`;
|
|
let tagsQuery = {fields: 'name,slug', limit: 'all'};
|
|
let content = this.content;
|
|
|
|
return this.ajax.request(tagsUrl, {data: tagsQuery}).then((tags) => {
|
|
content.pushObjects(tags.tags.map(tag => ({
|
|
id: `tag.${tag.slug}`,
|
|
title: tag.name,
|
|
category: 'Tags'
|
|
})));
|
|
}).catch((error) => {
|
|
this.notifications.showAPIError(error, {key: 'search.loadTags.error'});
|
|
});
|
|
}
|
|
});
|