mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
server websockets
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
MAJOR_VERSION="2"
|
MAJOR_VERSION="2"
|
||||||
MINOR_VERSION="2"
|
MINOR_VERSION="3"
|
||||||
VERSION="$MAJOR_VERSION.$MINOR_VERSION"
|
VERSION="$MAJOR_VERSION.$MINOR_VERSION"
|
||||||
|
|
||||||
docker build -t canvas_management:$VERSION .
|
docker build -t canvas_management:$VERSION .
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { MonacoEditor } from "@/components/editor/MonacoEditor";
|
import { MonacoEditor } from "@/components/editor/MonacoEditor";
|
||||||
import { useLecturesSuspenseQuery, useLectureUpdateMutation } from "@/hooks/localCourse/lectureHooks";
|
import {
|
||||||
|
useLecturesSuspenseQuery,
|
||||||
|
useLectureUpdateMutation,
|
||||||
|
} from "@/hooks/localCourse/lectureHooks";
|
||||||
import {
|
import {
|
||||||
lectureToString,
|
lectureToString,
|
||||||
parseLecture,
|
parseLecture,
|
||||||
@@ -10,11 +13,16 @@ import { useEffect, useState } from "react";
|
|||||||
import LecturePreview from "./LecturePreview";
|
import LecturePreview from "./LecturePreview";
|
||||||
import EditLectureTitle from "./EditLectureTitle";
|
import EditLectureTitle from "./EditLectureTitle";
|
||||||
import LectureButtons from "./LectureButtons";
|
import LectureButtons from "./LectureButtons";
|
||||||
import { trpc } from "@/services/trpc/utils";
|
|
||||||
import { useCourseContext } from "../../context/courseContext";
|
import { useCourseContext } from "../../context/courseContext";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
|
|
||||||
export default function EditLecture({ lectureDay }: { lectureDay: string }) {
|
export default function EditLecture({ lectureDay }: { lectureDay: string }) {
|
||||||
|
const [_, {dataUpdatedAt}] = useLecturesSuspenseQuery();
|
||||||
|
return (
|
||||||
|
<InnerEditLecture key={dataUpdatedAt} lectureDay={lectureDay} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export function InnerEditLecture({ lectureDay }: { lectureDay: string }) {
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
const [settings] = useLocalCourseSettingsQuery();
|
const [settings] = useLocalCourseSettingsQuery();
|
||||||
const [weeks] = useLecturesSuspenseQuery();
|
const [weeks] = useLecturesSuspenseQuery();
|
||||||
|
|||||||
@@ -26,6 +26,22 @@ export default function EditAssignment({
|
|||||||
}: {
|
}: {
|
||||||
assignmentName: string;
|
assignmentName: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
|
}) {
|
||||||
|
const [_, {dataUpdatedAt}] = useAssignmentQuery(moduleName, assignmentName);
|
||||||
|
return (
|
||||||
|
<InnerEditAssignment
|
||||||
|
key={dataUpdatedAt}
|
||||||
|
assignmentName={assignmentName}
|
||||||
|
moduleName={moduleName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export function InnerEditAssignment({
|
||||||
|
moduleName,
|
||||||
|
assignmentName,
|
||||||
|
}: {
|
||||||
|
assignmentName: string;
|
||||||
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
|
|||||||
@@ -21,10 +21,28 @@ export default function EditPage({
|
|||||||
}: {
|
}: {
|
||||||
pageName: string;
|
pageName: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
|
}) {
|
||||||
|
const [_, { dataUpdatedAt }] = usePageQuery(moduleName, pageName);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InnerEditPage
|
||||||
|
key={dataUpdatedAt}
|
||||||
|
pageName={pageName}
|
||||||
|
moduleName={moduleName}
|
||||||
|
></InnerEditPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InnerEditPage({
|
||||||
|
moduleName,
|
||||||
|
pageName,
|
||||||
|
}: {
|
||||||
|
pageName: string;
|
||||||
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
const [page] = usePageQuery(moduleName, pageName);
|
const [page, pageQuery] = usePageQuery(moduleName, pageName);
|
||||||
const updatePage = useUpdatePageMutation();
|
const updatePage = useUpdatePageMutation();
|
||||||
const [pageText, setPageText] = useState(
|
const [pageText, setPageText] = useState(
|
||||||
localPageMarkdownUtils.toMarkdown(page)
|
localPageMarkdownUtils.toMarkdown(page)
|
||||||
@@ -32,6 +50,10 @@ export default function EditPage({
|
|||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [settings] = useLocalCourseSettingsQuery();
|
const [settings] = useLocalCourseSettingsQuery();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("page data updated on sever", pageQuery.dataUpdatedAt);
|
||||||
|
}, [pageQuery.dataUpdatedAt]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const delay = 500;
|
const delay = 500;
|
||||||
const handler = setTimeout(() => {
|
const handler = setTimeout(() => {
|
||||||
|
|||||||
@@ -61,6 +61,22 @@ export default function EditQuiz({
|
|||||||
}: {
|
}: {
|
||||||
quizName: string;
|
quizName: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
|
}) {
|
||||||
|
const [_, {dataUpdatedAt}] = useQuizQuery(moduleName, quizName);
|
||||||
|
return (
|
||||||
|
<InnerEditQuiz
|
||||||
|
key={dataUpdatedAt}
|
||||||
|
quizName={quizName}
|
||||||
|
moduleName={moduleName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export function InnerEditQuiz({
|
||||||
|
moduleName,
|
||||||
|
quizName,
|
||||||
|
}: {
|
||||||
|
quizName: string;
|
||||||
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import { trpc } from "@/services/trpc/utils";
|
||||||
import { io, Socket } from 'socket.io-client';
|
import React, { useEffect } from "react";
|
||||||
|
import { io, Socket } from "socket.io-client";
|
||||||
|
|
||||||
interface ServerToClientEvents {
|
interface ServerToClientEvents {
|
||||||
message: (data: string) => void;
|
message: (data: string) => void;
|
||||||
@@ -12,28 +13,106 @@ interface ClientToServerEvents {
|
|||||||
sendMessage: (data: string) => void;
|
sendMessage: (data: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io('/');
|
const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io("/");
|
||||||
|
|
||||||
|
function removeFileExtension(fileName: string): string {
|
||||||
|
const lastDotIndex = fileName.lastIndexOf(".");
|
||||||
|
if (lastDotIndex > 0) {
|
||||||
|
return fileName.substring(0, lastDotIndex);
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
export function ClientCacheInvalidation() {
|
export function ClientCacheInvalidation() {
|
||||||
|
const utils = trpc.useUtils();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
socket.on('message', (data) => {
|
socket.on("message", (data) => {
|
||||||
console.log('Received message:', data);
|
console.log("Received message:", data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('fileChanged', (filePath) => {
|
socket.on("fileChanged", (filePath) => {
|
||||||
console.log('File changed:', filePath);
|
const [courseName, moduleOrLectures, itemType, itemFile] =
|
||||||
|
filePath.split("/");
|
||||||
|
|
||||||
|
const itemName = removeFileExtension(itemFile);
|
||||||
|
|
||||||
|
const allParts = [courseName, moduleOrLectures, itemType, itemName];
|
||||||
|
|
||||||
|
if (moduleOrLectures === "settings.yml") {
|
||||||
|
utils.settings.allCoursesSettings.invalidate();
|
||||||
|
utils.settings.courseSettings.invalidate({ courseName });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moduleOrLectures === "00 - lectures") {
|
||||||
|
console.log("lecture updated on FS ", allParts);
|
||||||
|
utils.lectures.getLectures.invalidate({ courseName });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemType === "assignments") {
|
||||||
|
console.log("assignment updated on FS ", allParts);
|
||||||
|
utils.assignment.getAllAssignments.invalidate({
|
||||||
|
courseName,
|
||||||
|
moduleName: moduleOrLectures,
|
||||||
|
});
|
||||||
|
utils.assignment.getAssignment.invalidate({
|
||||||
|
courseName,
|
||||||
|
moduleName: moduleOrLectures,
|
||||||
|
assignmentName: itemName,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemType === "quizzes") {
|
||||||
|
console.log("quiz updated on FS ", allParts);
|
||||||
|
utils.quiz.getAllQuizzes.invalidate({
|
||||||
|
courseName,
|
||||||
|
moduleName: moduleOrLectures,
|
||||||
|
});
|
||||||
|
utils.quiz.getQuiz.invalidate({
|
||||||
|
courseName,
|
||||||
|
moduleName: moduleOrLectures,
|
||||||
|
quizName: itemName,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemType === "pages") {
|
||||||
|
console.log("page updated on FS ", allParts);
|
||||||
|
utils.page.getAllPages.invalidate({
|
||||||
|
courseName,
|
||||||
|
moduleName: moduleOrLectures,
|
||||||
|
});
|
||||||
|
utils.page.getPage.invalidate({
|
||||||
|
courseName,
|
||||||
|
moduleName: moduleOrLectures,
|
||||||
|
pageName: itemName,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('connect_error', (error) => {
|
socket.on("connect_error", (error) => {
|
||||||
console.error('Connection error:', error);
|
console.error("Connection error:", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.off('message');
|
socket.off("message");
|
||||||
socket.off('fileChanged');
|
socket.off("fileChanged");
|
||||||
socket.off('connect_error');
|
socket.off("connect_error");
|
||||||
};
|
};
|
||||||
}, []);
|
}, [
|
||||||
|
utils.assignment.getAllAssignments,
|
||||||
|
utils.assignment.getAssignment,
|
||||||
|
utils.lectures.getLectures,
|
||||||
|
utils.page.getAllPages,
|
||||||
|
utils.page.getPage,
|
||||||
|
utils.quiz.getAllQuizzes,
|
||||||
|
utils.quiz.getQuiz,
|
||||||
|
utils.settings.allCoursesSettings,
|
||||||
|
utils.settings.courseSettings,
|
||||||
|
]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const port = 3000;
|
|||||||
const app = next({ dev, hostname, port });
|
const app = next({ dev, hostname, port });
|
||||||
const handler = app.getRequestHandler();
|
const handler = app.getRequestHandler();
|
||||||
|
|
||||||
const folderToWatch = path.join(process.cwd(), "./storage");
|
const folderToWatch = path.join(process.cwd(), "./storage", "/");
|
||||||
console.log("watching folder", folderToWatch);
|
console.log("watching folder", folderToWatch);
|
||||||
|
|
||||||
app.prepare().then(() => {
|
app.prepare().then(() => {
|
||||||
@@ -23,21 +23,14 @@ app.prepare().then(() => {
|
|||||||
|
|
||||||
io.on("connection", (socket) => {
|
io.on("connection", (socket) => {
|
||||||
console.log("websocket connection created");
|
console.log("websocket connection created");
|
||||||
|
|
||||||
// Define a change event handler
|
|
||||||
const changeHandler = (filePath) => {
|
const changeHandler = (filePath) => {
|
||||||
const relativePath = filePath.replace(folderToWatch, "")
|
const relativePath = filePath.replace(folderToWatch, "");
|
||||||
console.log(`Sending file changed websocket message: ${relativePath}`);
|
console.log(`Sending file changed websocket message: ${relativePath}`);
|
||||||
|
|
||||||
|
socket.emit("fileChanged", relativePath);
|
||||||
|
|
||||||
socket.emit("fileChanged", `File changed: ${filePath}`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attach the change event handler
|
|
||||||
watcher.on("change", changeHandler);
|
watcher.on("change", changeHandler);
|
||||||
|
|
||||||
// Clean up the change event handler when the client disconnects
|
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
console.log("Client disconnected");
|
console.log("Client disconnected");
|
||||||
watcher.off("change", changeHandler); // Remove the event listener
|
watcher.off("change", changeHandler); // Remove the event listener
|
||||||
|
|||||||
Reference in New Issue
Block a user