From 33e1abc65fcce4ee523079ca5d61c1be1bb9d1d1 Mon Sep 17 00:00:00 2001 From: Zakariyya Almalki Date: Sun, 3 Mar 2024 17:58:14 -0500 Subject: [PATCH] allow search using title and tags --- client/package.json | 1 + client/pnpm-lock.yaml | 8 ++++++ client/src/components/lib/Board.tsx | 9 ++++--- client/src/components/lib/BoardScroll.tsx | 24 +++++++++++++++--- client/src/components/lib/TopBar.tsx | 31 +++++++++++++++++------ client/src/views/Dashboard.tsx | 10 ++++++-- 6 files changed, 65 insertions(+), 18 deletions(-) diff --git a/client/package.json b/client/package.json index ec87914..73f5392 100644 --- a/client/package.json +++ b/client/package.json @@ -38,6 +38,7 @@ "electron-is-dev": "^2.0.0", "file-saver": "^2.0.5", "firebase": "^10.4.0", + "fuse.js": "^7.0.0", "image-blob-reduce": "^4.1.0", "jspdf": "^2.5.1", "lodash": "^4.17.21", diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index 6f75f11..8a00f2b 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -83,6 +83,9 @@ dependencies: firebase: specifier: ^10.4.0 version: 10.4.0 + fuse.js: + specifier: ^7.0.0 + version: 7.0.0 image-blob-reduce: specifier: ^4.1.0 version: 4.1.0 @@ -4768,6 +4771,11 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true + /fuse.js@7.0.0: + resolution: {integrity: sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==} + engines: {node: '>=10'} + dev: false + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} diff --git a/client/src/components/lib/Board.tsx b/client/src/components/lib/Board.tsx index 58470de..8c58b31 100644 --- a/client/src/components/lib/Board.tsx +++ b/client/src/components/lib/Board.tsx @@ -1,8 +1,8 @@ -import React from 'react'; +import React, { useState } from 'react'; import { TopBar } from '@/components/lib/TopBar'; import { BoardScroll } from './BoardScroll'; import { Settings } from './Settings'; -import { useCanvasBoardStore } from '@/stores/CanavasBoardStore'; +import { Canvas, useCanvasBoardStore } from '@/stores/CanavasBoardStore'; /** * Define a react component that displays @@ -13,10 +13,11 @@ import { useCanvasBoardStore } from '@/stores/CanavasBoardStore'; export const Board = () => { const { board } = useCanvasBoardStore(['board']); + const [searchCanvases, setSearchCanvases] = useState([]); return (
- - {board === 'Folder' && } + + {board === 'Folder' && } {board == 'Settings' && } {/** To be added template and setting page */}
diff --git a/client/src/components/lib/BoardScroll.tsx b/client/src/components/lib/BoardScroll.tsx index e6da30c..6b27f8e 100644 --- a/client/src/components/lib/BoardScroll.tsx +++ b/client/src/components/lib/BoardScroll.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { CalendarIcon } from '@radix-ui/react-icons'; -import { useCanvasBoardStore } from '@/stores/CanavasBoardStore'; +import { Canvas, useCanvasBoardStore } from '@/stores/CanavasBoardStore'; import { Thumbnail } from './Thumbnail'; import { DeleteCanavasDialog } from './DeleteCanvasDialog'; import axios from 'axios'; @@ -59,13 +59,18 @@ export const createStateWithRoughElement = (state: CanvasElementState) => { * @author Abdalla Abdelhadi */ -export const BoardScroll = () => { +export const BoardScroll = ({ + searchCanvases, +}: { + searchCanvases: Canvas[]; +}) => { const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [state, setState] = useState(); const [thumbnailUrl, setThumbnailUrl] = useState(''); - const { canvases, boardMeta, setBoardMeta } = useCanvasBoardStore([ + const { canvases, boardMeta, folder, setBoardMeta } = useCanvasBoardStore([ 'canvases', 'boardMeta', + 'folder', 'setBoardMeta', ]); const { setCanvasElementState } = useCanvasElementStore([ @@ -79,11 +84,22 @@ export const BoardScroll = () => { const { toast } = useToast(); + const sortedCavases = ( + searchCanvases.length === 0 ? canvases : searchCanvases + ) + .filter((board) => (folder === 'Recent' ? true : folder === board.folder)) + .sort((a, b) => { + const dateA = new Date(a.updatedAt); + const dateB = new Date(b.updatedAt); + + return dateB.getTime() - dateA.getTime(); + }); + return (
{/* eslint-disable-next-line sonarjs/cognitive-complexity */} - {canvases.map((board) => ( + {sortedCavases.map((board) => (
{ - const { board, folder, addCanvas, setBoardMeta } = useCanvasBoardStore([ - 'board', - 'folder', - 'addCanvas', - 'setBoardMeta', - ]); +export const TopBar = ({ + setSearchCanvases, +}: { + setSearchCanvases: (canvases: Canvas[]) => void; +}) => { + const { canvases, board, folder, addCanvas, setBoardMeta } = + useCanvasBoardStore([ + 'canvases', + 'board', + 'folder', + 'addCanvas', + 'setBoardMeta', + ]); const { userID } = useAuthStore(['userID']); const { setMode } = useAppStore(['setMode']); + const fuseOptions = { keys: ['title', 'tags'] }; + + const fuse = new Fuse(canvases, fuseOptions); return (
@@ -30,6 +40,11 @@ export const TopBar = () => {
+ setSearchCanvases( + fuse.search(e.target.value).map((target) => target.item), + ) + } type="text" className="h-[25px] mt-2 basis-3/4" placeholder="Search Boards" diff --git a/client/src/views/Dashboard.tsx b/client/src/views/Dashboard.tsx index a975a5e..b2b9d43 100644 --- a/client/src/views/Dashboard.tsx +++ b/client/src/views/Dashboard.tsx @@ -1,12 +1,18 @@ import React from 'react'; import { Sidebar } from '@/components/lib/Sidebar'; import { Board } from '@/components/lib/Board'; +import { useCanvasBoardStore } from '@/stores/CanavasBoardStore'; -const folders = ['Recent', 'Math', 'Science', 'Stats']; export default function Dashboard() { + const { canvases } = useCanvasBoardStore(['canvases']); + + const userFolders = [ + ...new Set(['Recent', ...canvases.map((board) => board.folder)]), + ]; + return (
- +
);