Skip to content

Commit

Permalink
Implemented Simple Version Control System
Browse files Browse the repository at this point in the history
  • Loading branch information
R1c4rdCo5t4 committed Jun 24, 2024
1 parent 6821a73 commit 425238b
Show file tree
Hide file tree
Showing 32 changed files with 493 additions and 39 deletions.
2 changes: 2 additions & 0 deletions code/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import AuthProvider from '@/contexts/auth/AuthContext';
import Profile from '@ui/pages/profile/Profile';
import Landing from '@ui/pages/landing/Landing';
import Search from '@ui/pages/search/Search';
import DocumentCommits from '@ui/pages/document/components/history/DocumentCommits';

function App() {
return (
Expand Down Expand Up @@ -66,6 +67,7 @@ function App() {
<Routes>
<Route path="/" element={<Workspace />} />
<Route path="/:id" element={<Document />} />
<Route path="/:id/commits" element={<DocumentCommits />} />
</Routes>
</WorkspaceProvider>
}
Expand Down
4 changes: 2 additions & 2 deletions code/client/src/domain/workspaces/useResources.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ResourceType, Resource } from '@notespace/shared/src/workspace/types/resource';
import useResourceService from '@services/resource/useResourceService';
import useResourcesService from '@services/resource/useResourcesService';
import useSocketListeners from '@services/communication/socket/useSocketListeners';
import { useCommunication } from '@/contexts/communication/useCommunication';
import useWorkspaceTree from '@domain/workspaces/tree/useWorkspaceTree';

function useResources() {
const service = useResourceService();
const service = useResourcesService();
const { socket } = useCommunication();
const tree = useWorkspaceTree();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { HttpCommunication } from '@services/communication/http/httpCommunication';
import { ResourceInputModel, ResourceType, Resource } from '@notespace/shared/src/workspace/types/resource';

function resourceService(http: HttpCommunication, wid: string) {
function resourcesService(http: HttpCommunication, wid: string) {
async function getResource(id: string): Promise<Resource> {
return await http.get(`/workspaces/${wid}/${id}`);
}
Expand All @@ -28,4 +28,4 @@ function resourceService(http: HttpCommunication, wid: string) {
};
}

export default resourceService;
export default resourcesService;
13 changes: 0 additions & 13 deletions code/client/src/services/resource/useResourceService.ts

This file was deleted.

13 changes: 13 additions & 0 deletions code/client/src/services/resource/useResourcesService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useMemo } from 'react';
import { useCommunication } from '@/contexts/communication/useCommunication';
import { useParams } from 'react-router-dom';
import resourcesService from '@services/resource/resourcesService';

function useResourcesService() {
const { http } = useCommunication();
const { wid } = useParams();
if (!wid) throw new Error('Cannot use document service outside of a workspace');
return useMemo(() => resourcesService(http, wid), [http, wid]);
}

export default useResourcesService;
13 changes: 13 additions & 0 deletions code/client/src/services/versions/useVersionsService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useMemo } from 'react';
import { useCommunication } from '@/contexts/communication/useCommunication';
import { useParams } from 'react-router-dom';
import versionsService from '@services/versions/versionsService';

function useVersionsService() {
const { http } = useCommunication();
const { wid, id } = useParams();
if (!wid || !id) throw new Error('Cannot use version service outside of a document');
return useMemo(() => versionsService(http, wid, id), [http, wid, id]);
}

export default useVersionsService;
29 changes: 29 additions & 0 deletions code/client/src/services/versions/versionsService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HttpCommunication } from '@services/communication/http/httpCommunication';
import { DocumentVersion } from '@notespace/shared/src/document/types/versions';

function versionsService(http: HttpCommunication, wid: string, id: string) {
async function commitVersion() {
return await http.post(`/workspaces/${wid}/${id}/commit`);
}

async function getVersions(): Promise<DocumentVersion[]> {
return await http.get(`/workspaces/${wid}/${id}/versions`);
}

async function rollbackVersion(versionId: string) {
return await http.post(`/workspaces/${wid}/${id}/rollback`, { versionId });
}

async function forkVersion(versionId: string) {
return await http.post(`/workspaces/${wid}/${id}/fork`, { versionId });
}

return {
commitVersion,
getVersions,
rollbackVersion,
forkVersion,
};
}

