diff --git a/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx b/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx
index 1c44e04..c2666af 100644
--- a/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx
+++ b/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx
@@ -27,16 +27,14 @@ export default function EditLecture({ lectureDay }: { lectureDay: string }) {
.flatMap(({ lectures }) => lectures.map((lecture) => lecture))
.find((l) => l.date === lectureDay);
- const serverVersionOfText = getLectureTextOrDefault(lecture, lectureDay);
+ const startingText = getLectureTextOrDefault(lecture, lectureDay);
- const [text, setText] = useState(serverVersionOfText);
+ const [text, setText] = useState(startingText);
const [updateMonacoKey, setUpdateMonacoKey] = useState(1);
const [error, setError] = useState("");
const [clientDataUpdatedAt, setClientDataUpdatedAt] =
useState(serverDataUpdatedAt);
- const clientIsAuthoritative = serverDataUpdatedAt <= clientDataUpdatedAt;
- console.log("client it authoritative", clientIsAuthoritative);
const textUpdate = useCallback((t: string) => {
setText(t);
@@ -45,6 +43,9 @@ export default function EditLecture({ lectureDay }: { lectureDay: string }) {
useEffect(() => {
const delay = 500;
+ const clientIsAuthoritative = serverDataUpdatedAt <= clientDataUpdatedAt;
+ console.log("client is authoritative", clientIsAuthoritative);
+
const handler = setTimeout(() => {
try {
const parsed = parseLecture(text);
@@ -75,15 +76,7 @@ export default function EditLecture({ lectureDay }: { lectureDay: string }) {
return () => {
clearTimeout(handler);
};
- }, [
- clientIsAuthoritative,
- courseName,
- lecture,
- settings,
- text,
- textUpdate,
- updateLecture,
- ]);
+ }, [courseName, lecture, settings, text, textUpdate, updateLecture]);
return (
diff --git a/nextjs/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx b/nextjs/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx
index b5a97dd..b0bc08b 100644
--- a/nextjs/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx
+++ b/nextjs/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx
@@ -8,7 +8,7 @@ import {
LocalAssignment,
localAssignmentMarkdown,
} from "@/models/local/assignment/localAssignment";
-import { useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import AssignmentPreview from "./AssignmentPreview";
import { getModuleItemUrl } from "@/services/urlUtils";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
@@ -26,38 +26,35 @@ export default function EditAssignment({
}: {
assignmentName: string;
moduleName: string;
-}) {
- const [_, {dataUpdatedAt}] = useAssignmentQuery(moduleName, assignmentName);
- return (
-
- );
-}
-export function InnerEditAssignment({
- moduleName,
- assignmentName,
-}: {
- assignmentName: string;
- moduleName: string;
}) {
const router = useRouter();
const { courseName } = useCourseContext();
const [settings] = useLocalCourseSettingsQuery();
- const [assignment] = useAssignmentQuery(moduleName, assignmentName);
+ const [assignment, { dataUpdatedAt: serverDataUpdatedAt }] =
+ useAssignmentQuery(moduleName, assignmentName);
const updateAssignment = useUpdateAssignmentMutation();
const [assignmentText, setAssignmentText] = useState(
localAssignmentMarkdown.toMarkdown(assignment)
);
+ const [updateMonacoKey, setUpdateMonacoKey] = useState(1);
+ const [clientDataUpdatedAt, setClientDataUpdatedAt] =
+ useState(serverDataUpdatedAt);
+
+ const textUpdate = useCallback((t: string) => {
+ setAssignmentText(t);
+ setClientDataUpdatedAt(Date.now());
+ }, []);
+
const [error, setError] = useState("");
const [showHelp, setShowHelp] = useState(false);
useEffect(() => {
const delay = 500;
+ const clientIsAuthoritative = serverDataUpdatedAt <= clientDataUpdatedAt;
+ console.log("client is authoritative", clientIsAuthoritative);
+
const handler = setTimeout(() => {
try {
const updatedAssignment: LocalAssignment =
@@ -66,27 +63,35 @@ export function InnerEditAssignment({
localAssignmentMarkdown.toMarkdown(assignment) !==
localAssignmentMarkdown.toMarkdown(updatedAssignment)
) {
- console.log("updating assignment");
- updateAssignment
- .mutateAsync({
- assignment: updatedAssignment,
- moduleName,
- assignmentName: updatedAssignment.name,
- previousModuleName: moduleName,
- previousAssignmentName: assignmentName,
- courseName,
- })
- .then(() => {
- if (updatedAssignment.name !== assignmentName)
- router.replace(
- getModuleItemUrl(
- courseName,
- moduleName,
- "assignment",
- updatedAssignment.name
- )
- );
- });
+ if (clientIsAuthoritative) {
+ console.log("updating assignment");
+ updateAssignment
+ .mutateAsync({
+ assignment: updatedAssignment,
+ moduleName,
+ assignmentName: updatedAssignment.name,
+ previousModuleName: moduleName,
+ previousAssignmentName: assignmentName,
+ courseName,
+ })
+ .then(() => {
+ if (updatedAssignment.name !== assignmentName)
+ router.replace(
+ getModuleItemUrl(
+ courseName,
+ moduleName,
+ "assignment",
+ updatedAssignment.name
+ )
+ );
+ });
+ } else {
+ console.log(
+ "client not authoritative, updating client with server data"
+ );
+ textUpdate(localAssignmentMarkdown.toMarkdown(assignment));
+ setUpdateMonacoKey((k) => k + 1);
+ }
}
setError("");
} catch (e: any) {
@@ -116,7 +121,11 @@ export function InnerEditAssignment({
)}
-
+
{error && error}
diff --git a/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx b/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx
index 22722a6..ec2cde3 100644
--- a/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx
+++ b/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx
@@ -1,7 +1,7 @@
"use client";
import { MonacoEditor } from "@/components/editor/MonacoEditor";
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
-import { useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import QuizPreview from "./QuizPreview";
import { QuizButtons } from "./QuizButton";
import ClientOnly from "@/components/ClientOnly";
@@ -62,7 +62,7 @@ export default function EditQuiz({
quizName: string;
moduleName: string;
}) {
- const [_, {dataUpdatedAt}] = useQuizQuery(moduleName, quizName);
+ const [_, { dataUpdatedAt }] = useQuizQuery(moduleName, quizName);
return (
{
+ setQuizText(t);
+ setClientDataUpdatedAt(Date.now());
+ }, []);
+
useEffect(() => {
const delay = 1000;
+ const clientIsAuthoritative = serverDataUpdatedAt <= clientDataUpdatedAt;
+ console.log("client is authoritative", clientIsAuthoritative);
+
const handler = setTimeout(async () => {
try {
- console.log("checking if the same...");
if (
quizMarkdownUtils.toMarkdown(quiz) !==
quizMarkdownUtils.toMarkdown(
quizMarkdownUtils.parseMarkdown(quizText)
)
) {
- const updatedQuiz = quizMarkdownUtils.parseMarkdown(quizText);
- updateQuizMutation
- .mutateAsync({
- quiz: updatedQuiz,
- moduleName,
- quizName: updatedQuiz.name,
- previousModuleName: moduleName,
- previousQuizName: quizName,
- courseName,
- })
- .then(() => {
- if (updatedQuiz.name !== quizName)
- router.replace(
- getModuleItemUrl(
- courseName,
- moduleName,
- "quiz",
- updatedQuiz.name
- )
- );
- });
+ if (clientIsAuthoritative) {
+ const updatedQuiz = quizMarkdownUtils.parseMarkdown(quizText);
+ await updateQuizMutation
+ .mutateAsync({
+ quiz: updatedQuiz,
+ moduleName,
+ quizName: updatedQuiz.name,
+ previousModuleName: moduleName,
+ previousQuizName: quizName,
+ courseName,
+ })
+ .then(() => {
+ if (updatedQuiz.name !== quizName)
+ router.replace(
+ getModuleItemUrl(
+ courseName,
+ moduleName,
+ "quiz",
+ updatedQuiz.name
+ )
+ );
+ });
+ } else {
+ console.log(
+ "client not authoritative, updating client with server data"
+ );
+ textUpdate(quizMarkdownUtils.toMarkdown(quiz));
+ setUpdateMonacoKey((k) => k + 1);
+ }
}
setError("");
} catch (e: any) {
@@ -129,15 +151,19 @@ export function InnerEditQuiz({
clearTimeout(handler);
};
}, [
+ clientDataUpdatedAt,
courseName,
moduleName,
quiz,
quizName,
quizText,
router,
+ serverDataUpdatedAt,
+ textUpdate,
updateQuizMutation,
]);
+ console.log("updateMonacoKey", updateMonacoKey);
return (
@@ -147,7 +173,11 @@ export function InnerEditQuiz({
)}
-
+