From 15ff02ccef8b18cac7b5a47ee71534d11a2f95bf Mon Sep 17 00:00:00 2001 From: Ricardo Costa Date: Tue, 25 Jun 2024 16:04:41 +0100 Subject: [PATCH] Refactoring & Bug Fixes --- code/client/src/App.tsx | 8 ++--- code/client/src/contexts/auth/AuthContext.tsx | 3 ++ .../contexts/workspace/WorkspaceContext.tsx | 2 +- .../src/services/commits/commitsService.ts | 6 ++-- .../src/ui/components/header/Header.scss | 9 ++++- .../src/ui/components/header/Header.tsx | 19 ++++++++--- .../ui/components/popup-menu/PopupMenu.tsx | 26 ++++++++------ .../src/ui/components/sidebar/Sidebar.tsx | 22 +++++++----- .../workspace-tree/TreeResourceView.tsx | 6 ++-- .../commit-history/CommitHistory.tsx | 34 +++++++++++-------- .../floating-buttons/FloatingButtons.tsx | 4 ++- code/client/src/ui/pages/home/Home.tsx | 28 +++++++-------- .../Landing.scss => login/Login.scss} | 2 +- .../{landing/Landing.tsx => login/Login.tsx} | 17 +++++----- code/client/src/ui/pages/search/Search.tsx | 18 ++++++---- .../http/handlers/commitsHandlers.ts | 6 ++-- .../http/handlers/workspacesHandlers.ts | 10 +++--- .../ws/events/workspace/onJoinWorkspace.ts | 4 +-- code/server/src/services/DocumentsService.ts | 4 +-- 19 files changed, 135 insertions(+), 93 deletions(-) rename code/client/src/ui/pages/{landing/Landing.scss => login/Login.scss} (98%) rename code/client/src/ui/pages/{landing/Landing.tsx => login/Login.tsx} (74%) diff --git a/code/client/src/App.tsx b/code/client/src/App.tsx index bf7a72ed..9e165527 100644 --- a/code/client/src/App.tsx +++ b/code/client/src/App.tsx @@ -3,7 +3,6 @@ import Document from '@ui/pages/document/Document'; import Header from '@ui/components/header/Header'; import Workspace from '@ui/pages/workspace/Workspace'; import NotFound from '@ui/pages/notfound/NotFound'; -import './App.scss'; import { ErrorProvider } from '@/contexts/error/ErrorContext'; import Sidebar from '@ui/components/sidebar/Sidebar'; import { WorkspaceProvider } from '@/contexts/workspace/WorkspaceContext'; @@ -12,10 +11,11 @@ import { CommunicationProvider } from '@/contexts/communication/CommunicationCon import Home from '@ui/pages/home/Home'; import AuthProvider from '@/contexts/auth/AuthContext'; import Profile from '@ui/pages/profile/Profile'; -import Landing from '@ui/pages/landing/Landing'; +import Login from '@ui/pages/login/Login'; import Search from '@ui/pages/search/Search'; import CommitHistory from '@ui/pages/document/components/commit-history/CommitHistory'; import Commit from '@ui/pages/document/components/commit/Commit'; +import './App.scss'; function App() { return ( @@ -27,9 +27,9 @@ function App() {
- } /> + } /> diff --git a/code/client/src/contexts/auth/AuthContext.tsx b/code/client/src/contexts/auth/AuthContext.tsx index 8df89094..6cff5b3e 100644 --- a/code/client/src/contexts/auth/AuthContext.tsx +++ b/code/client/src/contexts/auth/AuthContext.tsx @@ -7,6 +7,7 @@ import { useNavigate } from 'react-router-dom'; export type AuthContextType = { currentUser: User | null; + isLoggedIn: boolean; loginWithGoogle: () => Promise; loginWithGithub: () => Promise; logout: () => Promise; @@ -15,6 +16,7 @@ export type AuthContextType = { export const AuthContext = createContext({ currentUser: null, + isLoggedIn: false, loginWithGoogle: async () => {}, loginWithGithub: async () => {}, logout: async () => {}, @@ -69,6 +71,7 @@ export function AuthProvider({ children }: AuthProviderProps) { ({}); diff --git a/code/client/src/services/commits/commitsService.ts b/code/client/src/services/commits/commitsService.ts index 2b54a3d0..82afc478 100644 --- a/code/client/src/services/commits/commitsService.ts +++ b/code/client/src/services/commits/commitsService.ts @@ -11,8 +11,8 @@ function commitsService(http: HttpCommunication, errorHandler: ErrorHandler, wid return errorHandler(async () => await http.post(`/workspaces/${wid}/${id}/rollback`, { commitId })); } - async function fork(commitId: string) { - return errorHandler(async () => await http.post(`/workspaces/${wid}/${id}/fork`, { commitId })); + async function clone(commitId: string) { + return errorHandler(async () => await http.post(`/workspaces/${wid}/${id}/clone`, { commitId })); } async function getCommits(): Promise { @@ -26,7 +26,7 @@ function commitsService(http: HttpCommunication, errorHandler: ErrorHandler, wid return { commit, rollback, - fork, + clone, getCommits, getCommit, }; diff --git a/code/client/src/ui/components/header/Header.scss b/code/client/src/ui/components/header/Header.scss index 4633bba4..60083cee 100644 --- a/code/client/src/ui/components/header/Header.scss +++ b/code/client/src/ui/components/header/Header.scss @@ -25,9 +25,16 @@ align-items: center; margin-right: 1rem; gap: 2vh; + padding-left: 10vh; + padding-right: 2vh; button { - padding: 1vh; + padding: 1.5vh; + gap: 1vh; + + svg { + font-size: larger; + } } } diff --git a/code/client/src/ui/components/header/Header.tsx b/code/client/src/ui/components/header/Header.tsx index dea92284..84e0ec88 100644 --- a/code/client/src/ui/components/header/Header.tsx +++ b/code/client/src/ui/components/header/Header.tsx @@ -2,6 +2,7 @@ import { useAuth } from '@/contexts/auth/useAuth'; import { Link, useLocation, useNavigate } from 'react-router-dom'; import { ChangeEvent, FormEvent, useState } from 'react'; import './Header.scss'; +import { MdLogin, MdLogout } from 'react-icons/md'; function Header() { const { currentUser, logout } = useAuth(); @@ -20,9 +21,9 @@ function Header() { return (
- NoteSpace + NoteSpace
- {location.pathname !== '/' && ( + {location.pathname !== '/login' && (
- {currentUser && ( + {currentUser ? ( <> {currentUser?.displayName} - + + ) : ( + location.pathname !== '/login' && ( + + ) )}
diff --git a/code/client/src/ui/components/popup-menu/PopupMenu.tsx b/code/client/src/ui/components/popup-menu/PopupMenu.tsx index aa002a1c..d682b1fa 100644 --- a/code/client/src/ui/components/popup-menu/PopupMenu.tsx +++ b/code/client/src/ui/components/popup-menu/PopupMenu.tsx @@ -1,6 +1,7 @@ -import React, { ReactNode, useEffect, useState } from 'react'; +import React, { ReactNode, useCallback, useEffect, useState } from 'react'; import { Menu, PopoverPosition } from '@mui/material'; import './PopupMenu.scss'; +import useWorkspace from '@/contexts/workspace/useWorkspace'; type PopupMenuProps = { item: ReactNode; @@ -11,15 +12,20 @@ type PopupMenuProps = { function PopupMenu({ item, trigger, children }: PopupMenuProps) { const [anchorEl, setAnchorEl] = useState(null); const [contextMenuPosition, setContextMenuPosition] = useState(null); + const { isMember } = useWorkspace(); - const onOpen = (event: MouseEvent | React.MouseEvent) => { - event.preventDefault(); - setContextMenuPosition({ - left: event.clientX - 2, - top: event.clientY - 4, - }); - setAnchorEl(event.currentTarget as HTMLElement); - }; + const onOpen = useCallback( + (event: MouseEvent | React.MouseEvent) => { + event.preventDefault(); + if (!isMember) return; + setContextMenuPosition({ + left: event.clientX - 2, + top: event.clientY - 4, + }); + setAnchorEl(event.currentTarget as HTMLElement); + }, + [isMember] + ); const onClose = () => { setAnchorEl(null); @@ -34,7 +40,7 @@ function PopupMenu({ item, trigger, children }: PopupMenuProps) { return () => { triggerElement.removeEventListener('click', onOpen); }; - }, [trigger]); + }, [onOpen, trigger]); return (
{} : onOpen} onClick={onClose}> diff --git a/code/client/src/ui/components/sidebar/Sidebar.tsx b/code/client/src/ui/components/sidebar/Sidebar.tsx index 20491d45..a9d69543 100644 --- a/code/client/src/ui/components/sidebar/Sidebar.tsx +++ b/code/client/src/ui/components/sidebar/Sidebar.tsx @@ -9,11 +9,13 @@ import { TiHome } from 'react-icons/ti'; import { GoPlus } from 'react-icons/go'; import { ResourceType } from '@notespace/shared/src/workspace/types/resource'; import CreateResourceMenu from '@ui/components/sidebar/components/CreateResourceMenu'; +import { useAuth } from '@/contexts/auth/useAuth'; import './Sidebar.scss'; function Sidebar() { const { width, isOpen, isLocked, isLoaded, handlers } = useSidebarState(); - const { workspace, resources, operations } = useWorkspace(); + const { workspace, resources, operations, isMember } = useWorkspace(); + const { isLoggedIn } = useAuth(); if (!isLoaded) return null; return ( @@ -35,10 +37,12 @@ function Sidebar() { Home -
  • - - Workspaces -
  • + {isLoggedIn && ( +
  • + + Workspaces +
  • + )}
  • Recent @@ -58,9 +62,11 @@ function Sidebar() { onCreateNew={(type: ResourceType) => operations.createResource('Untitled', type, workspace.id)} trigger="sidebar-create-resource" /> - + {isMember && ( + + )}
  • diff --git a/code/client/src/ui/components/sidebar/components/workspace-tree/TreeResourceView.tsx b/code/client/src/ui/components/sidebar/components/workspace-tree/TreeResourceView.tsx index 22c44fa2..3df0951f 100644 --- a/code/client/src/ui/components/sidebar/components/workspace-tree/TreeResourceView.tsx +++ b/code/client/src/ui/components/sidebar/components/workspace-tree/TreeResourceView.tsx @@ -8,6 +8,7 @@ import CreateResourceMenu from '@ui/components/sidebar/components/CreateResource import { GoPlus } from 'react-icons/go'; import ResourceContextMenu from '@ui/pages/workspace/components/ResourceContextMenu'; import useEditing from '@ui/hooks/useEditing'; +import useWorkspace from '@/contexts/workspace/useWorkspace'; type TreeResourceViewProps = { workspace: string; @@ -34,6 +35,7 @@ function TreeResourceView({ onDrag, onDrop, }: TreeResourceViewProps) { + const { isMember } = useWorkspace(); const [isOpen, setIsOpen] = useState(true); const { component, isEditing, setIsEditing } = useEditing(resource.name || 'Untitled', (name: string) => onRenameResource!(resource.id, name) @@ -45,7 +47,7 @@ function TreeResourceView({ const props: React.HTMLProps = { id: resource.id, - draggable: true, + draggable: isMember, onDragOver: (e: React.DragEvent) => e.preventDefault(), onDragStart: onDrag, onDrop: onDrop, @@ -92,7 +94,7 @@ function TreeResourceView({ )} - {!isEditing && ( + {!isEditing && isMember && ( diff --git a/code/client/src/ui/pages/document/components/commit-history/CommitHistory.tsx b/code/client/src/ui/pages/document/components/commit-history/CommitHistory.tsx index 23fc03cf..ce044687 100644 --- a/code/client/src/ui/pages/document/components/commit-history/CommitHistory.tsx +++ b/code/client/src/ui/pages/document/components/commit-history/CommitHistory.tsx @@ -1,4 +1,3 @@ -import './CommitHistory.scss'; import useCommitsService from '@services/commits/useCommitsService'; import { Link, useNavigate, useParams } from 'react-router-dom'; import useResourcesService from '@services/resource/useResourcesService'; @@ -7,8 +6,10 @@ import useLoading from '@ui/hooks/useLoading'; import { DocumentResource } from '@notespace/shared/src/workspace/types/resource'; import { Commit } from '@notespace/shared/src/document/types/commits'; import { formatTimePassed } from '@/utils/utils'; -import { FaCodeFork } from 'react-icons/fa6'; +import { FaClone } from 'react-icons/fa6'; import { FaUndo } from 'react-icons/fa'; +import useWorkspace from '@/contexts/workspace/useWorkspace'; +import './CommitHistory.scss'; function CommitHistory() { const [document, setDocument] = useState(); @@ -16,7 +17,8 @@ function CommitHistory() { const { loading, spinner, startLoading, stopLoading } = useLoading(); const { wid, id } = useParams(); const { getResource } = useResourcesService(); - const { getCommits, fork, rollback } = useCommitsService(); + const { getCommits, clone, rollback } = useCommitsService(); + const { isMember } = useWorkspace(); const navigate = useNavigate(); async function onRollback(commitId: string) { @@ -24,8 +26,8 @@ function CommitHistory() { navigate(`/workspaces/${wid}/${id}`); } - async function onFork(commitId: string) { - await fork(commitId); + async function onClone(commitId: string) { + await clone(commitId); navigate(`/workspaces/${wid}`); } @@ -59,16 +61,18 @@ function CommitHistory() { {commit.author.name} committed{' '} {formatTimePassed(new Date(commit.timestamp).toLocaleString())}

    -
    - - -
    + {isMember && ( +
    + + +
    + )} )) ) : ( diff --git a/code/client/src/ui/pages/document/components/floating-buttons/FloatingButtons.tsx b/code/client/src/ui/pages/document/components/floating-buttons/FloatingButtons.tsx index c60170d3..5ea470c6 100644 --- a/code/client/src/ui/pages/document/components/floating-buttons/FloatingButtons.tsx +++ b/code/client/src/ui/pages/document/components/floating-buttons/FloatingButtons.tsx @@ -3,14 +3,16 @@ import CommitDialog from '@ui/pages/document/components/floating-buttons/CommitD import useCommitsService from '@services/commits/useCommitsService'; import { useNavigate, useParams } from 'react-router-dom'; import { MdHistory } from 'react-icons/md'; +import useWorkspace from '@/contexts/workspace/useWorkspace'; function FloatingButtons() { const { wid, id } = useParams(); const { commit } = useCommitsService(); + const { isMember } = useWorkspace(); const navigate = useNavigate(); return (
    - + {isMember && } diff --git a/code/client/src/ui/pages/home/Home.tsx b/code/client/src/ui/pages/home/Home.tsx index 723192e2..9b0de680 100644 --- a/code/client/src/ui/pages/home/Home.tsx +++ b/code/client/src/ui/pages/home/Home.tsx @@ -23,21 +23,19 @@ function Home() { return (

    Home

    -

    Welcome to NoteSpace

    - Go to Workspaces -
    -
    -
    -

    Public Workspaces

    - {loading - ? spinner - : workspaces.map(workspace => ( -
    - - {workspace.name} - -
    - ))} + {loading ? ( + spinner + ) : workspaces.length > 0 ? ( + workspaces.map(workspace => ( +
    + + {workspace.name} + +
    + )) + ) : ( +

    No workspaces yet

    + )}
    ); } diff --git a/code/client/src/ui/pages/landing/Landing.scss b/code/client/src/ui/pages/login/Login.scss similarity index 98% rename from code/client/src/ui/pages/landing/Landing.scss rename to code/client/src/ui/pages/login/Login.scss index 5c88741f..8c143d7f 100644 --- a/code/client/src/ui/pages/landing/Landing.scss +++ b/code/client/src/ui/pages/login/Login.scss @@ -1,4 +1,4 @@ -.landing { +.login { display: flex; flex-direction: column; justify-content: center; diff --git a/code/client/src/ui/pages/landing/Landing.tsx b/code/client/src/ui/pages/login/Login.tsx similarity index 74% rename from code/client/src/ui/pages/landing/Landing.tsx rename to code/client/src/ui/pages/login/Login.tsx index 76c5d191..d5928a8f 100644 --- a/code/client/src/ui/pages/landing/Landing.tsx +++ b/code/client/src/ui/pages/login/Login.tsx @@ -3,20 +3,20 @@ import { useNavigate } from 'react-router-dom'; import { useEffect } from 'react'; import googleIcon from '@assets/images/google-icon.png'; import { FaGithub } from 'react-icons/fa6'; -import './Landing.scss'; +import './Login.scss'; -function Landing() { - const { currentUser, loginWithGoogle, loginWithGithub } = useAuth(); +function Login() { + const { isLoggedIn, loginWithGoogle, loginWithGithub } = useAuth(); const navigate = useNavigate(); useEffect(() => { - if (currentUser) { - navigate('/home'); + if (isLoggedIn) { + navigate('/'); } - }, [currentUser, navigate]); + }, [isLoggedIn, navigate]); return ( -
    +

    Welcome to NoteSpace

    @@ -30,10 +30,9 @@ function Landing() {
    -

    Please choose a provider to continue

    ); } -export default Landing; +export default Login; diff --git a/code/client/src/ui/pages/search/Search.tsx b/code/client/src/ui/pages/search/Search.tsx index b8008a7a..89fa3d2b 100644 --- a/code/client/src/ui/pages/search/Search.tsx +++ b/code/client/src/ui/pages/search/Search.tsx @@ -25,13 +25,17 @@ function Search() { return (

    Search results for "{query}"

    - {results.map(workspace => ( -
    - - {workspace.name} - -
    - ))} + {results.length > 0 ? ( + results.map(workspace => ( +
    + + {workspace.name} + +
    + )) + ) : ( +

    No results found

    + )}