some papercuts

This commit is contained in:
2025-01-06 15:52:28 -07:00
parent ad4b059a17
commit a494e315d2
6 changed files with 78 additions and 26 deletions

View File

@@ -7,7 +7,6 @@ import { QuizButtons } from "./QuizButton";
import ClientOnly from "@/components/ClientOnly";
import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling";
import { useRouter } from "next/navigation";
import { getModuleItemUrl } from "@/services/urlUtils";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import {
useQuizQuery,
@@ -16,8 +15,15 @@ import {
import { useAuthoritativeUpdates } from "../../../../utils/useAuthoritativeUpdates";
import { extractLabelValue } from "@/models/local/assignment/utils/markdownUtils";
import EditQuizHeader from "./EditQuizHeader";
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
const helpString = `QUESTION REFERENCE
const helpString = (settings: LocalCourseSettings) => {
const groupNames = settings.assignmentGroups.map((g) => g.name).join("\n- ");
return `Assignment Group Names:
- ${groupNames}
QUESTION REFERENCE
---
Points: 2
this is a question?
@@ -57,6 +63,7 @@ short answer
this is a matching question
^ left answer - right dropdown
^ other thing - another option`;
};
export default function EditQuiz({
moduleName,
@@ -66,6 +73,7 @@ export default function EditQuiz({
moduleName: string;
}) {
const router = useRouter();
const [settings] = useLocalCourseSettingsQuery();
const { courseName } = useCourseContext();
const [quiz, { dataUpdatedAt: serverDataUpdatedAt, isFetching }] =
useQuizQuery(moduleName, quizName);
@@ -95,19 +103,15 @@ export default function EditQuiz({
)
) {
if (clientIsAuthoritative) {
const updatedQuiz = quizMarkdownUtils.parseMarkdown(
text,
quizName
);
await updateQuizMutation
.mutateAsync({
quiz: updatedQuiz,
moduleName,
quizName: quizName,
previousModuleName: moduleName,
previousQuizName: quizName,
courseName,
})
const updatedQuiz = quizMarkdownUtils.parseMarkdown(text, quizName);
await updateQuizMutation.mutateAsync({
quiz: updatedQuiz,
moduleName,
quizName: quizName,
previousModuleName: moduleName,
previousQuizName: quizName,
courseName,
});
} else {
console.log(
"client not authoritative, updating client with server quiz"
@@ -143,7 +147,7 @@ export default function EditQuiz({
<div className={"min-h-96 h-full flex flex-row w-full"}>
{showHelp && (
<pre className=" max-w-96">
<code>{helpString}</code>
<code>{helpString(settings)}</code>
</pre>
)}
<div className="flex-1 h-full">

View File

@@ -1,9 +1,10 @@
"use client"
"use client";
import AssignmentGroupManagement from "./AssignmentGroupManagement";
import DaysOfWeekSettings from "./DaysOfWeekSettings";
import DefaultDueTime from "./DefaultDueTime";
import DefaultFileUploadTypes from "./DefaultFileUploadTypes";
import GithubClassroomList from "./GithubClassroomList";
import HolidayConfig from "./HolidayConfig";
import SettingsHeader from "./SettingsHeader";
import StartAndEndDate from "./StartAndEndDate";
@@ -15,6 +16,7 @@ export default function AllSettings() {
<SettingsHeader />
<DaysOfWeekSettings />
<StartAndEndDate />
<GithubClassroomList />
<SubmissionDefaults />
<DefaultFileUploadTypes />
<DefaultDueTime />

View File

@@ -0,0 +1,31 @@
"use client";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import { settingsBox } from "./sharedSettings";
import { useCourseStudentsQuery } from "@/hooks/canvas/canvasCourseHooks";
import { Spinner } from "@/components/Spinner";
export default function GithubClassroomList() {
const [settings] = useLocalCourseSettingsQuery();
const enrollmentsQuery = useCourseStudentsQuery(settings.canvasId);
if (enrollmentsQuery.isLoading)
return (
<div className={settingsBox}>
<Spinner />
</div>
);
return (
<div className={settingsBox}>
<h5 className="text-center">Github Classroom Friendly Roster</h5>
<p className="text-center text-slate-500">
Copy and paste this into github classroom to import students
</p>
<pre>
<code>
{enrollmentsQuery.data?.map((student) => student.email + "\n")}
</code>
</pre>
</div>
);
}

View File

@@ -1,16 +1,11 @@
import { CanvasAssignmentGroup } from "@/models/canvas/assignments/canvasAssignmentGroup";
import { CanvasCourseModel } from "@/models/canvas/courses/canvasCourseModel";
import { LocalAssignmentGroup } from "@/models/local/assignment/localAssignmentGroup";
import {
LocalCourseSettings,
zodLocalCourseSettings,
} from "@/models/local/localCourseSettings";
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
import { canvasAssignmentGroupService } from "@/services/canvas/canvasAssignmentGroupService";
import { canvasService } from "@/services/canvas/canvasService";
import { trpc } from "@/services/serverFunctions/trpcClient";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useUpdateLocalCourseSettingsMutation } from "../localCourse/localCoursesHooks";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
export const canvasCourseKeys = {
courseDetails: (canavasId: number) =>
@@ -19,6 +14,8 @@ export const canvasCourseKeys = {
["canvas", canavasId, "assignment groups"] as const,
courseListInTerm: (canvasTermId: number | undefined) =>
["canvas courses in term", canvasTermId] as const,
students: (canvasId: number) =>
["students in canvas course", canvasId] as const,
};
export const useCourseListInTermQuery = (canvasTermId: number | undefined) =>
@@ -101,3 +98,9 @@ export const useAssignmentGroupsQuery = (canvasId: number) => {
await canvasAssignmentGroupService.getAll(canvasId),
});
};
export const useCourseStudentsQuery = (canvasId: number) =>
useQuery({
queryKey: canvasCourseKeys.students(canvasId),
queryFn: async () => await canvasService.getEnrolledStudents(canvasId),
});

View File

@@ -0,0 +1,12 @@
export interface CanvasCourseStudentModel {
id: number;
name: string;
created_at: string; // ISO 8601 date string
sortable_name: string;
short_name: string;
sis_user_id: string;
integration_id?: string;
root_account: string;
login_id: string;
email: string;
}

View File

@@ -1,8 +1,8 @@
import { CanvasEnrollmentTermModel } from "@/models/canvas/enrollmentTerms/canvasEnrollmentTermModel";
import { canvasApi, paginatedRequest } from "./canvasServiceUtils";
import { CanvasCourseModel } from "@/models/canvas/courses/canvasCourseModel";
import { CanvasEnrollmentModel } from "@/models/canvas/enrollments/canvasEnrollmentModel";
import { axiosClient } from "../axiosUtils";
import { CanvasCourseStudentModel } from "@/models/canvas/courses/canvasCourseStudentModel";
const getAllTerms = async () => {
const url = `${canvasApi}/accounts/10/terms?per_page=100`;
@@ -54,8 +54,8 @@ export const canvasService = {
async getEnrolledStudents(canvasCourseId: number) {
console.log(`Getting students for course ${canvasCourseId}`);
const url = `${canvasApi}/courses/${canvasCourseId}/enrollments?enrollment_type=student`;
const { data } = await axiosClient.get<CanvasEnrollmentModel[]>(url);
const url = `${canvasApi}/courses/${canvasCourseId}/users?enrollment_type=student`;
const data = await paginatedRequest<CanvasCourseStudentModel[]>({url});
if (!data)
throw new Error(