refactor: add Pagination class

This commit is contained in:
Chen, Tai-Lin committed 2023-12-21 17:09:20 +08:00
1 parent 19cd10ab7b
commit 68db16419d
9 files changed
+99 -89

No files matched your search

-23
View File
@@ -1,23 +0,0 @@
/* eslint-disable class-methods-use-this */
// eslint-disable-next-line max-classes-per-file
class Order {}
export class Asc extends Order {
matchStage(nextKey) {
return { $gt: nextKey }
}
order() {
return 1
}
}
export class Desc extends Order {
matchStage(nextKey) {
return { $lt: nextKey }
}
order() {
return -1
}
}
+2 -19
View File
@@ -1,6 +1,5 @@
/* eslint-disable object-shorthand */
import { Desc } from '../constants.js'
import { Command } from '@linux-odyssey/models'
import { Desc } from '../models/pagination.js'
import { errorCommands } from '../models/commands.js'
// eslint-disable-next-line import/prefer-default-export
@@ -9,23 +8,7 @@ export async function commandListController(req, res) {
const itemsPerPage = 100
try {
// const totalCommands = await Command.countDocuments({
// $and: [
// { error: { $exists: true } },
// { error: { $ne: null } },
// { error: { $ne: '' } },
// ],
// })
// const maxPages = Math.ceil(totalCommands / itemsPerPage)
// const pageNumber = req.query
const payload = await errorCommands({
nextKey,
itemsPerPage,
order: new Desc(),
})
const payload = await errorCommands(new Desc(itemsPerPage, nextKey))
const newNextKey = payload[payload.length - 1]?._id
res.render('commands', { errorCommands: payload, nextKey: newNextKey })
@@ -1,5 +1,5 @@
import { Desc } from '../constants.js'
import { sessionCount, sessionList, sessionDetail } from '../models/sessions.js'
import { Desc } from '../models/pagination.js'
import { sessionList, sessionDetail } from '../models/sessions.js'
export async function sessionListController(req, res) {
const { nextKey } = req.query
@@ -9,11 +9,7 @@ export async function sessionListController(req, res) {
// const totalSessions = await sessionCount()
// const maxPages = Math.ceil(totalSessions / itemsPerPage)
const sessions = await sessionList({
nextKey,
itemsPerPage,
order: new Desc(),
})
const sessions = await sessionList(new Desc(itemsPerPage, nextKey))
const newNextKey = sessions[sessions.length - 1]?._id
res.render('sessions', { sessions, nextKey: newNextKey })
+3 -7
View File
@@ -1,16 +1,12 @@
import { Desc } from '../constants.js'
import { userList, userCount } from '../models/users.js'
import { Desc } from '../models/pagination.js'
import { userList } from '../models/users.js'
export async function userListController(req, res) {
const { nextKey } = req.query
const itemsPerPage = 50
try {
const users = await userList({
nextKey,
itemsPerPage,
order: new Desc(),
})
const users = await userList(new Desc(itemsPerPage, nextKey))
const newNextKey = users[users.length - 1]?._id
res.render('users', { users, nextKey: newNextKey })
+4 -11
View File
@@ -1,16 +1,9 @@
import mongoose from 'mongoose'
import { Command } from '@linux-odyssey/models'
// eslint-disable-next-line import/prefer-default-export
export async function errorCommands({ nextKey, itemsPerPage, order }) {
let matchStage = {}
if (nextKey) {
const key = new mongoose.Types.ObjectId(nextKey)
matchStage = { _id: order.matchStage(key) }
}
console.log(matchStage, itemsPerPage, nextKey, order)
export async function errorCommands(pagination) {
const commands = await Command.aggregate([
{ $match: matchStage },
pagination.matchStage('_id'),
{
$match: {
$and: [
@@ -38,8 +31,8 @@ export async function errorCommands({ nextKey, itemsPerPage, order }) {
},
},
{ $unwind: '$session.user' },
{ $sort: { _id: order.order() } },
{ $limit: itemsPerPage },
pagination.order('_id'),
pagination.limit(),
])
return commands.map(({ _id, command, error, createdAt, session }) => {
@@ -0,0 +1,42 @@
/* eslint-disable lines-between-class-members */
/* eslint-disable class-methods-use-this */
// eslint-disable-next-line max-classes-per-file
import mongoose from 'mongoose'
class Pagination {
nextKey = null
itemsPerPage = 50
constructor(itemsPerPage = 50, nextKey = null) {
this.itemsPerPage = itemsPerPage
if (nextKey) {
this.nextKey = new mongoose.Types.ObjectId(nextKey)
}
}
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 } }
}
}
+4 -12
View File
@@ -1,4 +1,3 @@
import mongoose from 'mongoose'
import { Command, Session } from '@linux-odyssey/models'
export function sessionCount() {
@@ -31,16 +30,9 @@ function formatTime(time) {
return `${hours}h ${minutes % 60}m ${seconds % 60}s`
}
export async function sessionList({ nextKey, itemsPerPage, order }) {
let matchStage = {}
if (nextKey) {
const key = new mongoose.Types.ObjectId(nextKey)
matchStage = { _id: order.matchStage(key) }
}
export async function sessionList(pagination) {
const sessions = await Session.aggregate([
{
$match: matchStage,
},
pagination.matchStage('_id'),
{
$lookup: {
from: 'users',
@@ -58,8 +50,8 @@ export async function sessionList({ nextKey, itemsPerPage, order }) {
as: 'commands',
},
},
{ $sort: { _id: order.order() } },
{ $limit: itemsPerPage },
pagination.order('_id'),
pagination.limit(),
])
return sessions.map(
+4 -10
View File
@@ -12,15 +12,9 @@ export function userCount() {
return User.find().count()
}
export async function userList({ nextKey, itemsPerPage, order }) {
let matchStage = {}
if (nextKey) {
const key = new mongoose.Types.ObjectId(nextKey)
matchStage = { user: order.matchStage(key) }
}
console.log(matchStage)
export async function userList(pagination) {
const users = await Session.aggregate([
{ $match: matchStage },
pagination.matchStage('user'),
{
$group: {
_id: '$user',
@@ -37,8 +31,8 @@ export async function userList({ nextKey, itemsPerPage, order }) {
},
},
{ $unwind: '$userData' },
{ $sort: { 'userData._id': order.order() } },
{ $limit: itemsPerPage },
pagination.order('userData._id'),
pagination.limit(),
])
return users.map(({ userData, count, lastActivityAt }) => {
@@ -0,0 +1,37 @@
import mongoose from 'mongoose'
import { Desc } from '../src/models/pagination.js'
describe('Pagination', () => {
it('should return correct limit', async () => {
const pagination = new Desc(10)
expect(pagination.limit()).toMatchObject({ $limit: 10 })
})
it('should return correct order', async () => {
const pagination = new Desc(10)
expect(pagination.order('_id')).toMatchObject({ $sort: { _id: -1 } })
expect(pagination.order('time')).toMatchObject({ $sort: { time: -1 } })
})
it('should return correct match stage for empty nextKey', async () => {
const pagination = new Desc(10)
expect(pagination.matchStage('_id')).toMatchObject({ $match: {} })
})
it('should return correct match stage for empty nextKey', async () => {
const nextKeyStr = '656c7fea28a4c087bfcefe12'
const pagination = new Desc(10, nextKeyStr)
const nextKey = new mongoose.Types.ObjectId(nextKeyStr)
expect(pagination.matchStage('_id')).toMatchObject({
$match: {
_id: {
$lt: nextKey,
},
},
})
})
})