sort module button

This commit is contained in:
2025-08-11 14:06:59 -06:00
parent 5715b081a9
commit 762a51d6da
9 changed files with 133 additions and 29 deletions

View File

@@ -1,6 +1,8 @@
import { CanvasModuleItem } from "@/features/canvas/models/modules/canvasModuleItems";
import { useLocalCourseSettingsQuery } from "@/features/local/course/localCoursesHooks";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { canvasModuleService } from "../services/canvasModuleService";
import { IModuleItem } from "@/features/local/modules/IModuleItem";
export const canvasCourseModuleKeys = {
modules: (canvasId: number) => ["canvas", canvasId, "module list"] as const,
@@ -28,3 +30,54 @@ export const useAddCanvasModuleMutation = () => {
},
});
};
export const useReorderCanvasModuleItemsMutation = () => {
const { data: settings } = useLocalCourseSettingsQuery();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
moduleId,
items,
}: {
moduleId: number;
items: IModuleItem[];
}) => {
if (!settings?.canvasId) throw new Error("No canvasId in settings");
const canvasModule = await canvasModuleService.getModuleWithItems(
settings.canvasId,
moduleId
);
if (!canvasModule.items) {
throw new Error(
"cannot sort canvas module items, no items found in module"
);
}
const canvasItems = canvasModule.items;
// Sort IModuleItems by dueAt
const sorted = [...items].sort((a, b) => {
const aDate = a.dueAt ? new Date(a.dueAt).getTime() : 0;
const bDate = b.dueAt ? new Date(b.dueAt).getTime() : 0;
return aDate - bDate;
});
// Map sorted IModuleItems to CanvasModuleItem ids by matching name/title
const orderedIds = sorted
.map((localItem) => canvasItems.find((canvasItem) => canvasItem.title === localItem.name)?.id)
.filter((id): id is number => typeof id === "number");
return await canvasModuleService.reorderModuleItems(
settings.canvasId,
moduleId,
orderedIds
);
},
onSuccess: (_data) => {
if (!settings?.canvasId) return;
queryClient.invalidateQueries({
queryKey: canvasCourseModuleKeys.modules(settings.canvasId),
});
},
});
};

View File

@@ -20,6 +20,13 @@ export const canvasModuleService = {
if (!data) throw new Error("Something went wrong updating module item");
},
async getModuleWithItems(canvasCourseId: number, moduleId: number) {
const url = `${canvasApi}/courses/${canvasCourseId}/modules/${moduleId}`;
const params = { include: ["items"] };
const response = await axiosClient.get<CanvasModule>(url, { params });
return response.data;
},
async createModuleItem(
canvasCourseId: number,
canvasModuleId: number,
@@ -63,4 +70,21 @@ export const canvasModuleService = {
const response = await axiosClient.post<CanvasModule>(url, body);
return response.data.id;
},
async reorderModuleItems(
canvasCourseId: number,
canvasModuleId: number,
itemIds: number[]
) {
for (let i = 0; i < itemIds.length; i++) {
const itemId = itemIds[i];
const url = `${canvasApi}/courses/${canvasCourseId}/modules/${canvasModuleId}/items/${itemId}`;
const body = {
module_item: {
position: i + 1,
},
};
await axiosClient.put(url, body);
}
},
};

View File

@@ -15,7 +15,7 @@ import { GlobalSettingsCourse } from "../globalSettings/globalSettingsModels";
const getCourseSettings = async (
course: GlobalSettingsCourse
): Promise<LocalCourseSettings> => {
const courseDirectory = await getCoursePathByName(course.name);
const courseDirectory = path.join(basePath, course.path);
const settingsPath = path.join(courseDirectory, "settings.yml");
if (!(await directoryOrFileExists(settingsPath))) {
const errorMessage = `could not find settings for ${course.name}, settings file ${settingsPath}`;