mirror of
https://github.com/TryGhost/Ghost-Admin.git
synced 2023-12-14 02:33:04 +01:00
remove unnecessary posts/index route (#545)
no issue - the index route/controller/template was initially used for a separate loading state within the posts screen layout, this isn't necessary however as the same effect can be achieved with the `posts-loading.hbs` template - this change also lays the groundwork for more complex dropdown-based filters as it enables the filters and query params to live in the same controller+template
This commit is contained in:
parent
f4b7b6d375
commit
bd45481027
9 changed files with 257 additions and 247 deletions
|
@ -1,5 +1,23 @@
|
|||
import Controller from 'ember-controller';
|
||||
import computed from 'ember-computed';
|
||||
import injectService from 'ember-service/inject';
|
||||
|
||||
export default Controller.extend({
|
||||
|
||||
queryParams: ['type'],
|
||||
type: null,
|
||||
|
||||
session: injectService(),
|
||||
|
||||
showDeletePostModal: false,
|
||||
|
||||
showingAll: computed('type', function () {
|
||||
return this.get('type') === null;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
toggleDeletePostModal() {
|
||||
this.toggleProperty('showDeletePostModal');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import Controller from 'ember-controller';
|
||||
import computed from 'ember-computed';
|
||||
import injectService from 'ember-service/inject';
|
||||
|
||||
export default Controller.extend({
|
||||
|
||||
queryParams: ['type'],
|
||||
type: null,
|
||||
|
||||
session: injectService(),
|
||||
|
||||
showDeletePostModal: false,
|
||||
|
||||
showingAll: computed('type', function () {
|
||||
return this.get('type') === null;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
toggleDeletePostModal() {
|
||||
this.toggleProperty('showDeletePostModal');
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,5 +1,153 @@
|
|||
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
|
||||
import ShortcutsRoute from 'ghost-admin/mixins/shortcuts-route';
|
||||
import InfinityRoute from 'ember-infinity/mixins/route';
|
||||
import computed from 'ember-computed';
|
||||
import {assign} from 'ember-platform';
|
||||
import $ from 'jquery';
|
||||
|
||||
export default AuthenticatedRoute.extend({
|
||||
titleToken: 'Content'
|
||||
export default AuthenticatedRoute.extend(InfinityRoute, ShortcutsRoute, {
|
||||
titleToken: 'Content',
|
||||
|
||||
perPage: 30,
|
||||
perPageParam: 'limit',
|
||||
totalPagesParam: 'meta.pagination.pages',
|
||||
|
||||
_type: null,
|
||||
_selectedPostIndex: null,
|
||||
|
||||
model(params) {
|
||||
this.set('_type', params.type);
|
||||
let filterSettings = this.get('filterSettings');
|
||||
|
||||
return this.get('session.user').then((user) => {
|
||||
if (user.get('isAuthor')) {
|
||||
filterSettings.filter = filterSettings.filter
|
||||
? `${filterSettings.filter}+author:${user.get('slug')}` : `author:${user.get('slug')}`;
|
||||
}
|
||||
|
||||
let perPage = this.get('perPage');
|
||||
let paginationSettings = assign({perPage, startingPage: 1}, filterSettings);
|
||||
|
||||
return this.infinityModel('post', paginationSettings);
|
||||
});
|
||||
},
|
||||
|
||||
filterSettings: computed('_type', function () {
|
||||
let type = this.get('_type');
|
||||
let status = 'all';
|
||||
let staticPages = 'all';
|
||||
|
||||
switch (type) {
|
||||
case 'draft':
|
||||
status = 'draft';
|
||||
staticPages = false;
|
||||
break;
|
||||
case 'published':
|
||||
status = 'published';
|
||||
staticPages = false;
|
||||
break;
|
||||
case 'scheduled':
|
||||
status = 'scheduled';
|
||||
staticPages = false;
|
||||
break;
|
||||
case 'page':
|
||||
staticPages = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
status,
|
||||
staticPages
|
||||
};
|
||||
}),
|
||||
|
||||
stepThroughPosts(step) {
|
||||
let currentPost = this.get('controller.selectedPost');
|
||||
let posts = this.get('controller.model');
|
||||
let length = posts.get('length');
|
||||
let newPosition;
|
||||
|
||||
// when the currentPost is deleted we won't be able to use indexOf.
|
||||
// we keep track of the index locally so we can select next after deletion
|
||||
if (this._selectedPostIndex !== null && length) {
|
||||
newPosition = this._selectedPostIndex + step;
|
||||
} else {
|
||||
newPosition = posts.indexOf(currentPost) + step;
|
||||
}
|
||||
|
||||
// if we are on the first or last item
|
||||
// just do nothing (desired behavior is to not
|
||||
// loop around)
|
||||
if (newPosition >= length) {
|
||||
return;
|
||||
} else if (newPosition < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._selectedPostIndex = newPosition;
|
||||
this.set('controller.selectedPost', posts.objectAt(newPosition));
|
||||
},
|
||||
|
||||
shortcuts: {
|
||||
'up, k': 'moveUp',
|
||||
'down, j': 'moveDown',
|
||||
'enter': 'editPost',
|
||||
'c': 'newPost',
|
||||
'command+backspace, ctrl+backspace': 'deletePost'
|
||||
},
|
||||
|
||||
resetController() {
|
||||
this.set('controller.selectedPost', null);
|
||||
this.set('controller.showDeletePostModal', false);
|
||||
},
|
||||
|
||||
actions: {
|
||||
willTransition() {
|
||||
this._selectedPostIndex = null;
|
||||
|
||||
if (this.get('controller')) {
|
||||
this.resetController();
|
||||
}
|
||||
},
|
||||
|
||||
queryParamsDidChange() {
|
||||
// on direct page load controller won't exist so we want to
|
||||
// avoid a double transition
|
||||
if (this.get('controller')) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
// scroll back to the top
|
||||
$('.content-list').scrollTop(0);
|
||||
},
|
||||
|
||||
newPost() {
|
||||
this.transitionTo('editor.new');
|
||||
},
|
||||
|
||||
moveUp() {
|
||||
this.stepThroughPosts(-1);
|
||||
},
|
||||
|
||||
moveDown() {
|
||||
this.stepThroughPosts(1);
|
||||
},
|
||||
|
||||
editPost() {
|
||||
let selectedPost = this.get('controller.selectedPost');
|
||||
|
||||
if (selectedPost) {
|
||||
this.transitionTo('editor.edit', selectedPost.get('id'));
|
||||
}
|
||||
},
|
||||
|
||||
deletePost() {
|
||||
this.get('controller').send('toggleDeletePostModal');
|
||||
},
|
||||
|
||||
onPostDeletion() {
|
||||
// select next post (re-select the current index)
|
||||
this.stepThroughPosts(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
|
||||
import ShortcutsRoute from 'ghost-admin/mixins/shortcuts-route';
|
||||
import InfinityRoute from 'ember-infinity/mixins/route';
|
||||
import computed from 'ember-computed';
|
||||
import {assign} from 'ember-platform';
|
||||
import $ from 'jquery';
|
||||
|
||||
export default AuthenticatedRoute.extend(InfinityRoute, ShortcutsRoute, {
|
||||
|
||||
perPage: 30,
|
||||
perPageParam: 'limit',
|
||||
totalPagesParam: 'meta.pagination.pages',
|
||||
|
||||
_type: null,
|
||||
_selectedPostIndex: null,
|
||||
|
||||
model(params) {
|
||||
this.set('_type', params.type);
|
||||
let filterSettings = this.get('filterSettings');
|
||||
|
||||
return this.get('session.user').then((user) => {
|
||||
if (user.get('isAuthor')) {
|
||||
filterSettings.filter = filterSettings.filter
|
||||
? `${filterSettings.filter}+author:${user.get('slug')}` : `author:${user.get('slug')}`;
|
||||
}
|
||||
|
||||
let perPage = this.get('perPage');
|
||||
let paginationSettings = assign({perPage, startingPage: 1}, filterSettings);
|
||||
|
||||
return this.infinityModel('post', paginationSettings);
|
||||
});
|
||||
},
|
||||
|
||||
filterSettings: computed('_type', function () {
|
||||
let type = this.get('_type');
|
||||
let status = 'all';
|
||||
let staticPages = 'all';
|
||||
|
||||
switch (type) {
|
||||
case 'draft':
|
||||
status = 'draft';
|
||||
staticPages = false;
|
||||
break;
|
||||
case 'published':
|
||||
status = 'published';
|
||||
staticPages = false;
|
||||
break;
|
||||
case 'scheduled':
|
||||
status = 'scheduled';
|
||||
staticPages = false;
|
||||
break;
|
||||
case 'page':
|
||||
staticPages = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
status,
|
||||
staticPages
|
||||
};
|
||||
}),
|
||||
|
||||
stepThroughPosts(step) {
|
||||
let currentPost = this.get('controller.selectedPost');
|
||||
let posts = this.get('controller.model');
|
||||
let length = posts.get('length');
|
||||
let newPosition;
|
||||
|
||||
// when the currentPost is deleted we won't be able to use indexOf.
|
||||
// we keep track of the index locally so we can select next after deletion
|
||||
if (this._selectedPostIndex !== null && length) {
|
||||
newPosition = this._selectedPostIndex + step;
|
||||
} else {
|
||||
newPosition = posts.indexOf(currentPost) + step;
|
||||
}
|
||||
|
||||
// if we are on the first or last item
|
||||
// just do nothing (desired behavior is to not
|
||||
// loop around)
|
||||
if (newPosition >= length) {
|
||||
return;
|
||||
} else if (newPosition < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._selectedPostIndex = newPosition;
|
||||
this.set('controller.selectedPost', posts.objectAt(newPosition));
|
||||
},
|
||||
|
||||
shortcuts: {
|
||||
'up, k': 'moveUp',
|
||||
'down, j': 'moveDown',
|
||||
'enter': 'editPost',
|
||||
'c': 'newPost',
|
||||
'command+backspace, ctrl+backspace': 'deletePost'
|
||||
},
|
||||
|
||||
resetController() {
|
||||
this.set('controller.selectedPost', null);
|
||||
this.set('controller.showDeletePostModal', false);
|
||||
},
|
||||
|
||||
actions: {
|
||||
willTransition() {
|
||||
this._selectedPostIndex = null;
|
||||
|
||||
if (this.get('controller')) {
|
||||
this.resetController();
|
||||
}
|
||||
},
|
||||
|
||||
queryParamsDidChange() {
|
||||
// on direct page load controller won't exist so we want to
|
||||
// avoid a double transition
|
||||
if (this.get('controller')) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
// scroll back to the top
|
||||
$('.content-list').scrollTop(0);
|
||||
},
|
||||
|
||||
newPost() {
|
||||
this.transitionTo('editor.new');
|
||||
},
|
||||
|
||||
moveUp() {
|
||||
this.stepThroughPosts(-1);
|
||||
},
|
||||
|
||||
moveDown() {
|
||||
this.stepThroughPosts(1);
|
||||
},
|
||||
|
||||
editPost() {
|
||||
let selectedPost = this.get('controller.selectedPost');
|
||||
|
||||
if (selectedPost) {
|
||||
this.transitionTo('editor.edit', selectedPost.get('id'));
|
||||
}
|
||||
},
|
||||
|
||||
deletePost() {
|
||||
this.get('controller').send('toggleDeletePostModal');
|
||||
},
|
||||
|
||||
onPostDeletion() {
|
||||
// select next post (re-select the current index)
|
||||
this.stepThroughPosts(0);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title">Your stories</h2>
|
||||
<section class="view-actions">
|
||||
{{#link-to "editor.new" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New story</span>{{/link-to}}
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<ul class="gh-contentfilter">
|
||||
{{#active-link}}
|
||||
{{link-to "All" "posts.index" (query-params type=null) data-test-all-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Drafts" "posts.index" (query-params type="draft") data-test-drafts-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Published" "posts.index" (query-params type="published") data-test-published-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Scheduled" "posts.index" (query-params type="scheduled") data-test-scheduled-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Pages" "posts.index" (query-params type="page") data-test-pages-filter-link=true}}
|
||||
{{/active-link}}
|
||||
</ul>
|
|
@ -35,7 +35,7 @@
|
|||
{{#if (eq routing.currentRouteName "posts.index")}}
|
||||
{{#link-to "posts" (query-params type=null) classNames="gh-nav-main-content active"}}<i class="icon-content"></i>Stories{{/link-to}}
|
||||
{{else}}
|
||||
{{#link-to "posts" classNames="gh-nav-main-content"}}<i class="icon-content"></i>Content{{/link-to}}
|
||||
{{#link-to "posts" classNames="gh-nav-main-content"}}<i class="icon-content"></i>Stories{{/link-to}}
|
||||
{{/if}}
|
||||
</li>
|
||||
<li>{{#link-to "team" classNames="gh-nav-main-users"}}<i class="icon-team"></i>Team{{/link-to}}</li>
|
||||
|
|
|
@ -1,7 +1,28 @@
|
|||
<section class="gh-canvas">
|
||||
{{partial "posts-header"}}
|
||||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title">Your stories</h2>
|
||||
<section class="view-actions">
|
||||
{{#link-to "editor.new" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New story</span>{{/link-to}}
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<section class="content-list">
|
||||
{{gh-loading-spinner}}
|
||||
</section>
|
||||
<div class="gh-contentfilter">
|
||||
{{#active-link}}
|
||||
{{link-to "All" "posts.index" (query-params type=null) data-test-all-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Drafts" "posts.index" (query-params type="draft") data-test-drafts-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Published" "posts.index" (query-params type="published") data-test-published-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Scheduled" "posts.index" (query-params type="scheduled") data-test-scheduled-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Pages" "posts.index" (query-params type="page") data-test-pages-filter-link=true}}
|
||||
{{/active-link}}
|
||||
</div>
|
||||
|
||||
{{gh-loading-spinner}}
|
||||
</section>
|
||||
|
|
|
@ -1,5 +1,67 @@
|
|||
<section class="gh-canvas">
|
||||
{{partial "posts-header"}}
|
||||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title">Your stories</h2>
|
||||
<section class="view-actions">
|
||||
{{#link-to "editor.new" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New story</span>{{/link-to}}
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<div class="gh-contentfilter">
|
||||
{{#active-link}}
|
||||
{{link-to "All" "posts.index" (query-params type=null) data-test-all-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Drafts" "posts.index" (query-params type="draft") data-test-drafts-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Published" "posts.index" (query-params type="published") data-test-published-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Scheduled" "posts.index" (query-params type="scheduled") data-test-scheduled-filter-link=true}}
|
||||
{{/active-link}}
|
||||
{{#active-link}}
|
||||
{{link-to "Pages" "posts.index" (query-params type="page") data-test-pages-filter-link=true}}
|
||||
{{/active-link}}
|
||||
</div>
|
||||
|
||||
<section class="content-list">
|
||||
<ol class="posts-list">
|
||||
{{#each model as |post|}}
|
||||
{{gh-posts-list-item
|
||||
post=post
|
||||
active=(eq post selectedPost)
|
||||
onDoubleClick="openEditor"
|
||||
data-test-posts-list-item-id=post.id}}
|
||||
{{else}}
|
||||
<li class="no-posts-box">
|
||||
<div class="no-posts">
|
||||
{{#if showingAll}}
|
||||
<h3>You Haven't Written Any Posts Yet!</h3>
|
||||
{{#link-to "editor.new"}}<button type="button" class="gh-btn gh-btn-green gh-btn-lg"><span>Write a new Post</span></button>{{/link-to}}
|
||||
{{else}}
|
||||
<h3>No posts that match the current filter</h3>
|
||||
{{#link-to "posts.index" (query-params type=null)}}<button type="button" class="gh-btn gh-btn-lg"><span>Show all posts</span></button>{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
||||
{{infinity-loader
|
||||
infinityModel=model
|
||||
scrollable=".gh-main"
|
||||
triggerOffset=1000}}
|
||||
</section>
|
||||
|
||||
{{#if showDeletePostModal}}
|
||||
{{gh-fullscreen-modal "delete-post"
|
||||
model=(hash
|
||||
post=selectedPost
|
||||
onSuccess=(route-action 'onPostDeletion')
|
||||
)
|
||||
close=(action "toggleDeletePostModal")
|
||||
modifier="action wide"}}
|
||||
{{/if}}
|
||||
|
||||
{{outlet}}
|
||||
</section>
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<section class="content-list">
|
||||
<ol class="posts-list">
|
||||
{{#each model as |post|}}
|
||||
{{gh-posts-list-item
|
||||
post=post
|
||||
active=(eq post selectedPost)
|
||||
onDoubleClick="openEditor"
|
||||
data-test-posts-list-item-id=post.id}}
|
||||
{{else}}
|
||||
<li class="no-posts-box">
|
||||
<div class="no-posts">
|
||||
{{#if showingAll}}
|
||||
<h3>You Haven't Written Any Posts Yet!</h3>
|
||||
{{#link-to "editor.new"}}<button type="button" class="gh-btn gh-btn-green gh-btn-lg"><span>Write a new Post</span></button>{{/link-to}}
|
||||
{{else}}
|
||||
<h3>No posts that match the current filter</h3>
|
||||
{{#link-to "posts.index" (query-params type=null)}}<button type="button" class="gh-btn gh-btn-lg"><span>Show all posts</span></button>{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
||||
{{infinity-loader
|
||||
infinityModel=model
|
||||
scrollable=".gh-main"
|
||||
triggerOffset=1000}}
|
||||
</section>
|
||||
|
||||
{{#if showDeletePostModal}}
|
||||
{{gh-fullscreen-modal "delete-post"
|
||||
model=(hash
|
||||
post=selectedPost
|
||||
onSuccess=(route-action 'onPostDeletion')
|
||||
)
|
||||
close=(action "toggleDeletePostModal")
|
||||
modifier="action wide"}}
|
||||
{{/if}}
|
||||
|
||||
{{outlet}}
|
Loading…
Reference in a new issue