diff --git a/api/lib/db/mongoMeili.js b/api/lib/db/mongoMeili.js index 5890f3ed20..c603568e1a 100644 --- a/api/lib/db/mongoMeili.js +++ b/api/lib/db/mongoMeili.js @@ -85,12 +85,6 @@ const createMeiliMongooseModel = function ({ index, indexName, client, attribute // Push new document to Meili async addObjectToMeili() { const object = _.pick(this.toJSON(), attributesToIndex); - // const title = (await this.getTitle()) || 'New Chat'; // Get title value - // const objectWithTitle = { - // ...this.toJSON(), - // title - // }; - // const object = _.pick(objectWithTitle, attributesToIndex); // Pick desired attributes try { // console.log('Adding document to Meili', object); diff --git a/api/models/Conversation.js b/api/models/Conversation.js index 81d3646d98..7d59113b90 100644 --- a/api/models/Conversation.js +++ b/api/models/Conversation.js @@ -136,6 +136,25 @@ module.exports = { return { message: 'Error getting conversations' }; } }, + getConvosQueried: async (user, convoIds, pageNumber = 1, pageSize = 12) => { + try { + if (!convoIds || convoIds.length === 0) { + return { conversations: [], pages: 1, pageNumber, pageSize }; + } + + const promises = convoIds.map(convo => { + return Conversation.findOne({ user, conversationId: convo.conversationId}).exec(); + }); + const results = await Promise.all(promises); + const startIndex = (pageNumber - 1) * pageSize; + const convos = results.slice(startIndex, startIndex + pageSize); + const totalPages = Math.ceil(results.length / pageSize); + return { conversations: convos, pages: totalPages, pageNumber, pageSize }; + } catch (error) { + console.log(error); + return { message: 'Error fetching conversations' }; + } + }, getConvo, getConvoTitle: async (user, conversationId) => { try { diff --git a/api/server/routes/search.js b/api/server/routes/search.js index 4b92f18c70..511a97881a 100644 --- a/api/server/routes/search.js +++ b/api/server/routes/search.js @@ -1,7 +1,7 @@ const express = require('express'); const router = express.Router(); const { Message } = require('../../models/Message'); -const { Conversation } = require('../../models/Conversation'); +const { Conversation, getConvosQueried } = require('../../models/Conversation'); const {reduceMessages, reduceHits} = require('../../lib/utils/reduceHits'); // const { MeiliSearch } = require('meilisearch'); @@ -13,13 +13,18 @@ router.get('/sync', async function (req, res) { router.get('/', async function (req, res) { const { q } = req.query; - const message = await Message.meiliSearch(q, { attributesToHighlight: ['text', 'sender'] }); + 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}); + // res.status(200).send(sortedHits || result); + res.status(200).send(result); }); router.get('/clear', async function (req, res) { diff --git a/client/package-lock.json b/client/package-lock.json index d5e3024751..3fce5568f9 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -20,6 +20,7 @@ "clsx": "^1.2.1", "crypto-browserify": "^3.12.0", "highlight.js": "^11.7.0", + "lodash": "^4.17.21", "lucide-react": "^0.113.0", "markdown-to-jsx": "^7.1.9", "react": "^18.2.0", @@ -7469,8 +7470,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -16943,8 +16943,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.debounce": { "version": "4.0.8", diff --git a/client/package.json b/client/package.json index 3701fed8e6..ca58e257ce 100644 --- a/client/package.json +++ b/client/package.json @@ -30,6 +30,7 @@ "clsx": "^1.2.1", "crypto-browserify": "^3.12.0", "highlight.js": "^11.7.0", + "lodash": "^4.17.21", "lucide-react": "^0.113.0", "markdown-to-jsx": "^7.1.9", "react": "^18.2.0", diff --git a/client/src/components/Nav/NavLinks.jsx b/client/src/components/Nav/NavLinks.jsx index 9c42b5bb39..72cd44ce35 100644 --- a/client/src/components/Nav/NavLinks.jsx +++ b/client/src/components/Nav/NavLinks.jsx @@ -1,6 +1,7 @@ import React from 'react'; import NavLink from './NavLink'; import LogOutIcon from '../svg/LogOutIcon'; +import SearchBar from './SearchBar'; import ClearConvos from './ClearConvos'; import DarkMode from './DarkMode'; import Logout from './Logout'; @@ -8,6 +9,7 @@ import Logout from './Logout'; export default function NavLinks() { return ( <> + diff --git a/client/src/components/Nav/SearchBar.jsx b/client/src/components/Nav/SearchBar.jsx new file mode 100644 index 0000000000..16778d22ac --- /dev/null +++ b/client/src/components/Nav/SearchBar.jsx @@ -0,0 +1,66 @@ +import React, { useState, useCallback } from 'react'; +import { debounce } from 'lodash'; +import { useDispatch, useSelector } from 'react-redux'; +import { Search } from 'lucide-react'; +import { setQuery } from '~/store/searchSlice'; +import { setPage, refreshConversation } from '~/store/convoSlice'; + +export default function SearchBar() { + const dispatch = useDispatch(); + const [inputValue, setInputValue] = useState(''); + const { search } = useSelector((state) => state.search); + + const debouncedChangeHandler = useCallback( + debounce((q) => { + dispatch(setQuery(q)); + }, 750), + [dispatch] + ); + + const handleKeyUp = (e) => { + const { value } = e.target; + if (e.keyCode === 8 && value === '') { + // Value after clearing input: "" + console.log(`Value after clearing input: "${value}"`); + dispatch(setPage(1)); + dispatch(setQuery('')); + dispatch(refreshConversation()); + } + }; + + + const changeHandler = (e) => { + 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)); + dispatch(setQuery('')); + dispatch(refreshConversation()); + } else { + debouncedChangeHandler(q); + } + }; + + return ( +
+ {} + +
+ ); +} diff --git a/client/src/components/Nav/index.jsx b/client/src/components/Nav/index.jsx index c58db30a8c..0b6e8e5c49 100644 --- a/client/src/components/Nav/index.jsx +++ b/client/src/components/Nav/index.jsx @@ -10,7 +10,8 @@ import { increasePage, decreasePage, setPage, setConvos, setPages } from '~/stor export default function Nav({ navVisible, setNavVisible }) { const dispatch = useDispatch(); const [isHovering, setIsHovering] = useState(false); - const { conversationId, convos, search, pages, pageNumber, refreshConvoHint } = useSelector( + const { search, query } = useSelector((state) => state.search); + const { conversationId, convos, pages, pageNumber, refreshConvoHint } = useSelector( (state) => state.convo ); const onSuccess = (data) => { @@ -24,8 +25,12 @@ export default function Nav({ navVisible, setNavVisible }) { } }; - const { data, isLoading, mutate } = swr(`/api/${search ? 'search?q=' : `convos?pageNumber=${pageNumber}`}`, onSuccess, { - revalidateOnMount: false + const { data, isLoading, mutate } = swr(`/api/${search ? `search?q=${query}&pageNumber=${pageNumber}` : `convos?pageNumber=${pageNumber}`}`, onSuccess, { + revalidateOnMount: false, + revalidateIfStale: !search, + revalidateOnFocus: !search, + revalidateOnReconnect: !search, + populateCache: !search, }); const containerRef = useRef(null); @@ -103,7 +108,7 @@ export default function Nav({ navVisible, setNavVisible }) { ref={containerRef} >
- {isLoading && pageNumber === 1 ? ( + {isLoading && (pageNumber === 1 || search) ? ( ) : ( { + state.search = action.payload; + }, + setQuery: (state, action) => { + const q = action.payload; + state.query = q; + + if (!q || q === '') { + state.search = false; + } else { + state.search = true; + } + }, + } +}); + +export const { setSearchState, setQuery } = currentSlice.actions; + +export default currentSlice.reducer;