4 Commits

5 changed files with 40 additions and 13 deletions

3
.gitignore vendored
View File

@@ -43,4 +43,5 @@ next-env.d.ts
storage/ storage/
temp/ temp/
.claude/

View File

@@ -12,11 +12,13 @@ import {
useUpdateAssignmentInCanvasMutation, useUpdateAssignmentInCanvasMutation,
useDeleteAssignmentFromCanvasMutation, useDeleteAssignmentFromCanvasMutation,
useAddAssignmentToCanvasMutation, useAddAssignmentToCanvasMutation,
canvasAssignmentKeys,
} from "@/features/canvas/hooks/canvasAssignmentHooks"; } from "@/features/canvas/hooks/canvasAssignmentHooks";
import { useLocalCourseSettingsQuery } from "@/features/local/course/localCoursesHooks"; import { useLocalCourseSettingsQuery } from "@/features/local/course/localCoursesHooks";
import { baseCanvasUrl } from "@/features/canvas/services/canvasServiceUtils"; import { baseCanvasUrl } from "@/features/canvas/services/canvasServiceUtils";
import { useCourseContext } from "../../../context/courseContext"; import { useCourseContext } from "../../../context/courseContext";
import Modal, { ModalControl } from "@/components/Modal"; import Modal, { ModalControl } from "@/components/Modal";
import { useQueryClient } from "@tanstack/react-query";
function getDuplicateName(name: string, existingNames: string[]): string { function getDuplicateName(name: string, existingNames: string[]): string {
const match = name.match(/^(.*)\s+(\d+)$/); const match = name.match(/^(.*)\s+(\d+)$/);
@@ -34,6 +36,7 @@ export const AssignmentDayItemContextMenu: FC<{
item: IModuleItem; item: IModuleItem;
moduleName: string; moduleName: string;
}> = ({ modalControl, item, moduleName }) => { }> = ({ modalControl, item, moduleName }) => {
const queryClient = useQueryClient();
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const calendarItems = useCalendarItemsContext(); const calendarItems = useCalendarItemsContext();
const createAssignmentMutation = useCreateAssignmentMutation(); const createAssignmentMutation = useCreateAssignmentMutation();
@@ -68,6 +71,13 @@ export const AssignmentDayItemContextMenu: FC<{
}, [modalControl]); }, [modalControl]);
const handleClose = () => { const handleClose = () => {
for (let i = 1; i <= 8; i += 2) {
setTimeout(() => {
queryClient.invalidateQueries({
queryKey: canvasAssignmentKeys.assignments(settings.canvasId),
});
}, i * 1000);
}
setConfirmingDelete(false); setConfirmingDelete(false);
modalControl.closeModal(); modalControl.closeModal();
}; };
@@ -88,7 +98,11 @@ export const AssignmentDayItemContextMenu: FC<{
}; };
const handleDelete = () => { const handleDelete = () => {
deleteLocalMutation.mutate({ courseName, moduleName, assignmentName: item.name }); deleteLocalMutation.mutate({
courseName,
moduleName,
assignmentName: item.name,
});
handleClose(); handleClose();
}; };
@@ -133,11 +147,7 @@ export const AssignmentDayItemContextMenu: FC<{
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
{confirmingDelete ? ( {confirmingDelete ? (
<> <>
<div <div className={``}>Delete from disk?</div>
className={``}
>
Delete from disk?
</div>
<button <button
onClick={handleClose} onClick={handleClose}
className={`unstyled ${baseButtonClasses} ${normalButtonClass}`} className={`unstyled ${baseButtonClasses} ${normalButtonClass}`}

View File

@@ -6,6 +6,7 @@ import {
useAddAssignmentToCanvasMutation, useAddAssignmentToCanvasMutation,
useDeleteAssignmentFromCanvasMutation, useDeleteAssignmentFromCanvasMutation,
useUpdateAssignmentInCanvasMutation, useUpdateAssignmentInCanvasMutation,
canvasAssignmentKeys,
} from "@/features/canvas/hooks/canvasAssignmentHooks"; } from "@/features/canvas/hooks/canvasAssignmentHooks";
import { baseCanvasUrl } from "@/features/canvas/services/canvasServiceUtils"; import { baseCanvasUrl } from "@/features/canvas/services/canvasServiceUtils";
import { import {
@@ -19,6 +20,7 @@ import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import { useItemNavigation } from "../../../../hooks/useItemNavigation"; import { useItemNavigation } from "../../../../hooks/useItemNavigation";
import ItemNavigationButtons from "../../../../components/ItemNavigationButtons"; import ItemNavigationButtons from "../../../../components/ItemNavigationButtons";
import { useQueryClient } from "@tanstack/react-query";
export function AssignmentFooterButtons({ export function AssignmentFooterButtons({
moduleName, moduleName,
@@ -34,9 +36,10 @@ export function AssignmentFooterButtons({
const { data: settings } = useLocalCourseSettingsQuery(); const { data: settings } = useLocalCourseSettingsQuery();
const { data: canvasAssignments, isFetching: canvasIsFetching } = const { data: canvasAssignments, isFetching: canvasIsFetching } =
useCanvasAssignmentsQuery(); useCanvasAssignmentsQuery();
const queryClient = useQueryClient();
const { data: assignment, isFetching } = useAssignmentQuery( const { data: assignment, isFetching } = useAssignmentQuery(
moduleName, moduleName,
assignmentName assignmentName,
); );
const addToCanvas = useAddAssignmentToCanvasMutation(); const addToCanvas = useAddAssignmentToCanvasMutation();
const deleteFromCanvas = useDeleteAssignmentFromCanvasMutation(); const deleteFromCanvas = useDeleteAssignmentFromCanvasMutation();
@@ -47,11 +50,11 @@ export function AssignmentFooterButtons({
const { previousUrl, nextUrl } = useItemNavigation( const { previousUrl, nextUrl } = useItemNavigation(
"assignment", "assignment",
assignmentName, assignmentName,
moduleName moduleName,
); );
const assignmentInCanvas = canvasAssignments?.find( const assignmentInCanvas = canvasAssignments?.find(
(a) => a.name === assignmentName (a) => a.name === assignmentName,
); );
const anythingIsLoading = const anythingIsLoading =
@@ -84,6 +87,17 @@ export function AssignmentFooterButtons({
className="btn" className="btn"
target="_blank" target="_blank"
href={`${baseCanvasUrl}/courses/${settings.canvasId}/assignments/${assignmentInCanvas.id}`} href={`${baseCanvasUrl}/courses/${settings.canvasId}/assignments/${assignmentInCanvas.id}`}
onClick={() => {
for (let i = 1; i <= 8; i += 2) {
setTimeout(() => {
queryClient.invalidateQueries({
queryKey: canvasAssignmentKeys.assignments(
settings.canvasId,
),
});
}, i * 1000);
}
}}
> >
View in Canvas View in Canvas
</a> </a>

View File

@@ -75,14 +75,14 @@ export default function AssignmentPreview({
{extraPoints !== 0 && ( {extraPoints !== 0 && (
<h5 className="text-center">{extraPoints} Extra Credit Points</h5> <h5 className="text-center">{extraPoints} Extra Credit Points</h5>
)} )}
<div className="grid grid-cols-4"> <div className="grid grid-cols-[auto_auto_1fr]">
{assignment.rubric.map((rubricItem, i) => ( {assignment.rubric.map((rubricItem, i) => (
<Fragment key={rubricItem.label + i}> <Fragment key={rubricItem.label + i}>
<div className="text-end pe-1"> <div className="text-end pe-1">
{rubricItemIsExtraCredit(rubricItem) ? "Extra Credit" : ""} {rubricItemIsExtraCredit(rubricItem) ? "Extra Credit" : ""}
</div> </div>
<div className="text-end pe-3">{rubricItem.points}</div> <div className="text-end pe-3">{rubricItem.points}</div>
<div className="col-span-2">{rubricItem.label}</div> <div>{rubricItem.label}</div>
</Fragment> </Fragment>
))} ))}
</div> </div>

View File

@@ -44,6 +44,8 @@ export async function getModuleNamesFromFiles(courseName: string) {
.map((dirent) => dirent.name); .map((dirent) => dirent.name);
const modules = await Promise.all(modulePromises); const modules = await Promise.all(modulePromises);
const modulesWithoutLectures = modules.filter((m) => m !== lectureFolderName); const modulesWithoutLectures = modules.filter(
(m) => m !== lectureFolderName && !m.startsWith(".")
);
return modulesWithoutLectures.sort((a, b) => a.localeCompare(b)); return modulesWithoutLectures.sort((a, b) => a.localeCompare(b));
} }