From 8289558d94b613ff58645dc74ca5f85b333979c9 Mon Sep 17 00:00:00 2001
From: Wentao Lyu <35-wentao.lyu@users.noreply.git.stereye.tech>
Date: Wed, 15 Mar 2023 04:05:14 +0800
Subject: [PATCH] feat: pagination in nav
---
api/models/Conversation.js | 14 +++----
api/server/routes/convos.js | 4 +-
client/src/components/Conversations/index.jsx | 35 ++++++++++------
client/src/components/Nav/MobileNav.jsx | 6 +--
client/src/components/Nav/index.jsx | 41 ++++++++++++++-----
client/src/store/convoSlice.js | 19 ++++++---
client/src/style.css | 3 ++
client/src/utils/fetchers.js | 8 ++--
8 files changed, 84 insertions(+), 46 deletions(-)
diff --git a/api/models/Conversation.js b/api/models/Conversation.js
index a32bc3e7a4..6e3c646c64 100644
--- a/api/models/Conversation.js
+++ b/api/models/Conversation.js
@@ -91,19 +91,17 @@ module.exports = {
}
},
// getConvos: async () => await Conversation.find({}).sort({ createdAt: -1 }).exec(),
- getConvos: async (pageNumber = 1, pageSize = 12) => {
+ getConvosByPage: async (pageNumber = 1, pageSize = 12) => {
try {
- const skip = (pageNumber - 1) * pageSize;
- // const limit = pageNumber * pageSize;
-
- const conversations = await Conversation.find({})
+ const totalConvos = await Conversation.countDocuments();
+ const totalPages = Math.ceil(totalConvos / pageSize);
+ const convos = await Conversation.find()
.sort({ createdAt: -1 })
- .skip(skip)
- // .limit(limit)
+ .skip((pageNumber - 1) * pageSize)
.limit(pageSize)
.exec();
- return conversations;
+ return { conversations: convos, pages: totalPages, pageNumber, pageSize };
} catch (error) {
console.log(error);
return { message: 'Error getting conversations' };
diff --git a/api/server/routes/convos.js b/api/server/routes/convos.js
index bfe3bc2d56..9a5f71cee3 100644
--- a/api/server/routes/convos.js
+++ b/api/server/routes/convos.js
@@ -2,12 +2,12 @@ const express = require('express');
const router = express.Router();
const { titleConvo } = require('../../app/');
const { getConvo, saveConvo, getConvoTitle } = require('../../models');
-const { getConvos, deleteConvos, updateConvo } = require('../../models/Conversation');
+const { getConvosByPage, deleteConvos, updateConvo } = require('../../models/Conversation');
const { getMessages } = require('../../models/Message');
router.get('/', async (req, res) => {
const pageNumber = req.query.pageNumber || 1;
- res.status(200).send(await getConvos(pageNumber));
+ res.status(200).send(await getConvosByPage(pageNumber));
});
router.post('/gen_title', async (req, res) => {
diff --git a/client/src/components/Conversations/index.jsx b/client/src/components/Conversations/index.jsx
index d3ab1ffd0b..4142cb8ed1 100644
--- a/client/src/components/Conversations/index.jsx
+++ b/client/src/components/Conversations/index.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import Conversation from './Conversation';
-export default function Conversations({ conversations, conversationId, showMore }) {
- const clickHandler = async (e) => {
+export default function Conversations({ conversations, conversationId, pageNumber, pages, nextPage, previousPage, moveToTop }) {
+ const clickHandler = (func) => async (e) => {
e.preventDefault();
- await showMore();
+ await func();
};
return (
@@ -33,18 +33,29 @@ export default function Conversations({ conversations, conversationId, showMore
chatGptLabel={convo.chatGptLabel}
promptPrefix={convo.promptPrefix}
bingData={bingData}
- retainView={showMore.bind(null, false)}
+ retainView={moveToTop}
/>
);
})}
- {conversations?.length >= 12 && (
-
- )}
+
+
+
+ {pageNumber} / {pages}
+
+
+
>
);
}
diff --git a/client/src/components/Nav/MobileNav.jsx b/client/src/components/Nav/MobileNav.jsx
index e4107e9ac6..0c846524fc 100644
--- a/client/src/components/Nav/MobileNav.jsx
+++ b/client/src/components/Nav/MobileNav.jsx
@@ -7,7 +7,7 @@ import { setText } from '~/store/textSlice';
export default function MobileNav({ setNavVisible }) {
const dispatch = useDispatch();
- const { conversationId, convos } = useSelector((state) => state.convo);
+ const { conversationId, convos, title } = useSelector((state) => state.convo);
const toggleNavVisible = () => {
setNavVisible((prev) => {
@@ -22,8 +22,6 @@ export default function MobileNav({ setNavVisible }) {
dispatch(setSubmission({}));
}
- const title = convos?.find(element => element?.conversationId == conversationId)?.title || 'New Chat';
-
return (
-
{title}
+ {title || 'New Chat'}
diff --git a/client/src/store/convoSlice.js b/client/src/store/convoSlice.js
index 258de84e70..c862a8e1e7 100644
--- a/client/src/store/convoSlice.js
+++ b/client/src/store/convoSlice.js
@@ -13,8 +13,9 @@ const initialState = {
promptPrefix: null,
convosLoading: false,
pageNumber: 1,
+ pages: 1,
refreshConvoHint: 0,
- convos: []
+ convos: [],
};
const currentSlice = createSlice({
@@ -30,12 +31,18 @@ const currentSlice = createSlice({
setError: (state, action) => {
state.error = action.payload;
},
- incrementPage: (state) => {
+ increasePage: (state) => {
state.pageNumber = state.pageNumber + 1;
},
+ decreasePage: (state) => {
+ state.pageNumber = state.pageNumber - 1;
+ },
+ setPage: (state, action) => {
+ state.pageNumber = action.payload;
+ },
setNewConvo: (state) => {
state.error = false;
- state.title = 'New Chat';
+ state.title = 'ChatGPT Clone';
state.conversationId = null;
state.parentMessageId = null;
state.jailbreakConversationId = null;
@@ -45,13 +52,15 @@ const currentSlice = createSlice({
state.chatGptLabel = null;
state.promptPrefix = null;
state.convosLoading = false;
- state.pageNumber = 1;
},
setConvos: (state, action) => {
state.convos = action.payload.sort(
(a, b) => new Date(b.createdAt) - new Date(a.createdAt)
);
},
+ setPages: (state, action) => {
+ state.pages = action.payload;
+ },
removeConvo: (state, action) => {
state.convos = state.convos.filter((convo) => convo.conversationId !== action.payload);
},
@@ -61,7 +70,7 @@ const currentSlice = createSlice({
}
});
-export const { refreshConversation, setConversation, setConvos, setNewConvo, setError, incrementPage, removeConvo, removeAll } =
+export const { refreshConversation, setConversation, setPages, setConvos, setNewConvo, setError, increasePage, decreasePage, setPage, removeConvo, removeAll } =
currentSlice.actions;
export default currentSlice.reducer;
diff --git a/client/src/style.css b/client/src/style.css
index 6b17c388e2..c4a03408b7 100644
--- a/client/src/style.css
+++ b/client/src/style.css
@@ -1876,3 +1876,6 @@ button.scroll-convo {
background-color:hsla(0,0%,100%,.4)
}
}
+.hidden-visibility {
+ visibility: hidden;
+}
\ No newline at end of file
diff --git a/client/src/utils/fetchers.js b/client/src/utils/fetchers.js
index 9faa211d4e..d9cfa54116 100644
--- a/client/src/utils/fetchers.js
+++ b/client/src/utils/fetchers.js
@@ -9,14 +9,14 @@ const postRequest = async (url, { arg }) => {
return await axios.post(url, { arg });
};
-export const swr = (path, successCallback) => {
- const options = {};
+export const swr = (path, successCallback, options) => {
+ const _options = {...options};
if (successCallback) {
- options.onSuccess = successCallback;
+ _options.onSuccess = successCallback;
}
- return useSWR(path, fetcher, options);
+ return useSWR(path, fetcher, _options);
}
export default function manualSWR(path, type, successCallback) {