Skip to content

Commit 911a523

Browse files
committedJan 5, 2025·
Set Loading JSON Data from Database Function
1 parent 4c7e02f commit 911a523

File tree

5 files changed

+172
-16
lines changed

5 files changed

+172
-16
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { databases } from "@/backend/configs/configs";
2+
3+
4+
export async function updateFileData(
5+
fileId: string,
6+
fileData: string,
7+
fileLatestEditor: string,
8+
) {
9+
10+
const res = await databases.updateDocument(
11+
`${import.meta.env.VITE_DATABASES_MAIN}`,
12+
`${import.meta.env.VITE_COLL_DOCS}`,
13+
`${fileId}`,
14+
{ fileData: fileData, fileLatestEditor: fileLatestEditor }
15+
).then((response) => {
16+
console.log(response)
17+
return true
18+
}).catch((err) => {
19+
console.log(err)
20+
return false
21+
})
22+
23+
return res
24+
}

‎src/components/canvas/Canvas.tsx

+119-12
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ import { useEffect, useRef, useState } from 'react';
22
import Konva from 'konva';
33

44
// STORES
5-
import { useTools } from '@/stores';
5+
import { useFileDetails, useTools, useUserDataStore } from '@/stores';
66
import { useCanvasStore } from '@/stores';
7+
import useIsSaving from '@/stores/footer/useIsSaving';
8+
9+
// SERVICES
10+
import { updateFileData } from '@/backend/services/files/updateFileData';
11+
712

