Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
johannesbrandenburger committed May 8, 2024
2 parents 25a7b6a + 6887589 commit 6c2153f
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 59 deletions.
30 changes: 30 additions & 0 deletions inputtool/app/courses/[courseId]/feedbackform/[formId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,36 @@ export default function FeedbackFormPage({ params }: { params: { courseId: strin
setUserChangedOrder(true);
}


// save on page leave
useEffect(() => {
const handleBeforeUnload = async (e: BeforeUnloadEvent) => {
if (userChangedSomething) {
e.preventDefault();
await save();
toast.info("Saved. (You should give the app a few seconds to save your changes next time.)");
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [userChangedSomething, save]);

// direct save
useEffect(() => {
const handleSave = async (e: KeyboardEvent) => {
if (e.key === "s" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
save();
}
};
document.addEventListener("keydown", handleSave);
return () => {
document.removeEventListener("keydown", handleSave);
};
}, [save]);

return (
<div className="flex flex-col items-center justify-center h-max m-4">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,35 @@ export default function FeedbackQuestionPage({ params }: { params: { courseId: s
}, [save, userChangedSomething]);


// save on page leave
useEffect(() => {
const handleBeforeUnload = async (e: BeforeUnloadEvent) => {
if (userChangedSomething) {
e.preventDefault();
await save();
toast.info("Saved. (You should give the app a few seconds to save your changes next time.)");
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [userChangedSomething, save]);

// direct save
useEffect(() => {
const handleSave = async (e: KeyboardEvent) => {
if (e.key === "s" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
save();
}
};
document.addEventListener("keydown", handleSave);
return () => {
document.removeEventListener("keydown", handleSave);
};
}, [save]);

return (
<div className="flex flex-col items-center justify-center h-max m-4">

Expand Down
30 changes: 30 additions & 0 deletions inputtool/app/courses/[courseId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,36 @@ export default function CoursePage({ params }: { params: { courseId: string } })
};
}, [save, userChangedSomething]);


// save on page leave
useEffect(() => {
const handleBeforeUnload = async (e: BeforeUnloadEvent) => {
if (userChangedSomething) {
e.preventDefault();
await save();
toast.info("Saved. (You should give the app a few seconds to save your changes next time.)");
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [userChangedSomething, save]);

// direct save
useEffect(() => {
const handleSave = async (e: KeyboardEvent) => {
if (e.key === "s" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
save();
}
};
document.addEventListener("keydown", handleSave);
return () => {
document.removeEventListener("keydown", handleSave);
};
}, [save]);

return (
<div className="flex flex-col items-center justify-center h-max m-4">

Expand Down
30 changes: 30 additions & 0 deletions inputtool/app/courses/[courseId]/quizform/[formId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,36 @@ export default function QuizFormPage({ params }: { params: { courseId: string, f
setUserChangedOrder(true);
}


// save on page leave
useEffect(() => {
const handleBeforeUnload = async (e: BeforeUnloadEvent) => {
if (userChangedSomething) {
e.preventDefault();
await save();
toast.info("Saved. (You should give the app a few seconds to save your changes next time.)");
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [userChangedSomething, save]);

// direct save
useEffect(() => {
const handleSave = async (e: KeyboardEvent) => {
if (e.key === "s" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
save();
}
};
document.addEventListener("keydown", handleSave);
return () => {
document.removeEventListener("keydown", handleSave);
};
}, [save]);

return (
<div className="flex flex-col items-center justify-center h-max m-4">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,34 @@ export default function QuizQuestionPage({ params }: { params: { courseId: strin
};
}, [save, userChangedSomething]);

// save on page leave
useEffect(() => {
const handleBeforeUnload = async (e: BeforeUnloadEvent) => {
if (userChangedSomething) {
e.preventDefault();
await save();
toast.info("Saved. (You should give the app a few seconds to save your changes next time.)");
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [userChangedSomething, save]);

// direct save
useEffect(() => {
const handleSave = async (e: KeyboardEvent) => {
if (e.key === "s" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
save();
}
};
document.addEventListener("keydown", handleSave);
return () => {
document.removeEventListener("keydown", handleSave);
};
}, [save]);

return (
<div className="flex flex-col items-center justify-center h-max m-4">
Expand Down Expand Up @@ -259,61 +287,65 @@ export default function QuizQuestionPage({ params }: { params: { courseId: strin
</SelectItem>
</SelectContent>
</Select>
<Label className="mt-2">Correct Answers</Label>
<div className="flex gap-4">
<Checkbox
checked={quizQuestion?.hasCorrectAnswers}
onCheckedChange={(checked) => {
checked = checked as boolean || false;
setQuizQuestion({
...quizQuestion,
hasCorrectAnswers: checked
});
setUserChangedSomething(true);
}}
/>
<Label>Has Correct Answers</Label>
<div className="mt-2 flex gap-4 items-center">
<Label>Has Correct Answers</Label>
<Checkbox
checked={quizQuestion?.hasCorrectAnswers}
onCheckedChange={(checked) => {
checked = checked as boolean || false;
setQuizQuestion({
...quizQuestion,
hasCorrectAnswers: checked
});
setUserChangedSomething(true);
}}
/>
</div>

{/* if yes/no -> display checkboxes for yes and no */}
{quizQuestion?.type === "YES_NO" && quizQuestion?.hasCorrectAnswers && (
<div className="flex gap-4">
<Checkbox
checked={quizQuestion?.correctAnswers?.includes("yes")}
onCheckedChange={(checked) => {
checked = checked as boolean || false;
let correctAnswers = quizQuestion?.correctAnswers || [];
if (checked) {
correctAnswers.push("yes");
} else {
correctAnswers = correctAnswers.filter(a => a !== "yes");
}
setQuizQuestion({
...quizQuestion,
correctAnswers: correctAnswers
});
setUserChangedSomething(true);
}}
/>
<Label>Yes</Label>
<Checkbox
checked={quizQuestion?.correctAnswers?.includes("no")}
onCheckedChange={(checked) => {
checked = checked as boolean || false;
let correctAnswers = quizQuestion?.correctAnswers || [];
if (checked) {
correctAnswers.push("no");
} else {
correctAnswers = correctAnswers.filter(a => a !== "no");
}
setQuizQuestion({
...quizQuestion,
correctAnswers: correctAnswers
});
setUserChangedSomething(true);
}}
/>
<Label>No</Label>
<div className="flex gap-4 items-center bg-gray-100 p-4 rounded-md">
<div className="flex gap-4 items-center">
<Checkbox
checked={quizQuestion?.correctAnswers?.includes("yes")}
onCheckedChange={(checked) => {
checked = checked as boolean || false;
let correctAnswers = quizQuestion?.correctAnswers || [];
if (checked) {
correctAnswers.push("yes");
} else {
correctAnswers = correctAnswers.filter(a => a !== "yes");
}
setQuizQuestion({
...quizQuestion,
correctAnswers: correctAnswers
});
setUserChangedSomething(true);
}}
/>
<Label>Yes</Label>
</div>
<div className="flex gap-4 items-center">

<Checkbox
checked={quizQuestion?.correctAnswers?.includes("no")}
onCheckedChange={(checked) => {
checked = checked as boolean || false;
let correctAnswers = quizQuestion?.correctAnswers || [];
if (checked) {
correctAnswers.push("no");
} else {
correctAnswers = correctAnswers.filter(a => a !== "no");
}
setQuizQuestion({
...quizQuestion,
correctAnswers: correctAnswers
});
setUserChangedSomething(true);
}}
/>
<Label>No</Label>
</div>
</div>
)}
</CardContent>
Expand Down Expand Up @@ -460,8 +492,8 @@ export default function QuizQuestionPage({ params }: { params: { courseId: strin

</TableCell>

<TableCell>
{quizQuestion?.hasCorrectAnswers && (
{quizQuestion?.hasCorrectAnswers && (
<TableCell>
<Checkbox
checked={quizQuestion?.correctAnswers?.includes(index.toString())}
onCheckedChange={(checked) => {
Expand All @@ -485,8 +517,8 @@ export default function QuizQuestionPage({ params }: { params: { courseId: strin
setUserChangedSomething(true);
}}
/>
)}
</TableCell>
</TableCell>
)}

<TableCell>
<Button
Expand Down
15 changes: 12 additions & 3 deletions inputtool/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@radix-ui/react-dropdown-menu";
import { Label, Separator } from "@radix-ui/react-dropdown-menu";
import { useRouter } from 'next/navigation'
import { useState, useEffect } from "react";
import { Loader2 } from 'lucide-react';
import { hasValidJwtToken, login } from "@/lib/utils";
import HtwgPattern from "@/public/htwg-pattern";
import HtwgConnectLogo from "@/public/htwg-connect-logo";


export default function Home() {
Expand Down Expand Up @@ -47,15 +48,23 @@ export default function Home() {
<div className="flex flex-col items-center justify-center h-screen">
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Login</CardTitle>
<div className="flex items-center">
<HtwgConnectLogo className="m-5" style={{ height: '100px', width: '100px' }} />
<div className="row">
<span className="font-extrabold text-primary text-xl block" >HTWG Connect</span>
<span className="font-bold text-lg block" >Input Tool</span>
</div>
</div>
<Separator className="my-5"/>
<CardTitle className="text-center font-bold">Login</CardTitle>
</CardHeader>
<CardContent>
<Label>HTWG-Username</Label>
<Input autoFocus type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="jo871bra" />
<Label className="mt-2">Password</Label>
<Input type="password" value={password} onChange={(e) => setPassword(e.target.value)} onSubmit={handleLogin} />
<Button
className="mt-4"
className="mt-4 w-full"
onClick={handleLogin}
disabled={!username}
>{loading ? <Loader2 className="w-6 h-6 animate-spin" /> : "Login"}</Button>
Expand Down
7 changes: 6 additions & 1 deletion inputtool/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ export function cn(...inputs: ClassValue[]) {
}

export async function hasValidJwtToken(): Promise<boolean> {
const jwtToken = localStorage?.getItem("jwtToken");

if (typeof window === 'undefined') {
return false;
}

const jwtToken = localStorage ? localStorage.getItem("jwtToken") : null;
if (!jwtToken) {
return false;
}
Expand Down
Loading

0 comments on commit 6c2153f

Please sign in to comment.