mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 20:03:12 +03:00
✨ Added access level filter to posts and pages lists in admin
no issue - adds `visibility` query param to posts and pages controllers/routes that is tied to the `filter` query param used in API requests - adds dropdown for selecting post/page visibility to `<GhContentFilter>`
This commit is contained in:
parent
1a69f391ea
commit
758f5285fb
@ -17,6 +17,24 @@
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#if this.feature.members}}
|
||||
<div class="gh-contentfilter-menu gh-contentfilter-visibility {{if @selectedVisibility.value "gh-contentfilter-selected"}}" data-test-visibility-select="true">
|
||||
<PowerSelect
|
||||
@selected={{@selectedVisibility}}
|
||||
@options={{@availableVisibilities}}
|
||||
@searchEnabled={{false}}
|
||||
@onChange={{@onVisibilityChange}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
@triggerClass="gh-contentfilter-menu-trigger"
|
||||
@dropdownClass="gh-contentfilter-menu-dropdown"
|
||||
@matchTriggerWidth={{false}}
|
||||
as |visibility|
|
||||
>
|
||||
{{#if visibility.name}}{{visibility.name}}{{else}}<span class="red">Unknown visibility</span>{{/if}}
|
||||
</PowerSelect>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#unless @currentUser.isAuthorOrContributor}}
|
||||
<div class="gh-contentfilter-menu gh-contentfilter-author {{if @selectedAuthor.slug "gh-contentfilter-selected"}}" data-test-author-select="true">
|
||||
<PowerSelect
|
||||
|
@ -4,6 +4,7 @@ import {inject as service} from '@ember/service';
|
||||
|
||||
export default class GhContentfilterComponent extends Component {
|
||||
@service customViews;
|
||||
@service feature;
|
||||
@service router;
|
||||
|
||||
get showCustomViewManagement() {
|
||||
@ -11,6 +12,7 @@ export default class GhContentfilterComponent extends Component {
|
||||
let onPostsScreen = this.router.currentRouteName === 'posts';
|
||||
let isDefaultView = this.customViews?.activeView?.isDefault;
|
||||
let hasFilter = this.args.selectedType.value
|
||||
|| this.args.selectedVisibility.value
|
||||
|| this.args.selectedAuthor.slug
|
||||
|| this.args.selectedTag.slug
|
||||
|| this.args.selectedOrder.value;
|
||||
|
@ -76,13 +76,11 @@
|
||||
{{/unless}}
|
||||
|
||||
|
||||
{{#if this.feature.members}}
|
||||
{{#if this.showVisibilityInput}}
|
||||
<div class="form-group">
|
||||
<label for="visibility-input">Post access</label>
|
||||
<GhPsmVisibilityInput @post={{this.post}} @triggerId="visibility-input" />
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (and this.feature.members this.showVisibilityInput)}}
|
||||
<div class="form-group">
|
||||
<label for="visibility-input">Post access</label>
|
||||
<GhPsmVisibilityInput @post={{this.post}} @triggerId="visibility-input" />
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
||||
|
@ -11,6 +11,8 @@ export default Controller.extend({
|
||||
|
||||
availableTypes: readOnly('postsController.availableTypes'),
|
||||
selectedType: readOnly('postsController.selectedType'),
|
||||
selectedVisibility: readOnly('postsController.selectedVisibility'),
|
||||
availableVisibilities: readOnly('postsController.availableVisibilities'),
|
||||
availableTags: readOnly('postsController.availableTags'),
|
||||
selectedTag: readOnly('postsController.selectedTag'),
|
||||
availableAuthors: readOnly('postsController.availableAuthors'),
|
||||
|
@ -22,6 +22,20 @@ const TYPES = [{
|
||||
value: 'featured'
|
||||
}];
|
||||
|
||||
const VISIBILITIES = [{
|
||||
name: 'All access',
|
||||
value: null
|
||||
}, {
|
||||
name: 'Public',
|
||||
value: 'public'
|
||||
}, {
|
||||
name: 'Members-only',
|
||||
value: 'members'
|
||||
}, {
|
||||
name: 'Paid members-only',
|
||||
value: 'paid'
|
||||
}];
|
||||
|
||||
const ORDERS = [{
|
||||
name: 'Newest',
|
||||
value: null
|
||||
@ -38,27 +52,29 @@ export default Controller.extend({
|
||||
store: service(),
|
||||
|
||||
// default values for these are set in `init` and defined in `helpers/reset-query-params`
|
||||
queryParams: ['type', 'author', 'tag', 'order'],
|
||||
queryParams: ['type', 'access', 'author', 'tag', 'order'],
|
||||
|
||||
_hasLoadedTags: false,
|
||||
_hasLoadedAuthors: false,
|
||||
|
||||
availableTypes: null,
|
||||
availableVisibilities: null,
|
||||
availableOrders: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.availableTypes = TYPES;
|
||||
this.availableOrders = ORDERS;
|
||||
this.availableVisibilities = VISIBILITIES;
|
||||
this.setProperties(DEFAULT_QUERY_PARAMS.posts);
|
||||
},
|
||||
|
||||
postsInfinityModel: alias('model'),
|
||||
|
||||
showingAll: computed('type', 'author', 'tag', function () {
|
||||
let {type, author, tag} = this.getProperties(['type', 'author', 'tag']);
|
||||
let {type, author, tag, visibility} = this.getProperties(['type', 'visibility', 'author', 'tag']);
|
||||
|
||||
return !type && !author && !tag;
|
||||
return !type && !visibility && !author && !tag;
|
||||
}),
|
||||
|
||||
selectedType: computed('type', function () {
|
||||
@ -66,6 +82,11 @@ export default Controller.extend({
|
||||
return types.findBy('value', this.get('type')) || {value: '!unknown'};
|
||||
}),
|
||||
|
||||
selectedVisibility: computed('visibility', function () {
|
||||
let visibilities = this.get('availableVisibilities');
|
||||
return visibilities.findBy('value', this.get('visibility')) || {value: '!unknown'};
|
||||
}),
|
||||
|
||||
selectedOrder: computed('order', function () {
|
||||
let orders = this.get('availableOrders');
|
||||
return orders.findBy('value', this.get('order')) || {value: '!unknown'};
|
||||
@ -117,6 +138,10 @@ export default Controller.extend({
|
||||
this.set('type', get(type, 'value'));
|
||||
},
|
||||
|
||||
changeVisibility(visibility) {
|
||||
this.set('visibility', get(visibility, 'value'));
|
||||
},
|
||||
|
||||
changeAuthor(author) {
|
||||
this.set('author', get(author, 'slug'));
|
||||
},
|
||||
|
@ -3,12 +3,14 @@ import {helper} from '@ember/component/helper';
|
||||
export const DEFAULT_QUERY_PARAMS = {
|
||||
posts: {
|
||||
type: null,
|
||||
visibility: null,
|
||||
author: null,
|
||||
tag: null,
|
||||
order: null
|
||||
},
|
||||
pages: {
|
||||
type: null,
|
||||
visibility: null,
|
||||
author: null,
|
||||
tag: null,
|
||||
order: null
|
||||
|
@ -9,6 +9,8 @@ export default AuthenticatedRoute.extend({
|
||||
|
||||
queryParams: {
|
||||
type: {refreshModel: true},
|
||||
visibility: {refreshModel: true},
|
||||
access: {refreshModel: true},
|
||||
author: {refreshModel: true},
|
||||
tag: {refreshModel: true},
|
||||
order: {refreshModel: true}
|
||||
@ -38,7 +40,7 @@ export default AuthenticatedRoute.extend({
|
||||
model(params) {
|
||||
return this.session.user.then((user) => {
|
||||
let queryParams = {};
|
||||
let filterParams = {tag: params.tag};
|
||||
let filterParams = {tag: params.tag, visibility: params.visibility};
|
||||
let paginationParams = {
|
||||
perPageParam: 'limit',
|
||||
totalPagesParam: 'meta.pagination.pages'
|
||||
|
@ -7,6 +7,9 @@
|
||||
@selectedType={{this.selectedType}}
|
||||
@availableTypes={{this.availableTypes}}
|
||||
@onTypeChange={{action (mut k)}}
|
||||
@selectedVisibility={{this.selectedVisibility}}
|
||||
@availableVisibilities={{this.availableVisibilities}}
|
||||
@onVisibilityChange={{action (mut k)}}
|
||||
@selectedAuthor={{this.selectedAuthor}}
|
||||
@availableAuthors={{this.availableAuthors}}
|
||||
@onAuthorChange={{action (mut k)}}
|
||||
|
@ -8,6 +8,9 @@
|
||||
@selectedType={{this.selectedType}}
|
||||
@availableTypes={{this.availableTypes}}
|
||||
@onTypeChange={{action "changeType"}}
|
||||
@selectedVisibility={{this.selectedVisibility}}
|
||||
@availableVisibilities={{this.availableVisibilities}}
|
||||
@onVisibilityChange={{action "changeVisibility"}}
|
||||
@selectedAuthor={{this.selectedAuthor}}
|
||||
@availableAuthors={{this.availableAuthors}}
|
||||
@onAuthorChange={{action "changeAuthor"}}
|
||||
|
@ -7,6 +7,9 @@
|
||||
@selectedType={{this.selectedType}}
|
||||
@availableTypes={{this.availableTypes}}
|
||||
@onTypeChange={{action (mut k)}}
|
||||
@selectedVisibility={{this.selectedVisibility}}
|
||||
@availableVisibilities={{this.availableVisibilities}}
|
||||
@onVisibilityChange={{action (mut k)}}
|
||||
@selectedAuthor={{this.selectedAuthor}}
|
||||
@availableAuthors={{this.availableAuthors}}
|
||||
@onAuthorChange={{action (mut k)}}
|
||||
|
@ -8,6 +8,9 @@
|
||||
@selectedType={{this.selectedType}}
|
||||
@availableTypes={{this.availableTypes}}
|
||||
@onTypeChange={{action "changeType"}}
|
||||
@selectedVisibility={{this.selectedVisibility}}
|
||||
@availableVisibilities={{this.availableVisibilities}}
|
||||
@onVisibilityChange={{action "changeVisibility"}}
|
||||
@selectedAuthor={{this.selectedAuthor}}
|
||||
@availableAuthors={{this.availableAuthors}}
|
||||
@onAuthorChange={{action "changeAuthor"}}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {authenticateSession, invalidateSession} from 'ember-simple-auth/test-support';
|
||||
import {beforeEach, describe, it} from 'mocha';
|
||||
import {click, currentURL, fillIn, find, findAll, visit} from '@ember/test-helpers';
|
||||
import {click, currentURL, fillIn, find, findAll, settled, visit} from '@ember/test-helpers';
|
||||
import {clickTrigger, selectChoose} from 'ember-power-select/test-support/helpers';
|
||||
import {expect} from 'chai';
|
||||
import {setupApplicationTest} from 'ember-mocha';
|
||||
@ -86,8 +86,22 @@ describe('Acceptance: Content', function () {
|
||||
|
||||
// API request is correct
|
||||
[lastRequest] = this.server.pretender.handledRequests.slice(-1);
|
||||
expect(lastRequest.queryParams.filter, '"editor" request status filter').to.have.string('status:[draft,scheduled,published]');
|
||||
expect(lastRequest.queryParams.filter, '"editor" request filter param').to.have.string(`authors:${editor.slug}`);
|
||||
expect(lastRequest.queryParams.filter, '"editor" request status filter')
|
||||
.to.have.string('status:[draft,scheduled,published]');
|
||||
expect(lastRequest.queryParams.filter, '"editor" request filter param')
|
||||
.to.have.string(`authors:${editor.slug}`);
|
||||
|
||||
// Post status is only visible when members is enabled
|
||||
expect(find('[data-test-visibility-select]'), 'access dropdown before members enabled').to.not.exist;
|
||||
let featureService = this.owner.lookup('service:feature');
|
||||
featureService.set('members', true);
|
||||
await settled();
|
||||
expect(find('[data-test-visibility-select]'), 'access dropdown after members enabled').to.exist;
|
||||
|
||||
await selectChoose('[data-test-visibility-select]', 'Paid members-only');
|
||||
[lastRequest] = this.server.pretender.handledRequests.slice(-1);
|
||||
expect(lastRequest.queryParams.filter, '"visibility" request filter param')
|
||||
.to.have.string('visibility:paid+status:[draft,scheduled,published]');
|
||||
|
||||
// Displays editor post
|
||||
// TODO: implement "filter" param support and fix mirage post->author association
|
||||
|
Loading…
Reference in New Issue
Block a user