feat: integrate Moodle API services, add RichTextEditor component, and configure environment variables for course management.
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
import axios from "axios";
|
||||
import { MOODLE_API_URL, MOODLE_TOKEN } from "../config/moodle";
|
||||
|
||||
const ensureConfig = () => {
|
||||
if (!MOODLE_API_URL || !MOODLE_TOKEN) {
|
||||
throw new Error(
|
||||
"Configuration Moodle manquante. Vérifiez VITE_MOODLE_API_URL et VITE_MOODLE_TOKEN."
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const appendParam = (searchParams, value, key) => {
|
||||
if (value === undefined || value === null || key === undefined) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((entry, index) => {
|
||||
appendParam(searchParams, entry, `${key}[${index}]`);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (typeof value === "object" && !(value instanceof Date)) {
|
||||
Object.entries(value).forEach(([childKey, childValue]) => {
|
||||
const nextKey = key ? `${key}[${childKey}]` : childKey;
|
||||
appendParam(searchParams, childValue, nextKey);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const normalizedValue =
|
||||
value instanceof Date ? value.getTime().toString() : String(value);
|
||||
searchParams.append(key, normalizedValue);
|
||||
};
|
||||
|
||||
export const callMoodle = async (wsfunction, payload = {}, options = {}) => {
|
||||
ensureConfig();
|
||||
const params = new URLSearchParams();
|
||||
params.append("wstoken", MOODLE_TOKEN);
|
||||
params.append("wsfunction", wsfunction);
|
||||
params.append("moodlewsrestformat", "json");
|
||||
|
||||
Object.entries(payload).forEach(([key, value]) =>
|
||||
appendParam(params, value, key)
|
||||
);
|
||||
|
||||
const response = await axios.post(MOODLE_API_URL, params, {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
timeout: options.timeout ?? 20000,
|
||||
...options.axios,
|
||||
});
|
||||
|
||||
if (response.data?.exception || response.data?.errorcode) {
|
||||
const message =
|
||||
response.data.message ||
|
||||
response.data.debuginfo ||
|
||||
response.data.errorcode;
|
||||
throw new Error(message || "Erreur Moodle inconnue.");
|
||||
}
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const MoodleApi = {
|
||||
listCourses: (searchValue = "") => {
|
||||
if (searchValue) {
|
||||
return callMoodle("core_course_get_courses_by_field", {
|
||||
field: "search",
|
||||
value: searchValue,
|
||||
}).then((data) => data.courses || []);
|
||||
}
|
||||
return callMoodle("core_course_get_courses").then(
|
||||
(data) => data || []
|
||||
);
|
||||
},
|
||||
getCourseById: async (courseId) => {
|
||||
const response = await callMoodle("core_course_get_courses_by_field", {
|
||||
field: "id",
|
||||
value: Number(courseId),
|
||||
});
|
||||
return response?.courses?.[0] || null;
|
||||
},
|
||||
createCourse: (coursePayload) => {
|
||||
const normalized = {
|
||||
summaryformat: 1,
|
||||
format: "topics",
|
||||
...coursePayload,
|
||||
};
|
||||
if (normalized.categoryid !== undefined) {
|
||||
normalized.categoryid = Number(normalized.categoryid);
|
||||
}
|
||||
return callMoodle("core_course_create_courses", {
|
||||
courses: [normalized],
|
||||
});
|
||||
},
|
||||
updateCourse: (coursePayload) => {
|
||||
const normalized = {
|
||||
summaryformat: 1,
|
||||
...coursePayload,
|
||||
};
|
||||
if (normalized.id !== undefined) {
|
||||
normalized.id = Number(normalized.id);
|
||||
}
|
||||
if (normalized.categoryid !== undefined) {
|
||||
normalized.categoryid = Number(normalized.categoryid);
|
||||
}
|
||||
return callMoodle("core_course_update_courses", {
|
||||
courses: [normalized],
|
||||
});
|
||||
},
|
||||
deleteCourses: (courseIds) =>
|
||||
callMoodle("core_course_delete_courses", {
|
||||
courseids: courseIds,
|
||||
}),
|
||||
getCourseContents: (courseId) =>
|
||||
callMoodle("core_course_get_contents", { courseid: Number(courseId) }),
|
||||
getPagesByCourse: (courseId) =>
|
||||
callMoodle("mod_page_get_pages_by_courses", {
|
||||
courseids: [Number(courseId)],
|
||||
}).then((data) => data.pages || []),
|
||||
getAssignmentsByCourse: (courseId) =>
|
||||
callMoodle("mod_assign_get_assignments", {
|
||||
courseids: [Number(courseId)],
|
||||
}).then((data) => {
|
||||
const normalizedId = Number(courseId);
|
||||
const course = data?.courses?.find((c) => c.id === normalizedId);
|
||||
return course?.assignments || [];
|
||||
}),
|
||||
getH5PActivitiesByCourse: (courseId) =>
|
||||
callMoodle("mod_h5pactivity_get_h5pactivities_by_courses", {
|
||||
courseids: [Number(courseId)],
|
||||
}).then((data) => data.h5pactivities || []),
|
||||
getQuizzesByCourse: (courseId) =>
|
||||
callMoodle("mod_quiz_get_quizzes_by_courses", {
|
||||
courseids: [Number(courseId)],
|
||||
}).then((data) => data.quizzes || []),
|
||||
createSection: (sectionPayload) =>
|
||||
callMoodle("core_course_create_sections", {
|
||||
sections: [
|
||||
{
|
||||
summaryformat: 1,
|
||||
...sectionPayload,
|
||||
},
|
||||
],
|
||||
}),
|
||||
updateSection: (sectionPayload) => {
|
||||
const payload = {
|
||||
summaryformat: 1,
|
||||
...sectionPayload,
|
||||
};
|
||||
if (payload.id !== undefined) {
|
||||
payload.id = Number(payload.id);
|
||||
}
|
||||
if (payload.courseid !== undefined) {
|
||||
payload.courseid = Number(payload.courseid);
|
||||
}
|
||||
if (payload.section !== undefined && payload.section !== null) {
|
||||
const normalizedSection = Number(payload.section);
|
||||
payload.section = Number.isNaN(normalizedSection)
|
||||
? undefined
|
||||
: normalizedSection;
|
||||
}
|
||||
return callMoodle("core_course_update_sections", {
|
||||
sections: [payload],
|
||||
});
|
||||
},
|
||||
deleteSections: (courseId, sectionIds, sectionNumbers) => {
|
||||
const payload = {
|
||||
courseid: Number(courseId),
|
||||
};
|
||||
if (sectionIds?.length) {
|
||||
payload.sectionids = sectionIds.map((id) => Number(id));
|
||||
}
|
||||
if (sectionNumbers?.length) {
|
||||
payload.sectionnumbers = sectionNumbers.map((value) => Number(value));
|
||||
}
|
||||
return callMoodle("core_course_delete_sections", payload);
|
||||
},
|
||||
moveModuleToSection: (moduleId, sectionNumber) => {
|
||||
const payload = {
|
||||
cmid: Number(moduleId),
|
||||
};
|
||||
if (sectionNumber !== null && sectionNumber !== undefined) {
|
||||
const normalized = Number(sectionNumber);
|
||||
if (!Number.isNaN(normalized)) {
|
||||
payload.section = normalized;
|
||||
}
|
||||
}
|
||||
return callMoodle("core_course_edit_module", payload);
|
||||
},
|
||||
};
|
||||
|
||||
export default MoodleApi;
|
||||
Reference in New Issue
Block a user