@thanh01.pmt/interactive-quiz-kit 1.0.71 → 1.0.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.cjs +24 -14
- package/dist/ai.mjs +24 -14
- package/dist/authoring.cjs +311 -56
- package/dist/authoring.d.cts +1 -1
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.mjs +311 -56
- package/dist/react-ui.cjs +311 -56
- package/dist/react-ui.d.cts +1 -1
- package/dist/react-ui.d.ts +1 -1
- package/dist/react-ui.mjs +311 -56
- package/dist/{toaster-BWaJj0l-.d.cts → toaster-6AR8w2TO.d.cts} +3 -3
- package/dist/{toaster-BVaUJA6E.d.ts → toaster-DAXYZdrz.d.ts} +3 -3
- package/package.json +1 -1
package/dist/authoring.mjs
CHANGED
|
@@ -8767,12 +8767,10 @@ init_react_shim();
|
|
|
8767
8767
|
// src/services/TopicDataService.ts
|
|
8768
8768
|
init_react_shim();
|
|
8769
8769
|
var TopicDataService = class {
|
|
8770
|
-
// ... saveData, mergeData, getData, clearData methods remain the same ...
|
|
8771
8770
|
static saveData(data) {
|
|
8772
8771
|
try {
|
|
8773
8772
|
if (typeof window === "undefined") return;
|
|
8774
|
-
|
|
8775
|
-
localStorage.setItem(this.STORAGE_KEY, serializedData);
|
|
8773
|
+
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(data));
|
|
8776
8774
|
} catch (error) {
|
|
8777
8775
|
console.error("Error saving learning objectives to Local Storage:", error);
|
|
8778
8776
|
}
|
|
@@ -8783,8 +8781,7 @@ var TopicDataService = class {
|
|
|
8783
8781
|
newData.forEach((newLo) => {
|
|
8784
8782
|
loMap.set(newLo.code, newLo);
|
|
8785
8783
|
});
|
|
8786
|
-
|
|
8787
|
-
this.saveData(mergedData);
|
|
8784
|
+
this.saveData(Array.from(loMap.values()));
|
|
8788
8785
|
}
|
|
8789
8786
|
static getData() {
|
|
8790
8787
|
try {
|
|
@@ -8799,7 +8796,7 @@ var TopicDataService = class {
|
|
|
8799
8796
|
}
|
|
8800
8797
|
static clearData() {
|
|
8801
8798
|
try {
|
|
8802
|
-
if (typeof window
|
|
8799
|
+
if (typeof window !== "undefined") return;
|
|
8803
8800
|
localStorage.removeItem(this.STORAGE_KEY);
|
|
8804
8801
|
} catch (error) {
|
|
8805
8802
|
console.error("Error clearing learning objectives from Local Storage:", error);
|
|
@@ -8813,6 +8810,12 @@ var TopicDataService = class {
|
|
|
8813
8810
|
const headerLine = lines.shift();
|
|
8814
8811
|
const headers = headerLine.split(" ").map((h2) => h2.trim());
|
|
8815
8812
|
const headerMap = headers.map((h2) => this.HEADER_MAP[h2] || null);
|
|
8813
|
+
const requiredHeaders = ["LO ID", "LO Name", "Subject", "Subject Code", "Category", "Category Code", "Topic", "Topic Code", "Grade", "Grade Code"];
|
|
8814
|
+
const missingHeaders = requiredHeaders.filter((h2) => !headers.includes(h2));
|
|
8815
|
+
if (missingHeaders.length > 0) {
|
|
8816
|
+
const errorMsg = `Invalid TSV header. Missing required columns: ${missingHeaders.join(", ")}`;
|
|
8817
|
+
return { data: [], errors: [errorMsg] };
|
|
8818
|
+
}
|
|
8816
8819
|
const data = [];
|
|
8817
8820
|
const errors2 = [];
|
|
8818
8821
|
lines.forEach((line, index3) => {
|
|
@@ -8821,29 +8824,30 @@ var TopicDataService = class {
|
|
|
8821
8824
|
headerMap.forEach((propName, i) => {
|
|
8822
8825
|
if (propName) {
|
|
8823
8826
|
const value = values[i]?.trim() || "";
|
|
8824
|
-
if (
|
|
8827
|
+
if (["keywords", "stemElements", "bloomLevelsGuideline"].includes(propName)) {
|
|
8825
8828
|
rowObject[propName] = value.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
8826
8829
|
} else {
|
|
8827
8830
|
rowObject[propName] = value;
|
|
8828
8831
|
}
|
|
8829
8832
|
}
|
|
8830
8833
|
});
|
|
8831
|
-
if (!rowObject.code) {
|
|
8832
|
-
errors2.push(`Line ${index3 + 2}: Missing required
|
|
8834
|
+
if (!rowObject.code || !rowObject.name) {
|
|
8835
|
+
errors2.push(`Line ${index3 + 2}: Missing required values for 'LO ID' or 'LO Name'.`);
|
|
8833
8836
|
return;
|
|
8834
8837
|
}
|
|
8835
|
-
if (!rowObject.name) {
|
|
8836
|
-
rowObject.name = rowObject.code;
|
|
8837
|
-
}
|
|
8838
8838
|
const learningObjective = {
|
|
8839
8839
|
id: generateUniqueId("lo_"),
|
|
8840
8840
|
code: rowObject.code,
|
|
8841
8841
|
name: rowObject.name,
|
|
8842
8842
|
description: rowObject.description,
|
|
8843
8843
|
subject: rowObject.subject || "",
|
|
8844
|
+
subjectCode: rowObject.subjectCode,
|
|
8844
8845
|
category: rowObject.category || "",
|
|
8846
|
+
categoryCode: rowObject.categoryCode,
|
|
8845
8847
|
topic: rowObject.topic || "",
|
|
8848
|
+
topicCode: rowObject.topicCode,
|
|
8846
8849
|
grade: rowObject.grade || "",
|
|
8850
|
+
gradeCode: rowObject.gradeCode,
|
|
8847
8851
|
keywords: rowObject.keywords || [],
|
|
8848
8852
|
stemElements: rowObject.stemElements || [],
|
|
8849
8853
|
bloomLevelsGuideline: rowObject.bloomLevelsGuideline || []
|
|
@@ -8874,17 +8878,23 @@ var TopicDataService = class {
|
|
|
8874
8878
|
}
|
|
8875
8879
|
};
|
|
8876
8880
|
TopicDataService.STORAGE_KEY = "interactive_quiz_kit_learning_objectives";
|
|
8877
|
-
// Define a map for flexible header mapping
|
|
8878
8881
|
TopicDataService.HEADER_MAP = {
|
|
8879
8882
|
"LO ID": "code",
|
|
8880
8883
|
"LO Name": "name",
|
|
8881
|
-
// Ready for future addition
|
|
8882
8884
|
"LO Description": "description",
|
|
8883
8885
|
"Subject": "subject",
|
|
8886
|
+
"Subject Code": "subjectCode",
|
|
8887
|
+
// New
|
|
8884
8888
|
"Category": "category",
|
|
8889
|
+
"Category Code": "categoryCode",
|
|
8890
|
+
// New
|
|
8885
8891
|
"Topic": "topic",
|
|
8892
|
+
"Topic Code": "topicCode",
|
|
8893
|
+
// New
|
|
8886
8894
|
"Keywords": "keywords",
|
|
8887
8895
|
"Grade": "grade",
|
|
8896
|
+
"Grade Code": "gradeCode",
|
|
8897
|
+
// New
|
|
8888
8898
|
"STEM Element(s)": "stemElements",
|
|
8889
8899
|
"Bloom\u2019s Level(s) Guideline": "bloomLevelsGuideline"
|
|
8890
8900
|
};
|
|
@@ -77229,15 +77239,27 @@ function QuestionTypeManager({ initialData, isLoading: isLoadingProp, onAdd, onU
|
|
|
77229
77239
|
|
|
77230
77240
|
// src/react-ui/components/metadata/LearningObjectiveManager.tsx
|
|
77231
77241
|
init_react_shim();
|
|
77232
|
-
function LearningObjectiveManager({
|
|
77242
|
+
function LearningObjectiveManager({
|
|
77243
|
+
initialData,
|
|
77244
|
+
subjects: subjectsProp,
|
|
77245
|
+
isLoading: isLoadingProp,
|
|
77246
|
+
onAdd,
|
|
77247
|
+
onUpdate,
|
|
77248
|
+
onDelete,
|
|
77249
|
+
onBulkAdd
|
|
77250
|
+
}) {
|
|
77233
77251
|
const [items, setItems] = useState([]);
|
|
77234
77252
|
const [subjects, setSubjects] = useState([]);
|
|
77235
77253
|
const [isLoading, setIsLoading] = useState(true);
|
|
77236
77254
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
77237
77255
|
const [isAlertOpen, setIsAlertOpen] = useState(false);
|
|
77238
|
-
const [currentItem, setCurrentItem] = useState(
|
|
77256
|
+
const [currentItem, setCurrentItem] = useState(
|
|
77257
|
+
null
|
|
77258
|
+
);
|
|
77239
77259
|
const [formState, setFormState] = useState({});
|
|
77240
|
-
const [itemToDelete, setItemToDelete] = useState(
|
|
77260
|
+
const [itemToDelete, setItemToDelete] = useState(
|
|
77261
|
+
null
|
|
77262
|
+
);
|
|
77241
77263
|
const [isPending, startTransition] = useTransition();
|
|
77242
77264
|
const { toast: toast2 } = useToast();
|
|
77243
77265
|
const isControlled = initialData !== void 0;
|
|
@@ -77248,7 +77270,11 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77248
77270
|
setItems(MetadataService.getLearningObjectives());
|
|
77249
77271
|
setSubjects(MetadataService.getSubjects());
|
|
77250
77272
|
} catch (error) {
|
|
77251
|
-
toast2({
|
|
77273
|
+
toast2({
|
|
77274
|
+
title: "Error",
|
|
77275
|
+
description: "Failed to refresh data.",
|
|
77276
|
+
variant: "destructive"
|
|
77277
|
+
});
|
|
77252
77278
|
} finally {
|
|
77253
77279
|
setIsLoading(false);
|
|
77254
77280
|
}
|
|
@@ -77268,7 +77294,9 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77268
77294
|
};
|
|
77269
77295
|
const handleAddItem = () => {
|
|
77270
77296
|
setCurrentItem(null);
|
|
77271
|
-
setFormState({
|
|
77297
|
+
setFormState({
|
|
77298
|
+
subjectCode: subjects.length > 0 ? subjects[0].code : ""
|
|
77299
|
+
});
|
|
77272
77300
|
setIsDialogOpen(true);
|
|
77273
77301
|
};
|
|
77274
77302
|
const handleEditItem = (item) => {
|
|
@@ -77290,9 +77318,16 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77290
77318
|
MetadataService.deleteLearningObjective(itemToDelete.code);
|
|
77291
77319
|
refreshData();
|
|
77292
77320
|
}
|
|
77293
|
-
toast2({
|
|
77321
|
+
toast2({
|
|
77322
|
+
title: "Success",
|
|
77323
|
+
description: `Learning Objective "${itemToDelete.name}" deleted.`
|
|
77324
|
+
});
|
|
77294
77325
|
} catch (error) {
|
|
77295
|
-
toast2({
|
|
77326
|
+
toast2({
|
|
77327
|
+
title: "Error",
|
|
77328
|
+
description: error.message,
|
|
77329
|
+
variant: "destructive"
|
|
77330
|
+
});
|
|
77296
77331
|
} finally {
|
|
77297
77332
|
setIsAlertOpen(false);
|
|
77298
77333
|
setItemToDelete(null);
|
|
@@ -77301,7 +77336,11 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77301
77336
|
};
|
|
77302
77337
|
const handleSubmit = () => {
|
|
77303
77338
|
if (!formState.name?.trim() || !formState.code?.trim()) {
|
|
77304
|
-
toast2({
|
|
77339
|
+
toast2({
|
|
77340
|
+
title: "Validation Error",
|
|
77341
|
+
description: "Code and Name are required.",
|
|
77342
|
+
variant: "destructive"
|
|
77343
|
+
});
|
|
77305
77344
|
return;
|
|
77306
77345
|
}
|
|
77307
77346
|
startTransition(async () => {
|
|
@@ -77310,75 +77349,291 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77310
77349
|
if (isControlled && onUpdate) {
|
|
77311
77350
|
await onUpdate({ ...currentItem, ...formState });
|
|
77312
77351
|
} else {
|
|
77313
|
-
MetadataService.updateLearningObjective(
|
|
77352
|
+
MetadataService.updateLearningObjective(
|
|
77353
|
+
currentItem.id,
|
|
77354
|
+
formState
|
|
77355
|
+
);
|
|
77314
77356
|
refreshData();
|
|
77315
77357
|
}
|
|
77316
|
-
toast2({
|
|
77358
|
+
toast2({
|
|
77359
|
+
title: "Success",
|
|
77360
|
+
description: "Learning Objective updated."
|
|
77361
|
+
});
|
|
77317
77362
|
} else {
|
|
77318
77363
|
if (isControlled && onAdd) {
|
|
77319
77364
|
await onAdd(formState);
|
|
77320
77365
|
} else {
|
|
77321
|
-
MetadataService.addLearningObjective(
|
|
77366
|
+
MetadataService.addLearningObjective(
|
|
77367
|
+
formState
|
|
77368
|
+
);
|
|
77322
77369
|
refreshData();
|
|
77323
77370
|
}
|
|
77324
|
-
toast2({
|
|
77371
|
+
toast2({
|
|
77372
|
+
title: "Success",
|
|
77373
|
+
description: "Learning Objective added."
|
|
77374
|
+
});
|
|
77325
77375
|
}
|
|
77326
77376
|
setIsDialogOpen(false);
|
|
77327
77377
|
} catch (error) {
|
|
77328
|
-
toast2({
|
|
77378
|
+
toast2({
|
|
77379
|
+
title: "Error",
|
|
77380
|
+
description: error.message,
|
|
77381
|
+
variant: "destructive"
|
|
77382
|
+
});
|
|
77329
77383
|
}
|
|
77330
77384
|
});
|
|
77331
77385
|
};
|
|
77332
77386
|
const handleImport = async (records) => {
|
|
77333
|
-
console.log(
|
|
77387
|
+
console.log(
|
|
77388
|
+
`[LO Manager] handleImport called with ${records.length} raw records.`
|
|
77389
|
+
);
|
|
77334
77390
|
if (!onBulkAdd) {
|
|
77335
77391
|
console.error("[LO Manager] onBulkAdd handler is not provided.");
|
|
77336
77392
|
return;
|
|
77337
77393
|
}
|
|
77338
77394
|
const parseStringToArray = (input) => {
|
|
77339
77395
|
if (Array.isArray(input)) return input;
|
|
77340
|
-
if (typeof input === "string")
|
|
77396
|
+
if (typeof input === "string")
|
|
77397
|
+
return input.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
77341
77398
|
return [];
|
|
77342
77399
|
};
|
|
77343
|
-
const validationResult = records.reduce(
|
|
77344
|
-
|
|
77345
|
-
|
|
77346
|
-
|
|
77347
|
-
|
|
77348
|
-
|
|
77349
|
-
|
|
77350
|
-
|
|
77351
|
-
|
|
77352
|
-
|
|
77353
|
-
|
|
77354
|
-
|
|
77355
|
-
|
|
77356
|
-
|
|
77357
|
-
|
|
77358
|
-
|
|
77359
|
-
|
|
77360
|
-
|
|
77361
|
-
|
|
77362
|
-
|
|
77363
|
-
|
|
77364
|
-
|
|
77365
|
-
|
|
77366
|
-
|
|
77400
|
+
const validationResult = records.reduce(
|
|
77401
|
+
(acc, rec) => {
|
|
77402
|
+
if (typeof rec["LO ID"] === "string" && rec["LO ID"].trim() && typeof rec["LO Description"] === "string" && rec["LO Description"].trim()) {
|
|
77403
|
+
acc.valid.push({
|
|
77404
|
+
code: rec["LO ID"],
|
|
77405
|
+
name: rec["LO ID"],
|
|
77406
|
+
description: rec["LO Description"],
|
|
77407
|
+
subject: rec["Subject"] || "",
|
|
77408
|
+
subjectCode: rec["Subject Code"] || rec["Subject"],
|
|
77409
|
+
category: rec["Category"] || "",
|
|
77410
|
+
categoryCode: rec["Category Code"] || rec["Category"],
|
|
77411
|
+
topic: rec["Topic"] || "",
|
|
77412
|
+
topicCode: rec["Topic Code"] || rec["Topic"],
|
|
77413
|
+
grade: rec["Grade"] || "",
|
|
77414
|
+
gradeCode: rec["Grade Code"] || rec["Grade"],
|
|
77415
|
+
keywords: parseStringToArray(rec["Keywords"]),
|
|
77416
|
+
stemElements: parseStringToArray(
|
|
77417
|
+
rec["STEM Element(s)"]
|
|
77418
|
+
),
|
|
77419
|
+
bloomLevelsGuideline: parseStringToArray(
|
|
77420
|
+
rec["Bloom\u2019s Level(s) Guideline"]
|
|
77421
|
+
)
|
|
77422
|
+
});
|
|
77423
|
+
} else {
|
|
77424
|
+
acc.invalidCount++;
|
|
77425
|
+
}
|
|
77426
|
+
return acc;
|
|
77427
|
+
},
|
|
77428
|
+
{ valid: [], invalidCount: 0 }
|
|
77429
|
+
);
|
|
77430
|
+
console.log(
|
|
77431
|
+
`[LO Manager] Validation complete. ${validationResult.valid.length} valid records found.`
|
|
77432
|
+
);
|
|
77367
77433
|
if (validationResult.invalidCount > 0) {
|
|
77368
77434
|
toast2({
|
|
77369
77435
|
title: "Import Warning",
|
|
77370
|
-
description: `${validationResult.invalidCount} records had invalid or missing '
|
|
77436
|
+
description: `${validationResult.invalidCount} records had invalid or missing 'LO ID' or 'LO Description' fields and were ignored.`,
|
|
77371
77437
|
variant: "destructive"
|
|
77372
77438
|
});
|
|
77373
77439
|
}
|
|
77374
77440
|
if (validationResult.valid.length > 0) {
|
|
77375
|
-
console.log(
|
|
77441
|
+
console.log(
|
|
77442
|
+
"[LO Manager] Calling onBulkAdd prop with validated data..."
|
|
77443
|
+
);
|
|
77376
77444
|
await onBulkAdd(validationResult.valid);
|
|
77377
77445
|
} else {
|
|
77378
77446
|
console.log("[LO Manager] No valid records to import.");
|
|
77379
77447
|
}
|
|
77380
77448
|
};
|
|
77381
|
-
return /* @__PURE__ */ React119__default.createElement(Card, null, /* @__PURE__ */ React119__default.createElement(CardHeader, null, /* @__PURE__ */ React119__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React119__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React119__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Learning Objectives"), /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center gap-2" }, onBulkAdd && /* @__PURE__ */ React119__default.createElement(MetadataImportControls, { metadataName: "Learning Objectives", onImport: handleImport }), /* @__PURE__ */ React119__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React119__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective")))), /* @__PURE__ */ React119__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React119__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React119__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React119__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React119__default.createElement(Table2, null, /* @__PURE__ */ React119__default.createElement(TableHeader, null, /* @__PURE__ */ React119__default.createElement(TableRow, null, /* @__PURE__ */ React119__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Topic"), /* @__PURE__ */ React119__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React119__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React119__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.subject || item.subjectCode), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.topic || item.topicCode), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React119__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React119__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "code" }, "Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e2) => handleFormChange("code", e2.target.value.toUpperCase()), disabled: !!currentItem })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "name" }, "Name (Description)"), /* @__PURE__ */ React119__default.createElement(Input, { id: "name", value: formState.name || "", onChange: (e2) => handleFormChange("name", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subject" }, "Subject Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "subject", value: formState.subject || "", onChange: (e2) => handleFormChange("subject", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject Code"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: subjects.map((s2) => ({ value: s2.code, label: s2.name })), value: formState.subjectCode || "", onChange: (val) => handleFormChange("subjectCode", val), placeholder: "Select a subject..." }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "category" }, "Category Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "category", value: formState.category || "", onChange: (e2) => handleFormChange("category", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "categoryCode" }, "Category Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "categoryCode", value: formState.categoryCode || "", onChange: (e2) => handleFormChange("categoryCode", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topic" }, "Topic Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "topic", value: formState.topic || "", onChange: (e2) => handleFormChange("topic", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topicCode" }, "Topic Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "topicCode", value: formState.topicCode || "", onChange: (e2) => handleFormChange("topicCode", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "grade" }, "Grade Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "grade", value: formState.grade || "", onChange: (e2) => handleFormChange("grade", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "gradeCode" }, "Grade Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "gradeCode", value: formState.gradeCode || "", onChange: (e2) => handleFormChange("gradeCode", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "keywords" }, "Keywords (comma-separated)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "keywords", value: formState.keywords?.join(", ") || "", onChange: (e2) => handleFormChange("keywords", e2.target.value.split(",").map((s2) => s2.trim())) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "stemElements" }, "STEM Elements (comma-separated)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "stemElements", value: formState.stemElements?.join(", ") || "", onChange: (e2) => handleFormChange("stemElements", e2.target.value.split(",").map((s2) => s2.trim())) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "bloomLevelsGuideline" }, "Bloom's Guideline (comma-separated)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "bloomLevelsGuideline", value: formState.bloomLevelsGuideline?.join(", ") || "", onChange: (e2) => handleFormChange("bloomLevelsGuideline", e2.target.value.split(",").map((s2) => s2.trim())) }))), /* @__PURE__ */ React119__default.createElement(DialogFooter, null, /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !formState.name?.trim() || !formState.code?.trim() }, isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React119__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React119__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React119__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React119__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React119__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React119__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React119__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
77449
|
+
return /* @__PURE__ */ React119__default.createElement(Card, null, /* @__PURE__ */ React119__default.createElement(CardHeader, null, /* @__PURE__ */ React119__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React119__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React119__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " ", "Manage Learning Objectives"), /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center gap-2" }, onBulkAdd && /* @__PURE__ */ React119__default.createElement(
|
|
77450
|
+
MetadataImportControls,
|
|
77451
|
+
{
|
|
77452
|
+
metadataName: "Learning Objectives",
|
|
77453
|
+
onImport: handleImport
|
|
77454
|
+
}
|
|
77455
|
+
), /* @__PURE__ */ React119__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React119__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective")))), /* @__PURE__ */ React119__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React119__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React119__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React119__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React119__default.createElement(Table2, null, /* @__PURE__ */ React119__default.createElement(TableHeader, null, /* @__PURE__ */ React119__default.createElement(TableRow, null, /* @__PURE__ */ React119__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Topic"), /* @__PURE__ */ React119__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React119__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React119__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.subject || item.subjectCode), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.topic || item.topicCode), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React119__default.createElement(
|
|
77456
|
+
Button,
|
|
77457
|
+
{
|
|
77458
|
+
variant: "ghost",
|
|
77459
|
+
size: "icon",
|
|
77460
|
+
onClick: () => handleEditItem(item),
|
|
77461
|
+
className: "mr-2"
|
|
77462
|
+
},
|
|
77463
|
+
/* @__PURE__ */ React119__default.createElement(PenLine, { className: "h-4 w-4" })
|
|
77464
|
+
), /* @__PURE__ */ React119__default.createElement(
|
|
77465
|
+
Button,
|
|
77466
|
+
{
|
|
77467
|
+
variant: "ghost",
|
|
77468
|
+
size: "icon",
|
|
77469
|
+
onClick: () => handleDeleteItem(item),
|
|
77470
|
+
className: "text-destructive hover:text-destructive"
|
|
77471
|
+
},
|
|
77472
|
+
/* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4" })
|
|
77473
|
+
))))))), /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React119__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "code" }, "Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77474
|
+
Input,
|
|
77475
|
+
{
|
|
77476
|
+
id: "code",
|
|
77477
|
+
value: formState.code || "",
|
|
77478
|
+
onChange: (e2) => handleFormChange(
|
|
77479
|
+
"code",
|
|
77480
|
+
e2.target.value.toUpperCase()
|
|
77481
|
+
),
|
|
77482
|
+
disabled: !!currentItem
|
|
77483
|
+
}
|
|
77484
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "name" }, "Name (Description)"), /* @__PURE__ */ React119__default.createElement(
|
|
77485
|
+
Input,
|
|
77486
|
+
{
|
|
77487
|
+
id: "name",
|
|
77488
|
+
value: formState.name || "",
|
|
77489
|
+
onChange: (e2) => handleFormChange(
|
|
77490
|
+
"name",
|
|
77491
|
+
e2.target.value
|
|
77492
|
+
)
|
|
77493
|
+
}
|
|
77494
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subject" }, "Subject Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77495
|
+
Input,
|
|
77496
|
+
{
|
|
77497
|
+
id: "subject",
|
|
77498
|
+
value: formState.subject || "",
|
|
77499
|
+
onChange: (e2) => handleFormChange(
|
|
77500
|
+
"subject",
|
|
77501
|
+
e2.target.value
|
|
77502
|
+
)
|
|
77503
|
+
}
|
|
77504
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77505
|
+
EditableCombobox,
|
|
77506
|
+
{
|
|
77507
|
+
options: subjects.map((s2) => ({
|
|
77508
|
+
value: s2.code,
|
|
77509
|
+
label: s2.name
|
|
77510
|
+
})),
|
|
77511
|
+
value: formState.subjectCode || "",
|
|
77512
|
+
onChange: (val) => handleFormChange("subjectCode", val),
|
|
77513
|
+
placeholder: "Select a subject..."
|
|
77514
|
+
}
|
|
77515
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "category" }, "Category Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77516
|
+
Input,
|
|
77517
|
+
{
|
|
77518
|
+
id: "category",
|
|
77519
|
+
value: formState.category || "",
|
|
77520
|
+
onChange: (e2) => handleFormChange(
|
|
77521
|
+
"category",
|
|
77522
|
+
e2.target.value
|
|
77523
|
+
)
|
|
77524
|
+
}
|
|
77525
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "categoryCode" }, "Category Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77526
|
+
Input,
|
|
77527
|
+
{
|
|
77528
|
+
id: "categoryCode",
|
|
77529
|
+
value: formState.categoryCode || "",
|
|
77530
|
+
onChange: (e2) => handleFormChange(
|
|
77531
|
+
"categoryCode",
|
|
77532
|
+
e2.target.value
|
|
77533
|
+
)
|
|
77534
|
+
}
|
|
77535
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topic" }, "Topic Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77536
|
+
Input,
|
|
77537
|
+
{
|
|
77538
|
+
id: "topic",
|
|
77539
|
+
value: formState.topic || "",
|
|
77540
|
+
onChange: (e2) => handleFormChange(
|
|
77541
|
+
"topic",
|
|
77542
|
+
e2.target.value
|
|
77543
|
+
)
|
|
77544
|
+
}
|
|
77545
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topicCode" }, "Topic Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77546
|
+
Input,
|
|
77547
|
+
{
|
|
77548
|
+
id: "topicCode",
|
|
77549
|
+
value: formState.topicCode || "",
|
|
77550
|
+
onChange: (e2) => handleFormChange(
|
|
77551
|
+
"topicCode",
|
|
77552
|
+
e2.target.value
|
|
77553
|
+
)
|
|
77554
|
+
}
|
|
77555
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "grade" }, "Grade Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77556
|
+
Input,
|
|
77557
|
+
{
|
|
77558
|
+
id: "grade",
|
|
77559
|
+
value: formState.grade || "",
|
|
77560
|
+
onChange: (e2) => handleFormChange(
|
|
77561
|
+
"grade",
|
|
77562
|
+
e2.target.value
|
|
77563
|
+
)
|
|
77564
|
+
}
|
|
77565
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "gradeCode" }, "Grade Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77566
|
+
Input,
|
|
77567
|
+
{
|
|
77568
|
+
id: "gradeCode",
|
|
77569
|
+
value: formState.gradeCode || "",
|
|
77570
|
+
onChange: (e2) => handleFormChange(
|
|
77571
|
+
"gradeCode",
|
|
77572
|
+
e2.target.value
|
|
77573
|
+
)
|
|
77574
|
+
}
|
|
77575
|
+
))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "keywords" }, "Keywords (comma-separated)"), /* @__PURE__ */ React119__default.createElement(
|
|
77576
|
+
Textarea,
|
|
77577
|
+
{
|
|
77578
|
+
id: "keywords",
|
|
77579
|
+
value: formState.keywords?.join(", ") || "",
|
|
77580
|
+
onChange: (e2) => handleFormChange(
|
|
77581
|
+
"keywords",
|
|
77582
|
+
e2.target.value.split(",").map((s2) => s2.trim())
|
|
77583
|
+
)
|
|
77584
|
+
}
|
|
77585
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "stemElements" }, "STEM Elements (comma-separated)"), /* @__PURE__ */ React119__default.createElement(
|
|
77586
|
+
Textarea,
|
|
77587
|
+
{
|
|
77588
|
+
id: "stemElements",
|
|
77589
|
+
value: formState.stemElements?.join(", ") || "",
|
|
77590
|
+
onChange: (e2) => handleFormChange(
|
|
77591
|
+
"stemElements",
|
|
77592
|
+
e2.target.value.split(",").map((s2) => s2.trim())
|
|
77593
|
+
)
|
|
77594
|
+
}
|
|
77595
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "bloomLevelsGuideline" }, "Bloom's Guideline (comma-separated)"), /* @__PURE__ */ React119__default.createElement(
|
|
77596
|
+
Textarea,
|
|
77597
|
+
{
|
|
77598
|
+
id: "bloomLevelsGuideline",
|
|
77599
|
+
value: formState.bloomLevelsGuideline?.join(
|
|
77600
|
+
", "
|
|
77601
|
+
) || "",
|
|
77602
|
+
onChange: (e2) => handleFormChange(
|
|
77603
|
+
"bloomLevelsGuideline",
|
|
77604
|
+
e2.target.value.split(",").map((s2) => s2.trim())
|
|
77605
|
+
)
|
|
77606
|
+
}
|
|
77607
|
+
))), /* @__PURE__ */ React119__default.createElement(DialogFooter, null, /* @__PURE__ */ React119__default.createElement(
|
|
77608
|
+
Button,
|
|
77609
|
+
{
|
|
77610
|
+
type: "button",
|
|
77611
|
+
variant: "outline",
|
|
77612
|
+
onClick: () => setIsDialogOpen(false),
|
|
77613
|
+
disabled: isPending
|
|
77614
|
+
},
|
|
77615
|
+
"Cancel"
|
|
77616
|
+
), /* @__PURE__ */ React119__default.createElement(
|
|
77617
|
+
Button,
|
|
77618
|
+
{
|
|
77619
|
+
type: "submit",
|
|
77620
|
+
onClick: handleSubmit,
|
|
77621
|
+
disabled: isPending || !formState.name?.trim() || !formState.code?.trim()
|
|
77622
|
+
},
|
|
77623
|
+
isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
77624
|
+
" ",
|
|
77625
|
+
"Save"
|
|
77626
|
+
)))), /* @__PURE__ */ React119__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React119__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React119__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React119__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React119__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React119__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React119__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__default.createElement(
|
|
77627
|
+
AlertDialogAction2,
|
|
77628
|
+
{
|
|
77629
|
+
onClick: confirmDelete,
|
|
77630
|
+
disabled: isPending,
|
|
77631
|
+
className: "bg-destructive hover:bg-destructive/90"
|
|
77632
|
+
},
|
|
77633
|
+
isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
77634
|
+
" ",
|
|
77635
|
+
"Delete"
|
|
77636
|
+
))))));
|
|
77382
77637
|
}
|
|
77383
77638
|
|
|
77384
77639
|
// src/react-ui/components/metadata/ContextManager.tsx
|