Mentions ordering (#16215)

closes https://github.com/TryGhost/Team/issues/2498

- can now order mentions via the API via params eg `api/admin/mentions/?order=created_at%20desc`.
This commit is contained in:
Ronald Langeveld 2023-02-02 13:25:09 +08:00 committed by GitHub
parent 855bcb8613
commit e02c67dd3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 4 deletions

View File

@ -51,8 +51,16 @@ module.exports = class MentionController {
page = 1;
}
let order;
if (frame.options.order && frame.options.order === 'created_at desc') {
order = 'created_at desc';
} else {
order = 'created_at asc';
}
const results = await this.#api.listMentions({
filter: frame.options.filter,
order,
limit,
page
});

View File

@ -62,16 +62,25 @@ module.exports = class InMemoryMentionRepository {
/**
* @param {object} options
* @param {string} [options.filter]
* @param {string} [options.order]
* @param {number | null} options.page
* @param {number | 'all'} options.limit
* @returns {Promise<Page<Mention>>}
*/
async getPage(options) {
const filter = nql(options.filter || '', {});
const results = this.#store.slice().filter((item) => {
const data = this.#store.slice();
const results = data.slice().filter((item) => {
return filter.queryJSON(this.toPrimitive(item));
});
if (options.order === 'created_at desc') {
results.sort((a, b) => {
return Number(b.timestamp) - Number(a.timestamp);
});
}
if (options.limit === 'all') {
return {
data: results,

View File

@ -18,6 +18,7 @@ const Mention = require('./Mention');
/**
* @typedef {object} PaginatedOptions
* @prop {string} [filter] A valid NQL string
* @prop {string} [order]
* @prop {number} page
* @prop {number} limit
*/
@ -25,6 +26,7 @@ const Mention = require('./Mention');
/**
* @typedef {object} NonPaginatedOptions
* @prop {string} [filter] A valid NQL string
* @prop {string} [order]
* @prop {'all'} limit
*/
@ -105,13 +107,15 @@ module.exports = class MentionsAPI {
if (options.limit === 'all') {
pageOptions = {
filter: options.filter,
limit: options.limit
limit: options.limit,
order: options.order
};
} else {
pageOptions = {
filter: options.filter,
limit: options.limit,
page: options.page
page: options.page,
order: options.order
};
}

View File

@ -3,6 +3,7 @@ const ObjectID = require('bson-objectid');
const Mention = require('../lib/Mention');
const MentionsAPI = require('../lib/MentionsAPI');
const InMemoryMentionRepository = require('../lib/InMemoryMentionRepository');
const sinon = require('sinon');
const mockRoutingService = {
async pageExists() {
@ -30,7 +31,17 @@ const mockWebmentionMetadata = {
}
};
function addMinutes(date, minutes) {
date.setMinutes(date.getMinutes() + minutes);
return date;
}
describe('MentionsAPI', function () {
beforeEach(function () {
sinon.restore();
});
it('Can list paginated mentions', async function () {
const repository = new InMemoryMentionRepository();
const api = new MentionsAPI({
@ -94,7 +105,6 @@ describe('MentionsAPI', function () {
target: new URL('https://target.com'),
payload: {}
});
const mentionTwo = await api.processWebmention({
source: new URL('https://source.com'),
target: new URL('https://target.com'),
@ -113,6 +123,78 @@ describe('MentionsAPI', function () {
assert(page.data[0].id === mentionTwo.id);
});
it('Can list mentions in descending order', async function () {
const repository = new InMemoryMentionRepository();
const api = new MentionsAPI({
repository,
routingService: mockRoutingService,
resourceService: mockResourceService,
webmentionMetadata: mockWebmentionMetadata
});
const mentionOne = await api.processWebmention({
source: new URL('https://source.com'),
target: new URL('https://target.com'),
payload: {}
});
sinon.useFakeTimers(addMinutes(new Date(), 10).getTime());
const mentionTwo = await api.processWebmention({
source: new URL('https://source2.com'),
target: new URL('https://target.com'),
payload: {}
});
assert(mentionOne instanceof Mention);
assert(mentionTwo instanceof Mention);
const page = await api.listMentions({
limit: 'all',
order: 'created_at desc'
});
assert(page.meta.pagination.total === 2);
assert(page.data[0].id === mentionTwo.id, 'First mention should be the second one in descending order');
assert(page.data[1].id === mentionOne.id, 'Second mention should be the first one in descending order');
});
it('Can list mentions in ascending order', async function () {
const repository = new InMemoryMentionRepository();
const api = new MentionsAPI({
repository,
routingService: mockRoutingService,
resourceService: mockResourceService,
webmentionMetadata: mockWebmentionMetadata
});
const mentionOne = await api.processWebmention({
source: new URL('https://source.com'),
target: new URL('https://target.com'),
payload: {}
});
sinon.useFakeTimers(addMinutes(new Date(), 10).getTime());
const mentionTwo = await api.processWebmention({
source: new URL('https://source2.com'),
target: new URL('https://target.com'),
payload: {}
});
assert(mentionOne instanceof Mention);
assert(mentionTwo instanceof Mention);
const page = await api.listMentions({
limit: 'all',
order: 'created_at asc'
});
assert(page.meta.pagination.total === 2);
assert(page.data[0].id === mentionOne.id, 'First mention should be the first one in ascending order');
assert(page.data[1].id === mentionTwo.id, 'Second mention should be the second one in ascending order');
});
it('Can handle updating mentions', async function () {
const repository = new InMemoryMentionRepository();
const api = new MentionsAPI({