improve edited exam changes printing format
This commit is contained in:
@@ -1,7 +1,26 @@
|
|||||||
import { Exam } from "@/interfaces/exam";
|
import { Exam } from "@/interfaces/exam";
|
||||||
import { diff, Diff } from "deep-diff";
|
import { diff, Diff } from "deep-diff";
|
||||||
|
|
||||||
const EXCLUDED_FIELDS = new Set(["_id", "id", "createdAt", "createdBy", "entities", "isDiagnostic", "private"]);
|
const EXCLUDED_FIELDS = new Set(["_id", "id", "createdAt", "createdBy", "entities", "isDiagnostic", "private", "access", "requiresApproval", "score"]);
|
||||||
|
|
||||||
|
const PATH_LABELS: Record<string, string> = {
|
||||||
|
parts: "Parts",
|
||||||
|
exercises: "Exercises",
|
||||||
|
userSolutions: "User Solutions",
|
||||||
|
words: "Words",
|
||||||
|
options: "Options",
|
||||||
|
prompt: "Prompt",
|
||||||
|
text: "Text",
|
||||||
|
audio: "Audio",
|
||||||
|
script: "Script",
|
||||||
|
difficulty: "Difficulty",
|
||||||
|
shuffle: "Shuffle",
|
||||||
|
solutions: "Solutions",
|
||||||
|
variant: "Variant",
|
||||||
|
prefix: "Prefix",
|
||||||
|
suffix: "Suffix",
|
||||||
|
topic: "Topic",
|
||||||
|
};
|
||||||
|
|
||||||
export function generateExamDifferences(oldExam: Exam, newExam: Exam): string[] {
|
export function generateExamDifferences(oldExam: Exam, newExam: Exam): string[] {
|
||||||
const differences = diff(oldExam, newExam) || [];
|
const differences = diff(oldExam, newExam) || [];
|
||||||
@@ -17,24 +36,19 @@ function formatDifference(change: Diff<any, any>): string | undefined {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert path array to something human-readable
|
const pathString = pathToHumanReadable(change.path);
|
||||||
const pathString = change.path.join(" \u2192 "); // e.g. "parts → 0 → exercises → 1 → prompt"
|
|
||||||
|
|
||||||
switch (change.kind) {
|
switch (change.kind) {
|
||||||
case "N":
|
case "N": // A new property/element was added
|
||||||
// A new property/element was added
|
return `• Added ${pathString} with value: ${formatValue(change.rhs)}\n`;
|
||||||
return `\u{2022} Added \`${pathString}\` with value: ${formatValue(change.rhs)}`;
|
|
||||||
|
|
||||||
case "D":
|
case "D": // A property/element was deleted
|
||||||
// A property/element was deleted
|
return `• Removed ${pathString} which had value: ${formatValue(change.lhs)}\n`;
|
||||||
return `\u{2022} Removed \`${pathString}\` which had value: ${formatValue(change.lhs)}`;
|
|
||||||
|
|
||||||
case "E":
|
case "E": // A property/element was edited
|
||||||
// A property/element was edited
|
return `• Changed ${pathString} from ${formatValue(change.lhs)} to ${formatValue(change.rhs)}\n`;
|
||||||
return `\u{2022} Changed \`${pathString}\` from ${formatValue(change.lhs)} to ${formatValue(change.rhs)}`;
|
|
||||||
|
|
||||||
case "A":
|
case "A": // An array change; `change.item` describes what happened at array index `change.index`
|
||||||
// An array change; change.item describes what happened at array index change.index
|
|
||||||
return formatArrayChange(change);
|
return formatArrayChange(change);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -44,12 +58,12 @@ function formatDifference(change: Diff<any, any>): string | undefined {
|
|||||||
|
|
||||||
function formatArrayChange(change: Diff<any, any>): string | undefined {
|
function formatArrayChange(change: Diff<any, any>): string | undefined {
|
||||||
if (!change.path) return;
|
if (!change.path) return;
|
||||||
|
|
||||||
if (change.path.some((segment) => EXCLUDED_FIELDS.has(segment))) {
|
if (change.path.some((segment) => EXCLUDED_FIELDS.has(segment))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathString = change.path.join(" \u2192 ");
|
const pathString = pathToHumanReadable(change.path);
|
||||||
|
|
||||||
const arrayChange = (change as any).item;
|
const arrayChange = (change as any).item;
|
||||||
const idx = (change as any).index;
|
const idx = (change as any).index;
|
||||||
|
|
||||||
@@ -57,14 +71,13 @@ function formatArrayChange(change: Diff<any, any>): string | undefined {
|
|||||||
|
|
||||||
switch (arrayChange.kind) {
|
switch (arrayChange.kind) {
|
||||||
case "N":
|
case "N":
|
||||||
return `\u{2022} Added an item at index [${idx}] in \`${pathString}\`: ${formatValue(arrayChange.rhs)}`;
|
return `• Added an item at [#${idx + 1}] in ${pathString}: ${formatValue(arrayChange.rhs)}\n`;
|
||||||
case "D":
|
case "D":
|
||||||
return `\u{2022} Removed an item at index [${idx}] in \`${pathString}\`: ${formatValue(arrayChange.lhs)}`;
|
return `• Removed an item at [#${idx + 1}] in ${pathString}: ${formatValue(arrayChange.lhs)}\n`;
|
||||||
case "E":
|
case "E":
|
||||||
return `\u{2022} Edited an item at index [${idx}] in \`${pathString}\` from ${formatValue(arrayChange.lhs)} to ${formatValue(arrayChange.rhs)}`;
|
return `• Edited an item at [#${idx + 1}] in ${pathString} from ${formatValue(arrayChange.lhs)} to ${formatValue(arrayChange.rhs)}\n`;
|
||||||
case "A":
|
case "A":
|
||||||
// Nested array changes could happen theoretically; handle or ignore similarly
|
return `• Complex array change at [#${idx + 1}] in ${pathString}: ${JSON.stringify(arrayChange)}\n`;
|
||||||
return `\u{2022} Complex array change at index [${idx}] in \`${pathString}\`: ${JSON.stringify(arrayChange)}`;
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -82,3 +95,21 @@ function formatValue(value: any): string {
|
|||||||
}
|
}
|
||||||
return JSON.stringify(value);
|
return JSON.stringify(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an array of path segments into a friendlier string.
|
||||||
|
* Example:
|
||||||
|
* ["parts", 0, "exercises", 1, "prompt"]
|
||||||
|
* becomes:
|
||||||
|
* "Parts → [#1] → Exercises → [#2] → Prompt"
|
||||||
|
*/
|
||||||
|
function pathToHumanReadable(pathSegments: Array<string | number>): string {
|
||||||
|
return pathSegments
|
||||||
|
.map((seg) => {
|
||||||
|
if (typeof seg === "number") {
|
||||||
|
return `[#${seg + 1}]`;
|
||||||
|
}
|
||||||
|
return PATH_LABELS[seg] ?? seg;
|
||||||
|
})
|
||||||
|
.join(" → ");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user