Skip to content

Commit

Permalink
Tenancy and stores.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yyassin committed Feb 23, 2024
2 parents 051f461 + c17d7e8 commit 4d7aa6c
Show file tree
Hide file tree
Showing 19 changed files with 342 additions and 42 deletions.
5 changes: 4 additions & 1 deletion client/src/WebsocketClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface WSMessageType {
// Encapsualtes functionality to interact with websockets
export default class WebsocketClient {
userId: string;
_userId: string;
reconnectInterval: number;
socket: WebSocket | null;
room: string | null; //the current room the socket is in
Expand All @@ -58,6 +59,7 @@ export default class WebsocketClient {
this.callBacks = callBacks;
this.injectableCallbacks = {};
this.userId = userId;
this._userId = userId;
this.reconnectInterval = reconnectInterval;
this.connect(); // Create a socket
}
Expand Down Expand Up @@ -232,8 +234,9 @@ export default class WebsocketClient {
*
* @param room String, the room id
*/
async joinRoom(room: string) {
async joinRoom(room: string, collabID: string) {
this.room = room;
this.userId = `${this._userId}-${collabID}`;
return this.send({
topic: WS_TOPICS.JOIN_ROOM,
room: this.room,
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/lib/BoardHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ const BoardHeader = ({
lastModified: '',
roomID: '',
shareUrl: '',
folder: '',
tags: [],
collabID: '',
});
}}
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/lib/BoardScroll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ export const BoardScroll = () => {
id: isSelected ? '' : board.id,
lastModified: isSelected ? '' : board.updatedAt,
shareUrl: isSelected ? '' : board.shareUrl,
folder: isSelected ? '' : board.folder,
tags: isSelected ? [] : board.tags,
collabID: isSelected ? '' : collabID,
});
} catch (error) {
Expand Down
8 changes: 6 additions & 2 deletions client/src/components/lib/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
WS_TOPICS,
} from '@/constants';
import {
extractCollabID,
extractUsername,
getCanvasContext,
isDrawingTool,
Expand Down Expand Up @@ -160,9 +161,12 @@ export default function Canvas() {
* Callbacks for active tenants in the room.
*/
useEffect(() => {
socket?.on(WS_TOPICS.NOTIFY_JOIN_ROOM, () => {
socket?.on(WS_TOPICS.NOTIFY_JOIN_ROOM, (payload) => {
initTenants();
addColor(boardMeta.collabID);
const collabID = extractCollabID(
(payload as { payload: { id: string } }).payload.id,
);
collabID && addColor(collabID);
});
socket?.on(WS_TOPICS.NOTIFY_LEAVE_ROOM, initTenants);
return clearTenants;
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/lib/CommentsSheetContent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import { SheetFooter, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { TrashIcon } from '@radix-ui/react-icons';
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
import { getInitials } from '@/lib/misc';
import { useAuthStore } from '@/stores/AuthStore';
Expand Down Expand Up @@ -270,7 +271,7 @@ const CommentsSheetContent = () => {
</div>
</div>
<Button
className="bg-white hover:bg-gray-200 text-[#9493D3]"
className="p-0 h-7 w-15 bg-[#7f7dcf] hover:text-red-600 hover:bg-[#7f7dcf]"
onClick={() => {
removeComment(comment.uid);
axios.delete(REST.comment.delete, {
Expand All @@ -286,7 +287,7 @@ const CommentsSheetContent = () => {
);
}}
>
hi
<TrashIcon className="h-5 w-5" />
</Button>
</div>
))}
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/lib/DeleteCanvasDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export const DeleteCanavasDialog = ({
lastModified: '',
roomID: '',
shareUrl: '',
folder: '',
tags: [],
collabID: '',
});
axios.delete(REST.board.deleteBoard, {
Expand Down
8 changes: 6 additions & 2 deletions client/src/components/lib/DropDownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Button } from '../ui/button';

/**
* Creates a DropDownMenu for Canvas
* @author Dana El Sherif
* @author Dana El Sherif, Abdalla Abdelhadi, Zakariyya Almalki
*/

/**
Expand Down Expand Up @@ -44,8 +44,12 @@ const DropDownIcon = () => (
*/
const DropDownMenu = ({
viewportRef,
isEditDialogOpen,
setIsEditDialogOpen,
}: {
viewportRef: React.RefObject<HTMLDivElement>;
isEditDialogOpen: boolean;
setIsEditDialogOpen: (value: boolean) => void;
}) => {
const { isFullscreen } = useAppStore(['isFullscreen']);
//Handle button functionailities
Expand All @@ -57,7 +61,7 @@ const DropDownMenu = ({
console.log('Live Collab');
};
const handleEditCanvas = () => {
console.log('Editing Canvas');
setIsEditDialogOpen(!isEditDialogOpen);
};

return (
Expand Down
168 changes: 168 additions & 0 deletions client/src/components/lib/EditBoardDataDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import React, { useRef, useState } from 'react';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Input } from '../ui/input';
import { PlusCircleIcon } from 'lucide-react';
import { Button } from '../ui/button';
import { useCanvasBoardStore } from '@/stores/CanavasBoardStore';
import axios from 'axios';
import { REST } from '@/constants';
import { useWebSocketStore } from '@/stores/WebSocketStore';

/**
* An alert dialog where user can edit board data
* @author Zakariyya Almalki
*/

export default function EditBoardDataDialog({
open,
setOpen,
}: {
open: boolean;
setOpen: (value: boolean) => void;
}) {
/* Controls visibility of the addition input. */
const [isAddTagOpen, setIsTagUserOpen] = useState(false);
const tagRef = useRef<HTMLInputElement | null>(null);
const titleRef = useRef<HTMLInputElement | null>(null);
const folderRef = useRef<HTMLInputElement | null>(null);

const {
boardMeta,
setTag,
setBoardMeta,
updateCanvas,
updateCanvasInfo: updateCanvasInfo,
} = useCanvasBoardStore([
'boardMeta',
'setTag',
'setBoardMeta',
'updateCanvas',
'updateCanvasInfo',
]);

const { setWebsocketAction } = useWebSocketStore(['setWebsocketAction']);

return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Board Data</AlertDialogTitle>
<AlertDialogDescription>Edit Board Data</AlertDialogDescription>
</AlertDialogHeader>

<div className="flex items-center mb-1">
<label className="block text-sm font-medium text-gray-700 mr-1">
Title:
</label>
<Input
defaultValue={boardMeta.title}
className="mt-1 block w-full"
ref={titleRef}
/>
</div>
<div className="flex items-center mb-1">
<label className="block text-sm font-medium text-gray-700 mr-1">
Folder:
</label>
<Input
defaultValue={boardMeta.folder}
className="mt-1 block w-full"
ref={folderRef}
/>
</div>
<div className="flex items-center">
<h2 className="text-sm font-semibold text-black">Add Tags</h2>
<PlusCircleIcon
className="w-4 ml-2 cursor-pointer text-[#818cf8] hover:text-[#6c75c1]"
onClick={() => setIsTagUserOpen(!isAddTagOpen)}
/>
</div>
{isAddTagOpen && (
<div className="flex flex-row gap-4">
<Input
placeholder="Enter Tags to Add to Board"
className="p-[1rem]"
ref={tagRef}
/>
<Button
onClick={() => {
const tag = tagRef.current?.value;
if (tag && !boardMeta.tags.includes(tag)) {
setTag([...boardMeta.tags, tag]);
}
}}
className="bg-[#818cf8] hover:bg-[#6c75c1]"
>
Add
</Button>
</div>
)}
<div className="flex flex-wrap justify-center gap-4 overflow-y-scroll max-h-60 p-[1rem]">
{boardMeta.tags.map((tag, index) => (
<div
onClick={() =>
setTag(boardMeta.tags.filter((item) => item !== tag))
}
key={index}
className="bg-gray-200 rounded-md p-2 text-sm"
>
{tag}
</div>
))}
</div>

<AlertDialogFooter>
<AlertDialogCancel className="text-[#818cf8] border-[#818cf8] hover:text-[#6c75c1] hover:border-[#6c75c1]">
Cancel
</AlertDialogCancel>
<AlertDialogAction
className="bg-[#818cf8] hover:bg-[#6c75c1]"
onClick={async () => {
const newTitle = titleRef.current?.value;
const newFolder = folderRef.current?.value;
const updatedAt = await axios.put(REST.board.updateBoard, {
id: boardMeta.id,
fields: {
title: newTitle,
tags: boardMeta.tags,
folder: newFolder,
},
});
setBoardMeta({
title: newTitle,
tags: boardMeta.tags,
folder: newFolder,
lastModified: updatedAt.data.updatedAt,
});
updateCanvas(boardMeta.id, updatedAt.data.updatedAt);
updateCanvasInfo(
boardMeta.id,
newTitle ?? '',
newFolder ?? '',
boardMeta.tags,
);
setWebsocketAction(
{
boardID: boardMeta.id,
lastModified: updatedAt.data.updatedAt,
},
'updateUpdatedTime',
);
}}
>
Continue
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
6 changes: 6 additions & 0 deletions client/src/components/lib/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useAppStore } from '@/stores/AppStore';
import axios from 'axios';
import { REST } from '@/constants';
import { useAuthStore } from '@/stores/AuthStore';
import { useCommentsStore } from '@/stores/CommentsStore';

/**
* Define a react component that the top bar of the main dashboard
Expand All @@ -23,6 +24,7 @@ export const TopBar = () => {
]);
const { userID } = useAuthStore(['userID']);
const { setMode } = useAppStore(['setMode']);
const { setColorMaping } = useCommentsStore(['setColorMaping']);

return (
<div className="flex flex-col">
Expand Down Expand Up @@ -88,12 +90,16 @@ export const TopBar = () => {

addCanvas(boardData);

setColorMaping(boardData.collaborators);

setBoardMeta({
roomID: boardData.roomID,
title: boardData.title,
id: boardData.id,
lastModified: boardData.updatedAt,
shareUrl: boardData.shareUrl,
folder: boardData.folder,
tags: boardData.tags,
collabID: data.data.collabID,
});

Expand Down
5 changes: 3 additions & 2 deletions client/src/hooks/useSocket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ export const useSocket = () => {
'fileIds',
]);

const { setBoardMeta, updateCanvas } = useCanvasBoardStore([
const { boardMeta, setBoardMeta, updateCanvas } = useCanvasBoardStore([
'boardMeta',
'setBoardMeta',
'updateCanvas',
]);
Expand Down Expand Up @@ -237,7 +238,7 @@ export const useSocket = () => {
socket.current?.leaveRoom();
}
} else {
socket.current?.joinRoom(roomID);
socket.current?.joinRoom(roomID, boardMeta.collabID);
}
}, [roomID]);

Expand Down
11 changes: 11 additions & 0 deletions client/src/lib/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,14 @@ export const extractUsername = (email: string): string | null => {
const match = email.match(emailMatch);
return match ? match[1] : null;
};

/**
* Extracts the collabID from the user sockeetID.
*/
export const extractCollabID = (username: string) => {
const index = username.indexOf('-');
if (index !== -1) {
return username.substring(index + 1);
}
return null;
};
3 changes: 1 addition & 2 deletions client/src/stores/AuthStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { create } from 'zustand';
import { SetState } from './types';
import { createStoreWithSelectors } from './utils';
import { generateRandId } from '@/lib/bytes';

/**
* Define Global Auth states and reducers
Expand Down Expand Up @@ -55,7 +54,7 @@ const setUser =
userLastName,
// The random id allows the same user to login to different
// clients, helpful for tests but not irl.
userEmail: `${userEmail}-${generateRandId()}`,
userEmail: userEmail ?? ' ',
userPicture,
userID,
};
Expand Down
Loading

0 comments on commit 4d7aa6c

Please sign in to comment.