diff --git a/src/pages/approval-workflows/[id]/index.tsx b/src/pages/approval-workflows/[id]/index.tsx index 64a8026e..c6cdc340 100644 --- a/src/pages/approval-workflows/[id]/index.tsx +++ b/src/pages/approval-workflows/[id]/index.tsx @@ -557,7 +557,7 @@ export default function Home({ user, initialWorkflow, id, workflowAssignees, wor
{currentWorkflow.steps[selectedStepIndex].examChanges?.length ? ( currentWorkflow.steps[selectedStepIndex].examChanges!.map((change, index) => ( -

+

{change}

)) diff --git a/src/utils/exam.differences.ts b/src/utils/exam.differences.ts index 6a1cf303..b860e11f 100644 --- a/src/utils/exam.differences.ts +++ b/src/utils/exam.differences.ts @@ -1,9 +1,10 @@ import { Exam } from "@/interfaces/exam"; import { diff, Diff } from "deep-diff"; -const EXCLUDED_KEYS = new Set(["_id", "id", "createdAt", "createdBy", "entities", "isDiagnostic", "private", "access", "requiresApproval"]); +const EXCLUDED_KEYS = new Set(["_id", "id", "createdAt", "createdBy", "entities", "isDiagnostic", "private", "requiresApproval", "exerciseID", "questionID"]); const PATH_LABELS: Record = { + access: "Access Type", parts: "Parts", exercises: "Exercises", userSolutions: "User Solutions", @@ -20,6 +21,9 @@ const PATH_LABELS: Record = { prefix: "Prefix", suffix: "Suffix", topic: "Topic", + allowRepetition: "Allow Repetition", + maxWords: "Max Words", + minTimer: "Timer", }; export function generateExamDifferences(oldExam: Exam, newExam: Exam): string[] { @@ -28,9 +32,7 @@ export function generateExamDifferences(oldExam: Exam, newExam: Exam): string[] } function formatDifference(change: Diff): string | undefined { - if (!change.path) { - return; - } + if (!change.path) return; if (change.path.some((segment) => EXCLUDED_KEYS.has(segment))) { return; @@ -85,30 +87,53 @@ function formatValue(value: any): string { if (typeof value === "object") { try { - return JSON.stringify( - value, - (key, val) => { - if (EXCLUDED_KEYS.has(key)) { - return undefined; - } - return val; - }, - 2 // optional indentation for readability - ); + const sanitized = removeExcludedKeysDeep(value, EXCLUDED_KEYS); + + const renamed = renameKeysDeep(sanitized, PATH_LABELS); + + return JSON.stringify(renamed, null, 2); } catch { return String(value); } } - return JSON.stringify(value); } +function removeExcludedKeysDeep(obj: any, excludedKeys: Set): any { + if (Array.isArray(obj)) { + return obj.map((item) => removeExcludedKeysDeep(item, excludedKeys)); + } else if (obj && typeof obj === "object") { + const newObj: any = {}; + for (const key of Object.keys(obj)) { + if (excludedKeys.has(key)) { + // Skip this key entirely + continue; + } + newObj[key] = removeExcludedKeysDeep(obj[key], excludedKeys); + } + return newObj; + } + return obj; +} + +function renameKeysDeep(obj: any, renameMap: Record): any { + if (Array.isArray(obj)) { + return obj.map((item) => renameKeysDeep(item, renameMap)); + } else if (obj && typeof obj === "object") { + const newObj: any = {}; + for (const key of Object.keys(obj)) { + const newKey = renameMap[key] ?? key; // Use friendly label if available + newObj[newKey] = renameKeysDeep(obj[key], renameMap); + } + return newObj; + } + return obj; +} + /** - * Convert an array of path segments into a friendlier string. - * Example: - * ["parts", 0, "exercises", 1, "prompt"] - * becomes: - * "Parts → [#1] → Exercises → [#2] → Prompt" + * Convert an array of path segments into a user-friendly string. + * e.g. ["parts", 0, "exercises", 1, "prompt"] + * → "Parts → [#1] → Exercises → [#2] → Prompt" */ function pathToHumanReadable(pathSegments: Array): string { return pathSegments