813
export default function Canvas() {
14+
915
const [isCanvasReady, setIsCanvasReady] = useState(false);
1016

1117
// Refs for stage and layer
@@ -16,7 +22,17 @@ export default function Canvas() {
1622
const [selectedObject, setSelectedObject] = useState<Konva.Shape | null>(null);
1723

1824
// State to store the JSON data of the canvas
19-
const { setJsonData } = useCanvasStore();
25+
const { jsonData, setJsonData } = useCanvasStore();
26+
27+
// Get user details from store
28+
const { userData } = useUserDataStore();
29+
30+
// Get file details from store
31+
const { fileDetails } = useFileDetails();
32+
33+
// Check on the saving status
34+
const { setIsSaving } = useIsSaving();
35+
2036

2137
const {
2238
// Add Text
@@ -55,6 +71,65 @@ export default function Canvas() {
5571
setVideoUrl,
5672
} = useTools();
5773

74+
// Function to load images and videos from URLs
75+
const loadAssets = (node: Konva.Node) => {
76+
if (node.getClassName() === 'Image') {
77+
// Handle images
78+
const imageUrl = node.getAttr('imageUrl');
79+
if (imageUrl) {
80+
const image = new window.Image();
81+
image.src = imageUrl;
82+
image.onload = () => {
83+
node.setAttr('image', image); // Set the loaded image
84+
node.getLayer()?.batchDraw(); // Redraw the layer
85+
};
86+
}
87+
88+
// Handle videos
89+
const videoUrl = node.getAttr('videoUrl');
90+
if (videoUrl) {
91+
const video = document.createElement('video');
92+
video.src = videoUrl;
93+
video.autoplay = true;
94+
video.loop = true;
95+
video.muted = false; // Ensure the video is muted for autoplay
96+
97+
video.onloadeddata = () => {
98+
node.setAttr('image', video); // Set the video as the image
99+
node.getLayer()?.batchDraw(); // Redraw the layer
100+
101+
// Restore playback state
102+
const isPlaying = node.getAttr('isPlaying');
103+
if (isPlaying) {
104+
video.play();
105+
} else {
106+
video.pause();
107+
}
108+
109+
// Add click event to toggle play/pause
110+
node.on('click', () => {
111+
if (video.paused) {
112+
video.play();
113+
} else {
114+
video.pause();
115+
}
116+
node.getLayer()?.batchDraw();
117+
});
118+
119+
// Start the video frame update loop
120+
const updateVideoFrame = () => {
121+
node.setAttr('image', video);
122+
node.getLayer()?.batchDraw();
123+
requestAnimationFrame(updateVideoFrame);
124+
};
125+
126+
updateVideoFrame();
127+
};
128+
}
129+
}
130+
};
131+
132+
58133
// Initialize Konva stage and layer
59134
useEffect(() => {
60135
const stage = new Konva.Stage({
@@ -64,22 +139,28 @@ export default function Canvas() {
64139
});
65140
const layer = new Konva.Layer();
66141

67-
// Add a pointer cursor to the every shape on the layer
68-
layer.on('mouseover', (e) => {
69-
const shape = e.target;
70-
document.body.style.cursor = 'pointer';
71-
shape.on('mouseout', () => {
72-
document.body.style.cursor = 'default';
73-
});
74-
});
75-
76142
// Add layer to the stage
77143
stage.add(layer);
78144

79145
// Save stage and layer in refs
80146
stageRef.current = stage;
81147
layerRef.current = layer;
82148

149+
// Load JSON data if it exists
150+
if (jsonData) {
151+
const loadedStage = Konva.Node.create(jsonData, 'container') as Konva.Stage;
152+
stageRef.current = loadedStage;
153+
layerRef.current = loadedStage.getLayers()[0];
154+
155+
// Add event listeners and load assets for all nodes
156+
loadedStage.getLayers().forEach((layer) => {
157+
layer.getChildren().forEach((node) => {
158+
addEventListeners(node);
159+
loadAssets(node); // Load images and videos
160+
});
161+
});
162+
}
163+
83164
setIsCanvasReady(true);
84165
}, []);
85166

@@ -349,7 +430,7 @@ export default function Canvas() {
349430
video.src = `${videoUrl}`;
350431
video.autoplay = true;
351432
video.loop = true;
352-
// video.muted = true;
433+
video.muted = false;
353434
video.onloadeddata = () => {
354435
const myVideo = new Konva.Image({
355436
x: 50,
@@ -488,6 +569,32 @@ export default function Canvas() {
488569
};
489570
}, [selectedObject]);
490571

572+
573+
// Update the JSON Data
574+
function sentDataToBackend() {
575+
setIsSaving(true);
576+
setTimeout(async () => {
577+
await updateFileData(
578+
fileDetails?.$id,
579+
jsonData,
580+
userData?.name
581+
).then((res) => {
582+
if (res === true) {
583+
setIsSaving(false);
584+
} else if (res === false) {
585+
console.log('Error while updating the file', res)
586+
setIsSaving(false);
587+
}
588+
})
589+
}, 5000)
590+
}
591+
592+
useEffect(() => {
593+
sentDataToBackend();
594+
}, [jsonData]);
595+
596+
597+
491598
return (
492599
<div className="bg-white my-2 mx-auto pr-5 border-[1px] border-gray-200 min-h-[500px] w-[970px]">
493600
{/* Init canvas stage */}

‎src/components/common/Footer.tsx

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { useEffect } from "react";
2+
13
// ICONS
24
import { FcHighPriority } from "react-icons/fc";
35
import { FcOk } from "react-icons/fc";
@@ -13,6 +15,22 @@ export default function Footer() {
1315
// Check on the saving status
1416
const { isSaving } = useIsSaving();
1517

18+
useEffect(() => {
19+
const handleBeforeUnload = (event: { returnValue: string; }) => {
20+
if (isSaving) {
21+
const message = 'Data is still saving. Are you sure you want to leave?';
22+
event.returnValue = message; // Standard for most browsers
23+
return message; // For some older browsers
24+
}
25+
};
26+
27+
window.addEventListener('beforeunload', handleBeforeUnload);
28+
29+
return () => {
30+
window.removeEventListener('beforeunload', handleBeforeUnload);
31+
};
32+
}, [isSaving]);
33+
1634
return (
1735
<div className="bg-white font-normal text-gray-500 text-sm w-full z-50 m-0 border-t-[1px] border-gray-200 px-3 py-2 flex justify-between items-center">
1836

‎src/components/common/right-section/Settings.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export default function Settings() {
6969
setNewFileName(newFileName);
7070
setCurrentFileName(newFileName);
7171
setLoadingUpdateName(false);
72+
}).finally(() => {
73+
setNewFileName('');
7274
});
7375
};
7476

@@ -142,7 +144,7 @@ export default function Settings() {
142144
id="fileDeleteID"
143145
maxLength={20}
144146
onChange={(e) => setFileDeleteID(e.target.value)}
145-
placeholder="Enter file ID to delete"
147+
placeholder="Enter File Delete ID to continue"
146148
/>
147149
</div>
148150
<Separator />
@@ -196,6 +198,7 @@ export default function Settings() {
196198
<Input
197199
id="fileName"
198200
maxLength={25}
201+
value={newFileName}
199202
onChange={(e) => setNewFileName(e.target.value)}
200203
placeholder="Enter new file title"
201204
/>
@@ -205,7 +208,7 @@ export default function Settings() {
205208
<Button onClick={() => setShowDeleteAlert(true)} variant="destructive">
206209
Delete file
207210
</Button>
208-
<Button disabled={newFileName === '' || newFileName.trim().length === 0 || loadingUpdateName} className="min-w-[150px]" onClick={handleUpdateFileName}>
211+
<Button disabled={newFileName === '' || newFileName.length === 0 || newFileName.trim().length === 0 || loadingUpdateName} className="min-w-[150px]" onClick={handleUpdateFileName}>
209212
{loadingUpdateName ? (
210213
<LoadingState setWidth="28" />
211214
) : (

‎src/pages/Dashboard.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Canvas, LoadingState, Manage, Tools } from "@/components";
77
import { ScrollArea } from "@/components/ui/scroll-area"
88

99
// STORES
10-
import { useFileName, useFileDetails } from "@/stores";
10+
import { useFileName, useFileDetails, useCanvasStore } from "@/stores";
1111

1212
// SERVICES
1313
import { getFile } from "@/backend/services/files/getFile";
@@ -30,13 +30,17 @@ export default function Dashboard() {
3030
// Get the file name from the store
3131
const { currentFileName, setCurrentFileName } = useFileName();
3232

33+
// State to store the JSON data of the canvas
34+
const { setJsonData } = useCanvasStore();
35+
3336

3437
// Fetch the file details from the database
3538
async function getFileDetails() {
3639
await getFile(fileId as string)
3740
.then((res) => {
3841
setFileDetails(res);
3942
setCurrentFileName(res.fileName);
43+
setJsonData(res.fileData);
4044
}).finally(() => {
4145
setLoadingScreen(false);
4246
});
@@ -52,7 +56,7 @@ export default function Dashboard() {
5256
document.title = `${currentFileName === '' ? 'Loading...' : currentFileName} | Workspace`;
5357
}, [currentFileName]);
5458

55-
59+
5660

5761
// loading indicator
5862
if (loadingScreen) {

0 commit comments

Comments
 (0)
Please sign in to comment.