export default versionsService;
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function TreeResourceView({
trigger={'create-new-resource-' + resource.id}
/>
{resource.type === ResourceType.DOCUMENT ? (
<div {...props} className="resource-name document">
<div {...props} className="resource-name document-resource">
{isEditing ? (
<div>
<FaFile />
Expand All @@ -84,7 +84,7 @@ function TreeResourceView({
)}
</div>
) : (
<div {...props} className="resource-name folder">
<div {...props} className="resource-name folder-resource">
<div>
<FaFolder />
{component}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
gap: 4px;
}

.folder svg {
.folder-resource svg {
color: darkgray;
}

Expand Down
2 changes: 2 additions & 0 deletions code/client/src/ui/pages/document/Document.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.document {
}
10 changes: 8 additions & 2 deletions code/client/src/ui/pages/document/Document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useCommunication } from '@/contexts/communication/useCommunication';
import useError from '@/contexts/error/useError';
import useDocumentService from '@services/resource/useResourceService';
import useDocumentService from '@services/resource/useResourcesService';
import useConnectors from '@domain/editor/connectors/useConnectors';
import { DocumentResource } from '@notespace/shared/src/workspace/types/resource';
import './Document.scss';
import Version from '@ui/pages/document/components/version/Version';

function Document() {
const communication = useCommunication();
Expand Down Expand Up @@ -51,7 +52,12 @@ function Document() {
}, [fugue, id, http, socket, publishError, services, setTitle, navigate]);

if (!loaded) return null;
return <Editor title={title} fugue={fugue} connectors={connectors} />;
return (
<div className="document">
<Editor title={title} fugue={fugue} connectors={connectors} />
<Version />
</div>
);
}

export default Document;
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ function Editor({ title, connectors, fugue }: EditorProps) {

const syncEditor = useCallback(
(slate?: Descendant[]) => {
console.log('Syncing editor...');
const newSlate = slate || toSlate(fugue);
updateEditor(newSlate);
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.document-commits {
.commit {
padding: 0.5vh 8vh;
border-radius: 10px;
background-color: black;
color: white;

display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;

.commit-actions {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 2vh;

button {
gap: 2vh;
}
}

a {
color: white;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import './DocumentCommits.scss';
import useVersionsService from '@services/versions/useVersionsService';
import { Link, useParams } from 'react-router-dom';
import useResourcesService from '@services/resource/useResourcesService';
import { useEffect, useState } from 'react';
import useLoading from '@ui/hooks/useLoading';
import { DocumentResource } from '@notespace/shared/src/workspace/types/resource';
import { DocumentVersion } from '@notespace/shared/src/document/types/versions';
import { formatTimePassed } from '@/utils/utils';
import { FaCodeFork } from 'react-icons/fa6';
import { FaUndo } from 'react-icons/fa';

function DocumentCommits() {
const [document, setDocument] = useState<DocumentResource>();
const [versions, setVersions] = useState<DocumentVersion[]>([]);
const { loading, spinner, startLoading, stopLoading } = useLoading();
const { id } = useParams();
const { getResource } = useResourcesService();
const { getVersions, forkVersion, rollbackVersion } = useVersionsService();

useEffect(() => {
async function fetchDocument() {
const document = (await getResource(id!)) as DocumentResource;
setDocument(document);
}
async function fetchVersions() {
const versions = await getVersions();
setVersions(versions);
}
startLoading();
Promise.all([fetchDocument(), fetchVersions()])
.then(() => stopLoading())
.catch(() => stopLoading());
}, [getResource, getVersions, id, startLoading, stopLoading]);

return (
<div className="document-commits">
{loading ? (
spinner
) : (
<>
<h2>Commits from "{document?.name}"</h2>
<div className="commits-list">
{versions.length > 0 ? (
versions.map(version => (
<div key={version.id} className="commit">
<p>
<Link to={''}>John Doe</Link> committed{' '}
{formatTimePassed(new Date(version.timestamp).toLocaleString())}
</p>
<div className="commit-actions">
<button onClick={() => rollbackVersion(version.id)}>
<FaUndo />
Rollback
</button>
<button onClick={() => forkVersion(version.id)}>
<FaCodeFork />
Fork
</button>
</div>
</div>
))
) : (
<p>No commits yet</p>
)}
</div>
</>
)}
</div>
);
}

export default DocumentCommits;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ReactEditor, useSlate } from 'slate-react';
import { useParams } from 'react-router-dom';
import useSocketListeners from '@services/communication/socket/useSocketListeners';
import { Resource } from '@notespace/shared/src/workspace/types/resource';
import useDocumentService from '@services/resource/useResourceService';
import useDocumentService from '@services/resource/useResourcesService';
import { ServiceConnector } from '@domain/editor/connectors/service/connector';

interface TitleProps extends React.InputHTMLAttributes<HTMLInputElement> {
Expand Down
40 changes: 40 additions & 0 deletions code/client/src/ui/pages/document/components/version/Version.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.version {
position: fixed;
bottom: 0;
right: 0;
padding: 4vh;
display: flex;
flex-direction: row;
gap: 2vh;

button {
background-color: black;
color: white;
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: background-color 0.2s;
font-size: 22px;

&:hover {
background-color: rgba(0, 0, 0, 0.7);
}

&:focus {
outline: none;
}
}
}

.commits-dialog {
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: start;
padding: 1vh;
}
21 changes: 21 additions & 0 deletions code/client/src/ui/pages/document/components/version/Version.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import './Version.scss';
import VersionControlDialog from '@ui/pages/document/components/version/VersionControlDialog';
import useVersionsService from '@services/versions/useVersionsService';
import { useNavigate, useParams } from 'react-router-dom';
import { MdHistory } from 'react-icons/md';

function Version() {
const { wid, id } = useParams();
const { commitVersion } = useVersionsService();
const navigate = useNavigate();
return (
<div className="version">
<VersionControlDialog onCommit={commitVersion} />
<button onClick={() => navigate(`/workspaces/${wid}/${id}/commits`)}>
<MdHistory />
</button>
</div>
);
}

export default Version;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Dialog from '@ui/components/dialog/Dialog';
import { useParams } from 'react-router-dom';
import { FaCodeCommit } from 'react-icons/fa6';
import { useAuth } from '@/contexts/auth/useAuth';

type VersionControlDialogProps = {
onCommit: () => void;
};

function VersionControlDialog({ onCommit }: VersionControlDialogProps) {
const { wid, id } = useParams();
const { currentUser } = useAuth();
if (!wid || !id) throw new Error('Cannot use version dialog outside of a document');
return (
<Dialog
title="New Commit"
fields={[]}
onSubmit={onCommit}
submitText="Commit"
extraContent={
<div className="commits-dialog">
<p>
Committing as <strong>{currentUser!.displayName}</strong>
</p>
</div>
}
>
<FaCodeCommit />
</Dialog>
);
}

export default VersionControlDialog;
3 changes: 3 additions & 0 deletions code/client/src/ui/pages/home/Home.scss
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
.home {
hr {
width: 50%;
}
}
Loading

0 comments on commit 425238b

Please sign in to comment.