Extracted duplicated posts/pages filter into a component

no issue

- posts and pages (and their corresponding `-loading` counterparts) templates were all duplicating a lengthy section of handlebars
- extracted the duplicated handlebars into a template for easier design changes or upgrading of `ember-power-select`
- moved generation of the "selected" CSS classes into the template to clean up code in the controller
This commit is contained in:
Kevin Ansfield 2020-01-15 15:15:20 +00:00
parent 7c7c4962f9
commit 0f8610a6e9
8 changed files with 136 additions and 333 deletions

View File

@ -0,0 +1,6 @@
import Component from '@glimmer/component';
import {inject as service} from '@ember/service';
export default class GhContentfilterComponent extends Component {
@service session
}

View File

@ -17,23 +17,11 @@ const TYPES = [{
value: 'featured' value: 'featured'
}]; }];
const ORDERS = [{
name: 'Newest',
value: null
}, {
name: 'Oldest',
value: 'published_at asc'
}, {
name: 'Recently updated',
value: 'updated_at desc'
}];
/* eslint-disable ghost/ember/alias-model-in-controller */ /* eslint-disable ghost/ember/alias-model-in-controller */
export default PostsController.extend({ export default PostsController.extend({
init() { init() {
this._super(...arguments); this._super(...arguments);
this.availableTypes = TYPES; this.availableTypes = TYPES;
this.availableOrders = ORDERS;
}, },
actions: { actions: {

View File

@ -34,7 +34,6 @@ const ORDERS = [{
export default Controller.extend({ export default Controller.extend({
session: service(),
store: service(), store: service(),
queryParams: ['type', 'author', 'tag', 'order'], queryParams: ['type', 'author', 'tag', 'order'],
@ -116,30 +115,6 @@ export default Controller.extend({
return authors.findBy('slug', author); return authors.findBy('slug', author);
}), }),
typeClassNames: computed('type', function () {
let classNames = 'gh-contentfilter-menu gh-contentfilter-type';
if (this.get('type')) {
classNames = classNames + ' gh-contentfilter-selected';
}
return classNames;
}),
authorClassNames: computed('author', function () {
let classNames = 'gh-contentfilter-menu gh-contentfilter-author';
if (this.get('author')) {
classNames = classNames + ' gh-contentfilter-selected';
}
return classNames;
}),
tagClassNames: computed('tag', function () {
let classNames = 'gh-contentfilter-menu gh-contentfilter-tag';
if (this.get('tag')) {
classNames = classNames + ' gh-contentfilter-selected';
}
return classNames;
}),
actions: { actions: {
changeType(type) { changeType(type) {
this.set('type', get(type, 'value')); this.set('type', get(type, 'value'));

View File

@ -0,0 +1,74 @@
<div class="gh-contentfilter" ...attributes>
{{#unless this.session.user.isContributor}}
<PowerSelect
@selected={{@selectedType}}
@options={{@availableTypes}}
@searchEnabled={{false}}
@onChange={{@onTypeChange}}
@tagName="div"
@classNames={{concat "gh-contentfilter-menu gh-contentfilter-type " (if @selectedType.value "gh-contentfilter-selected")}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@matchTriggerWidth={{false}}
data-test-type-select="true"
as |type|
>
{{type.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isAuthorOrContributor}}
<PowerSelect
@selected={{@selectedAuthor}}
@options={{@availableAuthors}}
@searchField="name"
@onChange={{@onAuthorChange}}
@tagName="div"
@classNames={{concat "gh-contentfilter-menu gh-contentfilter-author " (if @selectedAuthor.slug "gh-contentfilter-selected")}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search authors"
@matchTriggerWidth={{false}}
data-test-author-select="true"
as |author|
>
{{author.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isContributor}}
<PowerSelect
@selected={{@selectedTag}}
@options={{@availableTags}}
@searchField="name"
@onChange={{@onTagChange}}
@tagName="div"
@classNames={{concat "gh-contentfilter-menu gh-contentfilter-tag " (if @selectedTag.slug "gh-contentfilter-selected")}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search tags"
@matchTriggerWidth={{false}}
@optionsComponent="power-select-vertical-collection-options"
data-test-tag-select="true"
as |tag|
>
{{tag.name}}
</PowerSelect>
{{/unless}}
<PowerSelect
@selected={{@selectedOrder}}
@options={{@availableOrders}}
@searchEnabled={{false}}
@onChange={{@onOrderChange}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-sort"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@matchTriggerWidth={{false}}
@data-test-order-select="true"
as |order|
>
{{order.name}}
</PowerSelect>
</div>

View File

@ -2,80 +2,20 @@
<header class="gh-canvas-header post-header"> <header class="gh-canvas-header post-header">
<h2 class="gh-canvas-title" data-test-screen-title>Pages</h2> <h2 class="gh-canvas-title" data-test-screen-title>Pages</h2>
<section class="view-actions"> <section class="view-actions">
<div class="gh-contentfilter"> <GhContentfilter
{{#unless this.session.user.isContributor}} @selectedType={{this.selectedType}}
<PowerSelect @availableTypes={{this.availableTypes}}
@selected={{this.selectedType}} @onTypeChange={{action (mut k)}}
@options={{this.availableTypes}} @selectedAuthor={{this.selectedAuthor}}
@searchEnabled={{false}} @availableAuthors={{this.availableAuthors}}
@onChange={{action (mut k)}} @onAuthorChange={{action (mut k)}}
@tagName="div" @selectedTag={{this.selectedTag}}
@classNames="gh-contentfilter-menu gh-contentfilter-type" @availableTags={{this.availableTags}}
@triggerClass="gh-contentfilter-menu-trigger" @onTagChange={{action (mut k)}}
@dropdownClass="gh-contentfilter-menu-dropdown" @selectedOrder={{this.selectedOrder}}
@matchTriggerWidth={{false}} @availableOrders={{this.availableOrders}}
data-test-type-select="true" @onOrderChange={{action (mut k)}}
as |type| />
>
{{type.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isAuthorOrContributor}}
<PowerSelect
@selected={{this.selectedAuthor}}
@options={{this.availableAuthors}}
@searchField="name"
@onChange={{action (mut k)}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-author"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search authors"
@matchTriggerWidth={{false}}
data-test-author-select="true"
as |author|
>
{{author.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isContributor}}
<PowerSelect
@selected={{this.selectedTag}}
@options={{this.availableTags}}
@searchField="name"
@onChange={{action (mut k)}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-tag"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search tags"
@matchTriggerWidth={{false}}
@optionsComponent="power-select-vertical-collection-options"
data-test-tag-select="true"
as |tag|
>
{{tag.name}}
</PowerSelect>
{{/unless}}
<PowerSelect
@selected={{this.selectedOrder}}
@options={{this.availableOrders}}
@searchEnabled={{false}}
@onChange={{action (mut k)}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-sort"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@matchTriggerWidth={{false}}
data-test-order-select="true"
as |order|
>
{{order.name}}
</PowerSelect>
</div>
{{#link-to "editor.new" "page" class="gh-btn gh-btn-green" data-test-new-page-button=true}}<span>New page</span>{{/link-to}} {{#link-to "editor.new" "page" class="gh-btn gh-btn-green" data-test-new-page-button=true}}<span>New page</span>{{/link-to}}
</section> </section>

View File

@ -2,80 +2,20 @@
<GhCanvasHeader class="gh-canvas-header post-header"> <GhCanvasHeader class="gh-canvas-header post-header">
<h2 class="gh-canvas-title" data-test-screen-title>Pages</h2> <h2 class="gh-canvas-title" data-test-screen-title>Pages</h2>
<section class="view-actions"> <section class="view-actions">
<div class="gh-contentfilter"> <GhContentfilter
{{#unless this.session.user.isContributor}} @selectedType={{this.selectedType}}
<PowerSelect @availableTypes={{this.availableTypes}}
@selected={{this.selectedType}} @onTypeChange={{action "changeType"}}
@options={{this.availableTypes}} @selectedAuthor={{this.selectedAuthor}}
@searchEnabled={{false}} @availableAuthors={{this.availableAuthors}}
@onChange={{action "changeType"}} @onAuthorChange={{action "changeAuthor"}}
@tagName="div" @selectedTag={{this.selectedTag}}
@classNames={{this.typeClassNames}} @availableTags={{this.availableTags}}
@triggerClass="gh-contentfilter-menu-trigger" @onTagChange={{action "changeTag"}}
@dropdownClass="gh-contentfilter-menu-dropdown" @selectedOrder={{this.selectedOrder}}
@matchTriggerWidth={{false}} @availableOrders={{this.availableOrders}}
data-test-type-select="true" @onOrderChange={{action "changeOrder"}}
as |type| />
>
{{type.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isAuthorOrContributor}}
<PowerSelect
@selected={{this.selectedAuthor}}
@options={{this.availableAuthors}}
@searchField="name"
@onChange={{action "changeAuthor"}}
@tagName="div"
@classNames={{this.authorClassNames}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search authors"
@matchTriggerWidth={{false}}
data-test-author-select="true"
as |author|
>
{{author.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isContributor}}
<PowerSelect
@selected={{this.selectedTag}}
@options={{this.availableTags}}
@searchField="name"
@onChange={{action "changeTag"}}
@tagName="div"
@classNames={{this.tagClassNames}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search tags"
@matchTriggerWidth={{false}}
@optionsComponent="power-select-vertical-collection-options"
data-test-tag-select="true"
as |tag|
>
{{tag.name}}
</PowerSelect>
{{/unless}}
<PowerSelect
@selected={{this.selectedOrder}}
@options={{this.availableOrders}}
@searchEnabled={{false}}
@onChange={{action "changeOrder"}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-sort"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@matchTriggerWidth={{false}}
@data-test-order-select="true"
as |order|
>
{{order.name}}
</PowerSelect>
</div>
{{#link-to "editor.new" "page" class="gh-btn gh-btn-green" data-test-new-page-button=true}}<span>New page</span>{{/link-to}} {{#link-to "editor.new" "page" class="gh-btn gh-btn-green" data-test-new-page-button=true}}<span>New page</span>{{/link-to}}
</section> </section>

View File

@ -2,80 +2,20 @@
<header class="gh-canvas-header post-header"> <header class="gh-canvas-header post-header">
<h2 class="gh-canvas-title" data-test-screen-title>Posts</h2> <h2 class="gh-canvas-title" data-test-screen-title>Posts</h2>
<section class="view-actions"> <section class="view-actions">
<div class="gh-contentfilter"> <GhContentfilter
{{#unless this.session.user.isContributor}} @selectedType={{this.selectedType}}
<PowerSelect @availableTypes={{this.availableTypes}}
@selected={{this.selectedType}} @onTypeChange={{action (mut k)}}
@options={{this.availableTypes}} @selectedAuthor={{this.selectedAuthor}}
@searchEnabled={{false}} @availableAuthors={{this.availableAuthors}}
@onChange={{action (mut k)}} @onAuthorChange={{action (mut k)}}
@tagName="div" @selectedTag={{this.selectedTag}}
@classNames="gh-contentfilter-menu gh-contentfilter-type" @availableTags={{this.availableTags}}
@triggerClass="gh-contentfilter-menu-trigger" @onTagChange={{action (mut k)}}
@dropdownClass="gh-contentfilter-menu-dropdown" @selectedOrder={{this.selectedOrder}}
@matchTriggerWidth={{false}} @availableOrders={{this.availableOrders}}
data-test-type-select="true" @onOrderChange={{action (mut k)}}
as |type| />
>
{{type.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isAuthorOrContributor}}
<PowerSelect
@selected={{this.selectedAuthor}}
@options={{this.availableAuthors}}
@searchField="name"
@onChange={{action (mut k)}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-author"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search authors"
@matchTriggerWidth={{false}}
data-test-author-select="true"
as |author|
>
{{author.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isContributor}}
<PowerSelect
@selected={{this.selectedTag}}
@options={{this.availableTags}}
@searchField="name"
@onChange={{action (mut k)}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-tag"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search tags"
@matchTriggerWidth={{false}}
@optionsComponent="power-select-vertical-collection-options"
data-test-tag-select="true"
as |tag|
>
{{tag.name}}
</PowerSelect>
{{/unless}}
<PowerSelect
@selected={{this.selectedOrder}}
@options={{this.availableOrders}}
@searchEnabled={{false}}
@onChange={{action (mut k)}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-sort"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@matchTriggerWidth={{false}}
data-test-order-select="true"
as |order|
>
{{order.name}}
</PowerSelect>
</div>
{{#link-to "editor.new" "post" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New post</span>{{/link-to}} {{#link-to "editor.new" "post" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New post</span>{{/link-to}}
</section> </section>

View File

@ -2,80 +2,20 @@
<GhCanvasHeader class="gh-canvas-header post-header"> <GhCanvasHeader class="gh-canvas-header post-header">
<h2 class="gh-canvas-title" data-test-screen-title>Posts</h2> <h2 class="gh-canvas-title" data-test-screen-title>Posts</h2>
<section class="view-actions"> <section class="view-actions">
<div class="gh-contentfilter"> <GhContentfilter
{{#unless this.session.user.isContributor}} @selectedType={{this.selectedType}}
<PowerSelect @availableTypes={{this.availableTypes}}
@selected={{this.selectedType}} @onTypeChange={{action "changeType"}}
@options={{this.availableTypes}} @selectedAuthor={{this.selectedAuthor}}
@searchEnabled={{false}} @availableAuthors={{this.availableAuthors}}
@onChange={{action "changeType"}} @onAuthorChange={{action "changeAuthor"}}
@tagName="div" @selectedTag={{this.selectedTag}}
@classNames={{this.typeClassNames}} @availableTags={{this.availableTags}}
@triggerClass="gh-contentfilter-menu-trigger" @onTagChange={{action "changeTag"}}
@dropdownClass="gh-contentfilter-menu-dropdown" @selectedOrder={{this.selectedOrder}}
@matchTriggerWidth={{false}} @availableOrders={{this.availableOrders}}
data-test-type-select="true" @onOrderChange={{action "changeOrder"}}
as |type| />
>
{{type.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isAuthorOrContributor}}
<PowerSelect
@selected={{this.selectedAuthor}}
@options={{this.availableAuthors}}
@searchField="name"
@onChange={{action "changeAuthor"}}
@tagName="div"
@classNames={{this.authorClassNames}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search authors"
@matchTriggerWidth={{false}}
data-test-author-select="true"
as |author|
>
{{author.name}}
</PowerSelect>
{{/unless}}
{{#unless this.session.user.isContributor}}
<PowerSelect
@selected={{this.selectedTag}}
@options={{this.availableTags}}
@searchField="name"
@onChange={{action "changeTag"}}
@tagName="div"
@classNames={{this.tagClassNames}}
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@searchPlaceholder="Search tags"
@matchTriggerWidth={{false}}
@optionsComponent="power-select-vertical-collection-options"
data-test-tag-select="true"
as |tag|
>
{{tag.name}}
</PowerSelect>
{{/unless}}
<PowerSelect
@selected={{this.selectedOrder}}
@options={{this.availableOrders}}
@searchEnabled={{false}}
@onChange={{action "changeOrder"}}
@tagName="div"
@classNames="gh-contentfilter-menu gh-contentfilter-sort"
@triggerClass="gh-contentfilter-menu-trigger"
@dropdownClass="gh-contentfilter-menu-dropdown"
@matchTriggerWidth={{false}}
@data-test-order-select="true"
as |order|
>
{{order.name}}
</PowerSelect>
</div>
{{#link-to "editor.new" "post" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New post</span>{{/link-to}} {{#link-to "editor.new" "post" class="gh-btn gh-btn-green" data-test-new-post-button=true}}<span>New post</span>{{/link-to}}
</section> </section>