diff --git a/api/models/Conversation.js b/api/models/Conversation.js
index 7d59113b90..4403c1e6ab 100644
--- a/api/models/Conversation.js
+++ b/api/models/Conversation.js
@@ -145,10 +145,11 @@ module.exports = {
const promises = convoIds.map(convo => {
return Conversation.findOne({ user, conversationId: convo.conversationId}).exec();
});
- const results = await Promise.all(promises);
+ const results = (await Promise.all(promises)).filter(convo => convo);
const startIndex = (pageNumber - 1) * pageSize;
const convos = results.slice(startIndex, startIndex + pageSize);
const totalPages = Math.ceil(results.length / pageSize);
+ console.log(results.length, totalPages, convos.length);
return { conversations: convos, pages: totalPages, pageNumber, pageSize };
} catch (error) {
console.log(error);
diff --git a/api/server/routes/search.js b/api/server/routes/search.js
index 511a97881a..d58c62919f 100644
--- a/api/server/routes/search.js
+++ b/api/server/routes/search.js
@@ -2,7 +2,7 @@ const express = require('express');
const router = express.Router();
const { Message } = require('../../models/Message');
const { Conversation, getConvosQueried } = require('../../models/Conversation');
-const {reduceMessages, reduceHits} = require('../../lib/utils/reduceHits');
+const { reduceMessages, reduceHits } = require('../../lib/utils/reduceHits');
// const { MeiliSearch } = require('meilisearch');
router.get('/sync', async function (req, res) {
@@ -12,19 +12,24 @@ router.get('/sync', async function (req, res) {
});
router.get('/', async function (req, res) {
- const { q } = req.query;
- console.log(req.query);
- const pageNumber = req.query.pageNumber || 1;
- // const message = await Message.meiliSearch(q, { attributesToHighlight: ['text', 'sender'] });
- const message = await Message.meiliSearch(q);
- const title = await Conversation.meiliSearch(q, { attributesToHighlight: ['title'] });
- // console.log('titles', title);
- // console.log(sortedHits);
- const sortedHits = reduceHits(message.hits, title.hits);
- const result = await getConvosQueried(req?.session?.user?.username, sortedHits, pageNumber);
- // const sortedHits = reduceMessages(message.hits);
- // res.status(200).send(sortedHits || result);
- res.status(200).send(result);
+ try {
+ const { q } = req.query;
+ console.log(req.query, req.params);
+ const pageNumber = req.query.pageNumber || 1;
+ const message = await Message.meiliSearch(q);
+ const title = await Conversation.meiliSearch(q, { attributesToHighlight: ['title'] });
+ const sortedHits = reduceHits(message.hits, title.hits);
+ const result = await getConvosQueried(
+ req?.session?.user?.username,
+ sortedHits,
+ pageNumber
+ );
+ console.log('result', result.pageNumber, result.pages, result.pageSize);
+ res.status(200).send(result);
+ } catch (error) {
+ console.log(error);
+ res.status(500).send({ message: 'Error searching' });
+ }
});
router.get('/clear', async function (req, res) {
diff --git a/client/src/components/Conversations/Pages.jsx b/client/src/components/Conversations/Pages.jsx
new file mode 100644
index 0000000000..1001ee8362
--- /dev/null
+++ b/client/src/components/Conversations/Pages.jsx
@@ -0,0 +1,36 @@
+import React from 'react';
+
+export default function Pages({ pageNumber, pages, nextPage, previousPage }) {
+ const clickHandler = (func) => async (e) => {
+ e.preventDefault();
+ await func();
+ };
+
+ return (
+
+
+
+ {pageNumber} / {pages}
+
+
+
+ );
+}
diff --git a/client/src/components/Conversations/index.jsx b/client/src/components/Conversations/index.jsx
index 4142cb8ed1..eaa59b0097 100644
--- a/client/src/components/Conversations/index.jsx
+++ b/client/src/components/Conversations/index.jsx
@@ -1,11 +1,7 @@
import React from 'react';
import Conversation from './Conversation';
-export default function Conversations({ conversations, conversationId, pageNumber, pages, nextPage, previousPage, moveToTop }) {
- const clickHandler = (func) => async (e) => {
- e.preventDefault();
- await func();
- };
+export default function Conversations({ conversations, conversationId, moveToTop }) {
return (
<>
@@ -37,25 +33,6 @@ export default function Conversations({ conversations, conversationId, pageNumbe
/>
);
})}
-
-
-
- {pageNumber} / {pages}
-
-
-
>
);
}
diff --git a/client/src/components/Nav/NavLinks.jsx b/client/src/components/Nav/NavLinks.jsx
index 72cd44ce35..97e90ca881 100644
--- a/client/src/components/Nav/NavLinks.jsx
+++ b/client/src/components/Nav/NavLinks.jsx
@@ -6,10 +6,10 @@ import ClearConvos from './ClearConvos';
import DarkMode from './DarkMode';
import Logout from './Logout';
-export default function NavLinks() {
+export default function NavLinks({ onSearchSuccess, clearSearch }) {
return (
<>
-
+
diff --git a/client/src/components/Nav/SearchBar.jsx b/client/src/components/Nav/SearchBar.jsx
index 16778d22ac..ae556c7dd6 100644
--- a/client/src/components/Nav/SearchBar.jsx
+++ b/client/src/components/Nav/SearchBar.jsx
@@ -1,18 +1,34 @@
import React, { useState, useCallback } from 'react';
import { debounce } from 'lodash';
-import { useDispatch, useSelector } from 'react-redux';
+import { useDispatch } from 'react-redux';
import { Search } from 'lucide-react';
import { setQuery } from '~/store/searchSlice';
-import { setPage, refreshConversation } from '~/store/convoSlice';
+import { setConvos, refreshConversation } from '~/store/convoSlice';
+import axios from 'axios';
-export default function SearchBar() {
+const fetch = async (q, pageNumber, callback) => {
+ const { data } = await axios.get(`/api/search?q=${q}&pageNumber=${pageNumber}`);
+ console.log(data);
+ callback(data);
+};
+
+export default function SearchBar({ onSuccess, clearSearch }) {
const dispatch = useDispatch();
const [inputValue, setInputValue] = useState('');
- const { search } = useSelector((state) => state.search);
+
+ // const onSuccess = (data) => {
+ // const { conversations, pages, pageNumber } = data;
+ // dispatch(setConvos({ convos: conversations, searchFetch: true }));
+ // dispatch(setPage(pageNumber));
+ // dispatch(setPages(pages));
+ // };
const debouncedChangeHandler = useCallback(
debounce((q) => {
dispatch(setQuery(q));
+ if (q.length > 0) {
+ fetch(q, 1, onSuccess);
+ }
}, 750),
[dispatch]
);
@@ -22,27 +38,27 @@ export default function SearchBar() {
if (e.keyCode === 8 && value === '') {
// Value after clearing input: ""
console.log(`Value after clearing input: "${value}"`);
- dispatch(setPage(1));
dispatch(setQuery(''));
- dispatch(refreshConversation());
+ clearSearch();
}
};
const changeHandler = (e) => {
- if (!search) {
- console.log('setting page to 1');
- dispatch(setPage(1));
- }
+ // if (!search) {
+ // console.log('setting page to 1');
+ // dispatch(setPage(1));
+ // }
let q = e.target.value;
setInputValue(q);
q = q.trim();
- if (q === '' || !q) {
- dispatch(setPage(1));
+ if (q === '') {
dispatch(setQuery(''));
- dispatch(refreshConversation());
+ // dispatch(setPage(1));
+ // dispatch(refreshConversation());
+ clearSearch();
} else {
debouncedChangeHandler(q);
}
diff --git a/client/src/components/Nav/index.jsx b/client/src/components/Nav/index.jsx
index 0b6e8e5c49..4903ed8a73 100644
--- a/client/src/components/Nav/index.jsx
+++ b/client/src/components/Nav/index.jsx
@@ -1,36 +1,63 @@
import React, { useState, useEffect, useRef } from 'react';
+import axios from 'axios';
+import _ from 'lodash';
import NewChat from './NewChat';
import Spinner from '../svg/Spinner';
+import Pages from '../Conversations/Pages';
import Conversations from '../Conversations';
import NavLinks from './NavLinks';
import { swr } from '~/utils/fetchers';
import { useDispatch, useSelector } from 'react-redux';
-import { increasePage, decreasePage, setPage, setConvos, setPages } from '~/store/convoSlice';
+import { setConvos, refreshConversation } from '~/store/convoSlice';
+
+const fetch = async (q, pageNumber, callback) => {
+ const { data } = await axios.get(`/api/search?q=${q}&pageNumber=${pageNumber}`);
+ console.log(data);
+ callback(data);
+};
export default function Nav({ navVisible, setNavVisible }) {
const dispatch = useDispatch();
const [isHovering, setIsHovering] = useState(false);
+ const [pages, setPages] = useState(1);
+ const [pageNumber, setPage] = useState(1);
const { search, query } = useSelector((state) => state.search);
- const { conversationId, convos, pages, pageNumber, refreshConvoHint } = useSelector(
- (state) => state.convo
- );
- const onSuccess = (data) => {
- const { conversations, pages } = data;
+ const { conversationId, convos, refreshConvoHint } = useSelector((state) => state.convo);
+ const onSuccess = (data, searchFetch = false) => {
+ if (search) {
+ return;
+ }
+ const { conversations, pages } = data;
if (pageNumber > pages) {
- dispatch(setPage(pages));
+ setPage(pages);
} else {
- dispatch(setConvos(conversations));
- dispatch(setPages(pages));
+ dispatch(setConvos({ convos: conversations, searchFetch }));
+ setPages(pages);
}
};
- const { data, isLoading, mutate } = swr(`/api/${search ? `search?q=${query}&pageNumber=${pageNumber}` : `convos?pageNumber=${pageNumber}`}`, onSuccess, {
+ const onSearchSuccess = (data, expectedPage) => {
+ const res = data;
+ dispatch(setConvos({ convos: res.conversations, searchFetch: true }));
+ if (expectedPage) {
+ setPage(expectedPage);
+ }
+ setPage(res.pageNumber);
+ setPages(res.pages);
+ };
+
+ const clearSearch = () => {
+ setPage(1);
+ dispatch(refreshConversation());
+ };
+
+ const { data, isLoading, mutate } = swr(`/api/convos?pageNumber=${pageNumber}`, onSuccess, {
revalidateOnMount: false,
- revalidateIfStale: !search,
- revalidateOnFocus: !search,
- revalidateOnReconnect: !search,
- populateCache: !search,
+ // populateCache: false,
+ // revalidateIfStale: false,
+ // revalidateOnFocus: false,
+ // revalidateOnReconnect : false,
});
const containerRef = useRef(null);
@@ -46,19 +73,29 @@ export default function Nav({ navVisible, setNavVisible }) {
const nextPage = async () => {
moveToTop();
- dispatch(increasePage());
- await mutate();
+ if (!search) {
+ setPage((prev) => prev + 1);
+ await mutate();
+ } else {
+ await fetch(query, +pageNumber + 1, _.partialRight(onSearchSuccess, +pageNumber + 1));
+ }
};
const previousPage = async () => {
moveToTop();
- dispatch(decreasePage());
- await mutate();
+ if (!search) {
+ setPage((prev) => prev - 1);
+ await mutate();
+ } else {
+ await fetch(query, +pageNumber - 1, _.partialRight(onSearchSuccess, +pageNumber - 1));
+ }
};
useEffect(() => {
- mutate();
+ if (!search) {
+ mutate();
+ }
}, [pageNumber, conversationId, refreshConvoHint]);
useEffect(() => {
@@ -114,16 +151,21 @@ export default function Nav({ navVisible, setNavVisible }) {
)}
+
-
+
diff --git a/client/src/store/convoSlice.js b/client/src/store/convoSlice.js
index 3b02bcc31a..2d84e05b38 100644
--- a/client/src/store/convoSlice.js
+++ b/client/src/store/convoSlice.js
@@ -17,7 +17,7 @@ const initialState = {
refreshConvoHint: 0,
search: false,
latestMessage: null,
- convos: [],
+ convos: []
};
const currentSlice = createSlice({
@@ -57,9 +57,12 @@ const currentSlice = createSlice({
state.latestMessage = null;
},
setConvos: (state, action) => {
- state.convos = action.payload.sort(
- (a, b) => new Date(b.createdAt) - new Date(a.createdAt)
- );
+ const { convos, searchFetch } = action.payload;
+ if (searchFetch) {
+ state.convos = convos;
+ } else {
+ state.convos = convos.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
+ }
},
setPages: (state, action) => {
state.pages = action.payload;
@@ -72,11 +75,23 @@ const currentSlice = createSlice({
},
setLatestMessage: (state, action) => {
state.latestMessage = action.payload;
- },
+ }
}
});
-export const { refreshConversation, setConversation, setPages, setConvos, setNewConvo, setError, increasePage, decreasePage, setPage, removeConvo, removeAll, setLatestMessage } =
- currentSlice.actions;
+export const {
+ refreshConversation,
+ setConversation,
+ setPages,
+ setConvos,
+ setNewConvo,
+ setError,
+ increasePage,
+ decreasePage,
+ setPage,
+ removeConvo,
+ removeAll,
+ setLatestMessage
+} = currentSlice.actions;
export default currentSlice.reducer;
diff --git a/client/src/store/searchSlice.js b/client/src/store/searchSlice.js
index 2c39b3654f..3769af3af6 100644
--- a/client/src/store/searchSlice.js
+++ b/client/src/store/searchSlice.js
@@ -16,9 +16,9 @@ const currentSlice = createSlice({
const q = action.payload;
state.query = q;
- if (!q || q === '') {
+ if (q === '') {
state.search = false;
- } else {
+ } else if (q?.length > 0 && !state.search) {
state.search = true;
}
},
diff --git a/client/src/utils/fetchers.js b/client/src/utils/fetchers.js
index 3d9a83413e..abe8f4a9a6 100644
--- a/client/src/utils/fetchers.js
+++ b/client/src/utils/fetchers.js
@@ -3,21 +3,25 @@ import axios from 'axios';
import useSWR from 'swr';
import useSWRMutation from 'swr/mutation';
-const fetcher = (url) => fetch(url, {credentials: 'include'}).then((res) => res.json());
+const fetcher = (url) => fetch(url, { credentials: 'include' }).then((res) => res.json());
+const axiosFetcher = async (url, params) => {
+ console.log(params, 'params');
+ return axios.get(url, params);
+};
const postRequest = async (url, { arg }) => {
return await axios.post(url, { withCredentials: true, arg });
};
export const swr = (path, successCallback, options) => {
- const _options = {...options};
+ const _options = { ...options };
if (successCallback) {
_options.onSuccess = successCallback;
}
return useSWR(path, fetcher, _options);
-}
+};
export default function manualSWR(path, type, successCallback) {
const options = {};
@@ -28,3 +32,16 @@ export default function manualSWR(path, type, successCallback) {
const fetchFunction = type === 'get' ? fetcher : postRequest;
return useSWRMutation(path, fetchFunction, options);
}
+
+export function useManualSWR({ path, params, type, onSuccess }) {
+ const options = {};
+
+ if (onSuccess) {
+ options.onSuccess = onSuccess;
+ }
+
+ console.log(params, 'params');
+
+ const fetchFunction = type === 'get' ? _.partialRight(axiosFetcher, params) : postRequest;
+ return useSWRMutation(path, fetchFunction, options);
+}