Skip to content

Commit

Permalink
Code Refactoring & Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
R1c4rdCo5t4 committed May 10, 2024
1 parent fe89fe2 commit 0ddb415
Show file tree
Hide file tree
Showing 28 changed files with 399 additions and 335 deletions.
22 changes: 11 additions & 11 deletions code/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ function App() {
<div className="app">
<ErrorProvider>
<CommunicationProvider communication={communication}>
<WorkspaceProvider>
<Router>
<Sidebar />
<div className="content">
<Header />
<Routes>
<Router>
<Sidebar />
<div className="content">
<Header />
<Routes>
<WorkspaceProvider>
<Route path="/" element={<Navigate to={`/documents`} />} />
<Route path="/documents" element={<Workspace />} />
<Route path="/documents/:id" element={<Document />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</WorkspaceProvider>
</WorkspaceProvider>
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</CommunicationProvider>
</ErrorProvider>
</div>
Expand Down
7 changes: 2 additions & 5 deletions code/client/src/domain/editor/crdt/fugue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,7 @@ export class Fugue {
* @param selection
*/
updateBlockStylesLocalBySelection = (style: BlockStyle, selection: Selection) =>
range(selection.start.line, selection.end.line + 1)
.map(line => this.updateBlockStyleLocal(line, style));
range(selection.start.line, selection.end.line + 1).map(line => this.updateBlockStyleLocal(line, style));

/**
* Updates the style of the node based on the given operation
Expand All @@ -240,9 +239,7 @@ export class Fugue {
updateBlockStyleRemote = ({ line, style, append }: BlockStyleOperation) =>
this.tree.updateBlockStyle(style, line, append);

getBlockStyle = (line: number) : BlockStyle =>
(this.tree.root.styles[line] as BlockStyle) || 'paragraph';

getBlockStyle = (line: number): BlockStyle => (this.tree.root.styles[line] as BlockStyle) || 'paragraph';

/**
* Traverses the tree in in-order traversal
Expand Down
2 changes: 1 addition & 1 deletion code/client/src/domain/editor/crdt/useFugue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import { Fugue } from '@domain/editor/crdt/fugue';

const useFugue = () => useMemo(() => new Fugue(), []);

export default useFugue;
export default useFugue;
2 changes: 1 addition & 1 deletion code/client/src/domain/editor/hooks/useEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ function useEvents(fugueOperations: FugueDomainOperations, { socket }: Communica
});
}

export default useEvents;
export default useEvents;
2 changes: 1 addition & 1 deletion code/client/src/domain/error/useError.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext } from 'react';
import { ErrorContext } from '@domain/error/ErrorContext';

const useError = () =>useContext(ErrorContext);
const useError = () => useContext(ErrorContext);

export default useError;
26 changes: 24 additions & 2 deletions code/client/src/domain/workspace/WorkspaceContext.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
import * as React from 'react';
import { useState, createContext } from 'react';
import { useState, createContext, useEffect } from 'react';
import { WorkspaceResource } from '@notespace/shared/workspace/types/resource.ts';
import { useCommunication } from '@/services/communication/context/useCommunication.ts';
import useError from '@domain/error/useError.ts';

export type WorkspaceContextType = {
resources: WorkspaceResource[];
setResources: (resources: WorkspaceResource[]) => void;
filePath: string | undefined;
setFilePath: (path: string) => void;
};

export const WorkspaceContext = createContext<WorkspaceContextType>({
resources: [],
setResources: () => {},
filePath: undefined,
setFilePath: () => {},
});

export function WorkspaceProvider({ children }: { children: React.ReactNode }) {
const [resources, setResources] = useState<WorkspaceResource[]>([]);
const [filePath, setFilePath] = useState<string | undefined>(undefined);
return <WorkspaceContext.Provider value={{ filePath, setFilePath }}>{children}</WorkspaceContext.Provider>;
const { http } = useCommunication();
const { showError } = useError();

useEffect(() => {
async function getResources() {
const res = await http.get('/documents');
setResources(res);
}
getResources().catch(showError);
}, [http, showError]);
return (
<WorkspaceContext.Provider value={{ resources, setResources, filePath, setFilePath }}>
{children}
</WorkspaceContext.Provider>
);
}
37 changes: 5 additions & 32 deletions code/client/src/ui/pages/workspace/Workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,26 @@
import { useEffect, useState } from 'react';
import { useCommunication } from '@/services/communication/context/useCommunication';
import { DocumentData } from '@notespace/shared/workspace/document.d.ts';
import WorkspaceHeader from '@ui/pages/workspace/components/WorkspaceHeader';
import DocumentPreview from '@ui/pages/workspace/components/DocumentPreview';
import useError from '@domain/error/useError';
import useWorkspace from '@domain/workspace/useWorkspace';
import useDocuments from '@ui/pages/workspace/hooks/useDocuments.ts';
import './Workspace.scss';

function Workspace() {
const { http, socket } = useCommunication();
const [docs, setDocs] = useState<DocumentData[]>([]);
const communication = useCommunication();
const { documents, createDocument, deleteDocument, updateDocument } = useDocuments(communication);
const { showError } = useError();
const { setFilePath } = useWorkspace();

async function createDocument(title?: string) {
const { id } = await http.post('/documents', { title });
setDocs(prev => [...prev, { id, title } as DocumentData]);
}

async function deleteDocument(id: string) {
await http.delete(`/documents/${id}`);
setDocs(docs.filter(doc => doc.id !== id));
}

async function updateDocument(id: string, title: string) {
await http.put(`/documents/${id}`, { title });
}

useEffect(() => {
async function getDocuments() {
const documents = await http.get('/documents');
setDocs(documents);
}
setFilePath('/documents');
getDocuments().catch(showError);
socket.connect('/workspace');
}, [http, socket, setFilePath, showError]);

return (
<div className="workspace">
<h2>Workspace</h2>
<WorkspaceHeader onCreateDocument={() => createDocument().catch(showError)} />
<ul>
{docs.map(document => (
{documents.map(document => (
<DocumentPreview
key={document.id}
doc={document}
onDelete={() => deleteDocument(document.id).catch(showError)}
onDuplicate={() => createDocument(document.title).catch(showError)}
onDuplicate={() => createDocument(document.name).catch(showError)}
onRename={title => updateDocument(document.id, title).catch(showError)}
/>
))}
Expand Down
56 changes: 56 additions & 0 deletions code/client/src/ui/pages/workspace/hooks/useDocuments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useState } from 'react';
import { Communication } from '@/services/communication/communication.ts';
import { DocumentResourceMetadata } from '@notespace/shared/workspace/types/resource.ts';
import useSocketListeners from '@/services/communication/socket/useSocketListeners.ts';
import useWorkspace from '@domain/workspace/useWorkspace.ts';
import { ResourceType } from '@notespace/shared/workspace/types/resource.ts';

export function useDocuments({ http, socket }: Communication) {
const { resources } = useWorkspace();
const [documents, setDocuments] = useState<DocumentResourceMetadata[]>(
resources.filter(res => res.type === ResourceType.DOCUMENT) as DocumentResourceMetadata[]
);

function onCreateDocument(id: string, name?: string) {
const document: DocumentResourceMetadata = { id, name: name || '', type: ResourceType.DOCUMENT };
setDocuments(prev => [...prev, document]);
}

async function createDocument(title?: string) {
const { id } = await http.post('/documents', { title });
onCreateDocument(id, title);
}

function onDeleteDocument(id: string) {
setDocuments(documents.filter(res => res.id !== id));
}

async function deleteDocument(id: string) {
await http.delete(`/documents/${id}`);
onDeleteDocument(id);
}

function onUpdateDocument(id: string, title: string) {
setDocuments(documents.map(doc => (doc.id === id ? { ...doc, title } : doc)));
}

async function updateDocument(id: string, title: string) {
await http.put(`/documents/${id}`, { title });
onUpdateDocument(id, title);
}

useSocketListeners(socket, {
'document:create': onCreateDocument,
'document:delete': onDeleteDocument,
'document:update': onUpdateDocument,
});

return {
documents,
createDocument,
deleteDocument,
updateDocument,
};
}

export default useDocuments;
1 change: 0 additions & 1 deletion code/server/src/ts/controllers/http/httpResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ export const httpResponse = {
conflict: (res: Response) => res.status(409),
internalServerError: (res: Response) => res.status(500),
};

6 changes: 3 additions & 3 deletions code/server/src/ts/controllers/http/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { NoteSpaceServices } from '@services/noteSpaceServices';
import workspaceHandlers from '@controllers/http/workspace/workspaceHandlers';
import errorHandler from '@controllers/http/errorHandler';

export default function (service: NoteSpaceServices) {
if (!service) throw new Error('Service parameter is required');
export default function (services: NoteSpaceServices) {
if (!services) throw new Error('Services parameter is required');

const router = PromiseRouter(); // automatically routes unhandled errors to error handling middleware
router.use(express.urlencoded({ extended: true }));

router.use('/workspaces', workspaceHandlers(service));
router.use('/workspaces', workspaceHandlers(services));
router.use(errorHandler);
return router;
}
62 changes: 23 additions & 39 deletions code/server/src/ts/controllers/http/workspace/resourcesHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,64 @@
import PromiseRouter from 'express-promise-router';
import { ResourceInputModel, WorkspaceResource } from '../../../../../../shared/workspace/resource';
import { ResourceInputModel, WorkspaceResource } from '@notespace/shared/workspace/resource';
import { httpResponse } from '@controllers/http/httpResponse';
import { Request, Response } from 'express';
import { ResourcesService } from '@services/resourcesService';
import { InvalidParameterError } from '@domain/errors/errors';

function resourcesHandlers(services : ResourcesService) {
function resourcesHandlers(service: ResourcesService) {
const router = PromiseRouter();

/**
* Create a new resource -
* @param req
* @param res
*/
const createResource = async (req : Request, res : Response) => {
const createResource = async (req: Request, res: Response) => {
const resource = req.body as ResourceInputModel;
const id = await services.createResource(resource);

if (!id) return httpResponse.internalServerError(res).send();

const id = await service.createResource(resource);
return httpResponse.created(res).json({ id });
}
};

/**
* Get a resource by its id
* @param req
* @param res
*/
const getResource = async (req : Request, res: Response) => {
const id = req.params.resId;
const resource = await services.getResource(id);

if (!resource) return httpResponse.notFound(res).send();

const getResource = async (req: Request, res: Response) => {
const { wid, id, metaOnly } = req.params;
const resource = await service.getResource(wid, id, metaOnly === 'true');
return httpResponse.ok(res).json(resource);
}


const getDocContent = async (req : Request, res : Response) => {
const {wid, rid} = req.params;
const content = await services.getDocContent(wid, rid);
return httpResponse.ok(res).json(content);
}
};

/**
* Update a resource
* @param req
* @param res
*/
const updateResource = async (req : Request, res : Response) => {
const resource = req.body as Partial<WorkspaceResource>

if (!resource.id) return httpResponse.badRequest(res).send('Resource id is required');

await services.updateResource(resource);
const updateResource = async (req: Request, res: Response) => {
const resource = req.body as Partial<WorkspaceResource>;
if (!resource.id) throw new InvalidParameterError('Resource id is required');
await service.updateResource(resource);
return httpResponse.noContent(res).send();
}
};

/**
* Delete a resource
* @param req
* @param res
*/
const deleteResource = async (req : Request, res : Response) => {
const id = req.params.resId;
await services.deleteResource(id);
const deleteResource = async (req: Request, res: Response) => {
const { id } = req.params;
await service.deleteResource(id);
return httpResponse.noContent(res).send();
}
};

router.post('/', createResource);
router.get('/:rid', getResource);
router.get('/:rid/content', getDocContent);

router.put('/:rid', updateResource);
router.delete('/:rid', deleteResource);
router.get('/:id', getResource);
router.put('/:id', updateResource);
router.delete('/:id', deleteResource);

return router;
}

export default resourcesHandlers;
export default resourcesHandlers;
Loading

0 comments on commit 0ddb415

Please sign in to comment.