feat: add order to pagination

This commit is contained in:
Chen, Tai-Lin committed 2023-12-21 17:28:48 +08:00
1 parent 68db16419d
commit fa36b63fbe
8 files changed
+85 -50

No files matched your search

@@ -1,18 +1,21 @@
/* eslint-disable object-shorthand */
import { Desc } from '../models/pagination.js'
import Pagination from '../models/pagination.js'
import { errorCommands } from '../models/commands.js'
// eslint-disable-next-line import/prefer-default-export
export async function commandListController(req, res) {
const { nextKey } = req.query
const { nextKey, order } = req.query
const itemsPerPage = 100
try {
const payload = await errorCommands(new Desc(itemsPerPage, nextKey))
const payload = await errorCommands(
new Pagination(order, itemsPerPage, nextKey)
)
const newNextKey = payload[payload.length - 1]?._id
res.render('commands', { errorCommands: payload, nextKey: newNextKey })
} catch (error) {
console.error(error)
res.status(500).send('Error fetching data')
}
}
@@ -1,15 +1,17 @@
import { Desc } from '../models/pagination.js'
import Pagination from '../models/pagination.js'
import { sessionList, sessionDetail } from '../models/sessions.js'
export async function sessionListController(req, res) {
const { nextKey } = req.query
const { nextKey, order } = req.query
const itemsPerPage = 50
try {
// const totalSessions = await sessionCount()
// const maxPages = Math.ceil(totalSessions / itemsPerPage)
const sessions = await sessionList(new Desc(itemsPerPage, nextKey))
const sessions = await sessionList(
new Pagination(order, itemsPerPage, nextKey)
)
const newNextKey = sessions[sessions.length - 1]?._id
res.render('sessions', { sessions, nextKey: newNextKey })
+3 -3
View File
@@ -1,12 +1,12 @@
import { Desc } from '../models/pagination.js'
import Pagination from '../models/pagination.js'
import { userList } from '../models/users.js'
export async function userListController(req, res) {
const { nextKey } = req.query
const { nextKey, order } = req.query
const itemsPerPage = 50
try {
const users = await userList(new Desc(itemsPerPage, nextKey))
const users = await userList(new Pagination(order, itemsPerPage, nextKey))
const newNextKey = users[users.length - 1]?._id
res.render('users', { users, nextKey: newNextKey })
+2 -2
View File
@@ -3,7 +3,7 @@ import { Command } from '@linux-odyssey/models'
// eslint-disable-next-line import/prefer-default-export
export async function errorCommands(pagination) {
const commands = await Command.aggregate([
pagination.matchStage('_id'),
pagination.match('_id'),
{
$match: {
$and: [
@@ -31,7 +31,7 @@ export async function errorCommands(pagination) {
},
},
{ $unwind: '$session.user' },
pagination.order('_id'),
pagination.sort('_id'),
pagination.limit(),
])
+44 -24
View File
@@ -3,40 +3,60 @@
// eslint-disable-next-line max-classes-per-file
import mongoose from 'mongoose'
class Pagination {
export const DESC = 'desc'
export const ASC = 'asc'
class Asc {
getOperator() {
return '$gt'
}
getOrder() {
return 1
}
}
class Desc {
getOperator() {
return '$lt'
}
getOrder() {
return -1
}
}
export default class Pagination {
nextKey = null
itemsPerPage = 50
order = null
constructor(itemsPerPage = 50, nextKey = null) {
constructor(order, itemsPerPage = 50, nextKey = null) {
this.itemsPerPage = itemsPerPage
if (!order || order === DESC) {
this.order = new Desc()
} else if (order === ASC) {
this.order = new Asc()
} else {
throw new Error('order must be asc or desc')
}
if (nextKey) {
this.nextKey = new mongoose.Types.ObjectId(nextKey)
}
}
match(field) {
const stage = this.nextKey
? { [field]: { [this.order.getOperator()]: this.nextKey } }
: {}
return { $match: stage }
}
sort(field) {
return { $sort: { [field]: this.order.getOrder() } }
}
limit() {
return { $limit: this.itemsPerPage }
}
}
export class Asc extends Pagination {
matchStage(field) {
const stage = this.nextKey ? { [field]: { $gt: this.nextKey } } : {}
return { $match: stage }
}
order(field) {
return { $sort: { [field]: 1 } }
}
}
export class Desc extends Pagination {
matchStage(field) {
const stage = this.nextKey ? { [field]: { $lt: this.nextKey } } : {}
return { $match: stage }
}
order(field) {
return { $sort: { [field]: -1 } }
}
}
+2 -2
View File
@@ -32,7 +32,7 @@ function formatTime(time) {
export async function sessionList(pagination) {
const sessions = await Session.aggregate([
pagination.matchStage('_id'),
pagination.match('_id'),
{
$lookup: {
from: 'users',
@@ -50,7 +50,7 @@ export async function sessionList(pagination) {
as: 'commands',
},
},
pagination.order('_id'),
pagination.sort('_id'),
pagination.limit(),
])
+2 -2
View File
@@ -14,7 +14,7 @@ export function userCount() {
export async function userList(pagination) {
const users = await Session.aggregate([
pagination.matchStage('user'),
pagination.match('user'),
{
$group: {
_id: '$user',
@@ -31,7 +31,7 @@ export async function userList(pagination) {
},
},
{ $unwind: '$userData' },
pagination.order('userData._id'),
pagination.sort('userData._id'),
pagination.limit(),
])
+21 -11
View File
@@ -1,32 +1,42 @@
import mongoose from 'mongoose'
import { Desc } from '../src/models/pagination.js'
import Pagination, { ASC, DESC } from '../src/models/pagination.js'
describe('Pagination', () => {
it('should return correct limit', async () => {
const pagination = new Desc(10)
it('should failed when not provide order', () => {
expect(() => new Pagination()).toThrow('order must be asc or desc')
})
it('should return correct limit', () => {
const pagination = new Pagination(DESC, 10)
expect(pagination.limit()).toMatchObject({ $limit: 10 })
})
it('should return correct order', async () => {
const pagination = new Desc(10)
it('desc should return correct order', async () => {
const pagination = new Pagination(DESC, 10)
expect(pagination.order('_id')).toMatchObject({ $sort: { _id: -1 } })
expect(pagination.order('time')).toMatchObject({ $sort: { time: -1 } })
expect(pagination.sort('_id')).toMatchObject({ $sort: { _id: -1 } })
expect(pagination.sort('time')).toMatchObject({ $sort: { time: -1 } })
})
it('asc should return correct order', async () => {
const pagination = new Pagination(ASC, 10)
expect(pagination.sort('_id')).toMatchObject({ $sort: { _id: 1 } })
expect(pagination.sort('time')).toMatchObject({ $sort: { time: 1 } })
})
it('should return correct match stage for empty nextKey', async () => {
const pagination = new Desc(10)
const pagination = new Pagination(DESC, 10)
expect(pagination.matchStage('_id')).toMatchObject({ $match: {} })
expect(pagination.match('_id')).toMatchObject({ $match: {} })
})
it('should return correct match stage for empty nextKey', async () => {
const nextKeyStr = '656c7fea28a4c087bfcefe12'
const pagination = new Desc(10, nextKeyStr)
const pagination = new Pagination(DESC, 10, nextKeyStr)
const nextKey = new mongoose.Types.ObjectId(nextKeyStr)
expect(pagination.matchStage('_id')).toMatchObject({
expect(pagination.match('_id')).toMatchObject({
$match: {
_id: {
$lt: nextKey,