@anantagnanam/lms 0.2.0 → 0.3.0
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/README.md +19 -2
- package/astro/assignment-player.ts +231 -0
- package/astro/client.ts +24 -1
- package/astro/components/AssignmentFeedback.astro +32 -0
- package/astro/components/AssignmentRubric.astro +27 -0
- package/astro/components/LearnerDashboard.astro +3 -0
- package/astro/components/LearningShell.astro +6 -0
- package/astro/components/LessonContent.astro +16 -2
- package/astro/components/LessonPlayer.astro +126 -38
- package/astro/draft-queue.ts +95 -0
- package/astro/media-player.ts +26 -1
- package/astro/pages/author-preview.astro +2 -0
- package/astro/pages/study.astro +180 -0
- package/astro/quiz-drafts.ts +12 -76
- package/astro/study-tools.ts +386 -0
- package/astro/styles.css +18 -0
- package/astro/transcript-search.ts +56 -0
- package/dist/admin.js +172 -12
- package/dist/admin.js.map +1 -1
- package/dist/assignments-CsuAjxGO.js +75 -0
- package/dist/assignments-CsuAjxGO.js.map +1 -0
- package/dist/astro.js +1 -0
- package/dist/astro.js.map +1 -1
- package/dist/{constants-Cnx7k82Z.js → constants-DyQbwNbP.js} +2 -2
- package/dist/{constants-Cnx7k82Z.js.map → constants-DyQbwNbP.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/runtime.d.ts +26 -5
- package/dist/runtime.js +307 -16
- package/dist/runtime.js.map +1 -1
- package/dist/schemas.d.ts +69 -3
- package/dist/schemas.js +47 -6
- package/dist/schemas.js.map +1 -1
- package/dist/server.d.ts +9 -2
- package/dist/server.js +6 -3
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +67 -2
- package/package.json +1 -1
- package/dist/errors-ChzJS9al.js +0 -16
- package/dist/errors-ChzJS9al.js.map +0 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
var LmsError = class extends Error {
|
|
3
|
+
constructor(code, message, status = 400) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.name = "PluginRouteError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
function invariant(condition, code, message, status = 400) {
|
|
11
|
+
if (!condition) throw new LmsError(code, message, status);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/assignments.ts
|
|
16
|
+
function emptyAssignmentDraft() {
|
|
17
|
+
return {
|
|
18
|
+
body: "",
|
|
19
|
+
attachmentUrl: null,
|
|
20
|
+
revision: 0,
|
|
21
|
+
updatedAt: null
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function assignmentBlock(assignment, progress, now) {
|
|
25
|
+
if (progress.completedAt) return {
|
|
26
|
+
code: "ASSIGNMENT_PASSED",
|
|
27
|
+
message: "This assignment has already been passed.",
|
|
28
|
+
status: 409
|
|
29
|
+
};
|
|
30
|
+
if (assignment.dueAt && now.getTime() > Date.parse(assignment.dueAt)) return {
|
|
31
|
+
code: "ASSIGNMENT_CLOSED",
|
|
32
|
+
message: "The assignment deadline has passed.",
|
|
33
|
+
status: 403
|
|
34
|
+
};
|
|
35
|
+
const last = progress.assignments.at(-1);
|
|
36
|
+
if (last && (last.status !== "graded" || !assignment.allowResubmission)) return {
|
|
37
|
+
code: "SUBMISSION_PENDING",
|
|
38
|
+
message: last.status === "submitted" ? "Wait for grading before submitting again." : "Resubmission is not enabled for this assignment.",
|
|
39
|
+
status: 409
|
|
40
|
+
};
|
|
41
|
+
if (progress.assignments.length >= 10) return {
|
|
42
|
+
code: "SUBMISSION_LIMIT",
|
|
43
|
+
message: "The assignment submission limit has been reached.",
|
|
44
|
+
status: 403
|
|
45
|
+
};
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
/** Only the submission's snapshot can determine the score, never the latest course draft. */
|
|
49
|
+
function assignmentGrade(submission, points, scores = []) {
|
|
50
|
+
const rubric = submission.rubric ?? [];
|
|
51
|
+
if (!rubric.length) {
|
|
52
|
+
invariant(!scores.length, "INVALID_GRADE", "This submission has no grading rubric.");
|
|
53
|
+
invariant(points !== void 0 && points <= submission.maxPoints, "INVALID_GRADE", "Supply a score within this submission's maximum points.");
|
|
54
|
+
return {
|
|
55
|
+
points,
|
|
56
|
+
rubricScores: []
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
invariant(scores.length === rubric.length && new Set(scores.map((item) => item.criterionId)).size === rubric.length, "INVALID_GRADE", "Score each rubric criterion exactly once.");
|
|
60
|
+
const rubricScores = rubric.map((criterion) => {
|
|
61
|
+
const score = scores.find((item) => item.criterionId === criterion.id);
|
|
62
|
+
invariant(score && score.points <= criterion.maxPoints, "INVALID_GRADE", "Each score must match a rubric criterion and stay within its maximum.");
|
|
63
|
+
return score;
|
|
64
|
+
});
|
|
65
|
+
const total = rubricScores.reduce((sum, score) => sum + score.points, 0);
|
|
66
|
+
invariant(points === void 0 || points === total, "INVALID_GRADE", "Total points must match the rubric scores.");
|
|
67
|
+
return {
|
|
68
|
+
points: total,
|
|
69
|
+
rubricScores
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
export { invariant as a, LmsError as i, assignmentGrade as n, emptyAssignmentDraft as r, assignmentBlock as t };
|
|
75
|
+
//# sourceMappingURL=assignments-CsuAjxGO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assignments-CsuAjxGO.js","names":[],"sources":["../src/errors.ts","../src/assignments.ts"],"sourcesContent":["export class LmsError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status = 400,\n ) {\n super(message);\n this.name = \"PluginRouteError\";\n }\n}\n\nexport function invariant(\n condition: unknown,\n code: string,\n message: string,\n status = 400,\n): asserts condition {\n if (!condition) throw new LmsError(code, message, status);\n}\n","import type {\n AssignmentDraft,\n AssignmentSubmission,\n Lesson,\n LessonProgress,\n RubricScore,\n} from \"./types.js\";\nimport { invariant } from \"./errors.js\";\n\nexport function emptyAssignmentDraft(): AssignmentDraft {\n return { body: \"\", attachmentUrl: null, revision: 0, updatedAt: null };\n}\n\nexport function assignmentBlock(\n assignment: NonNullable<Lesson[\"assignment\"]>,\n progress: Pick<LessonProgress, \"completedAt\" | \"assignments\">,\n now: Date,\n) {\n if (progress.completedAt)\n return {\n code: \"ASSIGNMENT_PASSED\",\n message: \"This assignment has already been passed.\",\n status: 409,\n };\n if (assignment.dueAt && now.getTime() > Date.parse(assignment.dueAt))\n return {\n code: \"ASSIGNMENT_CLOSED\",\n message: \"The assignment deadline has passed.\",\n status: 403,\n };\n const last = progress.assignments.at(-1);\n if (last && (last.status !== \"graded\" || !assignment.allowResubmission))\n return {\n code: \"SUBMISSION_PENDING\",\n message:\n last.status === \"submitted\"\n ? \"Wait for grading before submitting again.\"\n : \"Resubmission is not enabled for this assignment.\",\n status: 409,\n };\n if (progress.assignments.length >= 10)\n return {\n code: \"SUBMISSION_LIMIT\",\n message: \"The assignment submission limit has been reached.\",\n status: 403,\n };\n return null;\n}\n\n/** Only the submission's snapshot can determine the score, never the latest course draft. */\nexport function assignmentGrade(\n submission: AssignmentSubmission,\n points: number | undefined,\n scores: RubricScore[] = [],\n) {\n const rubric = submission.rubric ?? [];\n if (!rubric.length) {\n invariant(!scores.length, \"INVALID_GRADE\", \"This submission has no grading rubric.\");\n invariant(\n points !== undefined && points <= submission.maxPoints,\n \"INVALID_GRADE\",\n \"Supply a score within this submission's maximum points.\",\n );\n return { points, rubricScores: [] };\n }\n invariant(\n scores.length === rubric.length &&\n new Set(scores.map((item) => item.criterionId)).size === rubric.length,\n \"INVALID_GRADE\",\n \"Score each rubric criterion exactly once.\",\n );\n const rubricScores = rubric.map((criterion) => {\n const score = scores.find((item) => item.criterionId === criterion.id);\n invariant(\n score && score.points <= criterion.maxPoints,\n \"INVALID_GRADE\",\n \"Each score must match a rubric criterion and stay within its maximum.\",\n );\n return score;\n });\n const total = rubricScores.reduce((sum, score) => sum + score.points, 0);\n invariant(\n points === undefined || points === total,\n \"INVALID_GRADE\",\n \"Total points must match the rubric scores.\",\n );\n return { points: total, rubricScores };\n}\n"],"mappings":";AAAA,IAAa,WAAb,cAA8B,MAAM;CAClC,YACE,AAAS,MACT,SACA,AAAS,SAAS,KAClB;AACA,QAAM,QAAQ;EAJL;EAEA;AAGT,OAAK,OAAO;;;AAIhB,SAAgB,UACd,WACA,MACA,SACA,SAAS,KACU;AACnB,KAAI,CAAC,UAAW,OAAM,IAAI,SAAS,MAAM,SAAS,OAAO;;;;;ACR3D,SAAgB,uBAAwC;AACtD,QAAO;EAAE,MAAM;EAAI,eAAe;EAAM,UAAU;EAAG,WAAW;EAAM;;AAGxE,SAAgB,gBACd,YACA,UACA,KACA;AACA,KAAI,SAAS,YACX,QAAO;EACL,MAAM;EACN,SAAS;EACT,QAAQ;EACT;AACH,KAAI,WAAW,SAAS,IAAI,SAAS,GAAG,KAAK,MAAM,WAAW,MAAM,CAClE,QAAO;EACL,MAAM;EACN,SAAS;EACT,QAAQ;EACT;CACH,MAAM,OAAO,SAAS,YAAY,GAAG,GAAG;AACxC,KAAI,SAAS,KAAK,WAAW,YAAY,CAAC,WAAW,mBACnD,QAAO;EACL,MAAM;EACN,SACE,KAAK,WAAW,cACZ,8CACA;EACN,QAAQ;EACT;AACH,KAAI,SAAS,YAAY,UAAU,GACjC,QAAO;EACL,MAAM;EACN,SAAS;EACT,QAAQ;EACT;AACH,QAAO;;;AAIT,SAAgB,gBACd,YACA,QACA,SAAwB,EAAE,EAC1B;CACA,MAAM,SAAS,WAAW,UAAU,EAAE;AACtC,KAAI,CAAC,OAAO,QAAQ;AAClB,YAAU,CAAC,OAAO,QAAQ,iBAAiB,yCAAyC;AACpF,YACE,WAAW,UAAa,UAAU,WAAW,WAC7C,iBACA,0DACD;AACD,SAAO;GAAE;GAAQ,cAAc,EAAE;GAAE;;AAErC,WACE,OAAO,WAAW,OAAO,UACvB,IAAI,IAAI,OAAO,KAAK,SAAS,KAAK,YAAY,CAAC,CAAC,SAAS,OAAO,QAClE,iBACA,4CACD;CACD,MAAM,eAAe,OAAO,KAAK,cAAc;EAC7C,MAAM,QAAQ,OAAO,MAAM,SAAS,KAAK,gBAAgB,UAAU,GAAG;AACtE,YACE,SAAS,MAAM,UAAU,UAAU,WACnC,iBACA,wEACD;AACD,SAAO;GACP;CACF,MAAM,QAAQ,aAAa,QAAQ,KAAK,UAAU,MAAM,MAAM,QAAQ,EAAE;AACxE,WACE,WAAW,UAAa,WAAW,OACnC,iBACA,6CACD;AACD,QAAO;EAAE,QAAQ;EAAO;EAAc"}
|
package/dist/astro.js
CHANGED
|
@@ -25,6 +25,7 @@ function lmsAstro(options = {}) {
|
|
|
25
25
|
[`${basePath}/courses/[slug]/lessons/[lessonId]`, "lesson.astro"],
|
|
26
26
|
[`${basePath}/my-learning`, "dashboard.astro"],
|
|
27
27
|
[`${basePath}/my-learning/library`, "library.astro"],
|
|
28
|
+
[`${basePath}/my-learning/study`, "study.astro"],
|
|
28
29
|
[`${basePath}/paths`, "paths.astro"],
|
|
29
30
|
[`${basePath}/certificates/[certificateId]`, "certificate.astro"],
|
|
30
31
|
[`${basePath}/teach`, "teach.astro"],
|
package/dist/astro.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"astro.js","names":[],"sources":["../src/astro.ts"],"sourcesContent":["import type { AstroIntegration } from \"astro\";\nimport { fileURLToPath } from \"node:url\";\nimport type { LmsOptions } from \"./types.js\";\nimport { normalizeLmsOptions } from \"./config.js\";\n\nexport interface LmsAstroOptions extends LmsOptions {\n layout?: string;\n}\n\nexport function lmsAstro(options: LmsAstroOptions = {}): AstroIntegration {\n const { basePath, loginPath } = normalizeLmsOptions(options);\n return {\n name: \"@anantagnanam/lms\",\n hooks: {\n \"astro:config:setup\": ({ config, injectRoute, updateConfig }) => {\n if (config.output !== \"server\") throw new Error(\"The LMS requires Astro output: server.\");\n const layouts = options.layout\n ? fileURLToPath(new URL(options.layout, config.root))\n : fileURLToPath(new URL(\"../astro/layouts/AcademyLayout.astro\", import.meta.url));\n const virtual = {\n \"virtual:anantagnanam-lms/config\": `export const basePath = ${JSON.stringify(basePath)}; export const loginPath = ${JSON.stringify(loginPath)};`,\n \"virtual:anantagnanam-lms/layout\": `export { default } from ${JSON.stringify(layouts.replaceAll(\"\\\\\", \"/\"))};`,\n };\n updateConfig({\n vite: {\n plugins: [\n {\n name: \"anantagnanam-lms-pages\",\n resolveId: (id) => (id in virtual ? `\\0${id}` : undefined),\n load: (id) => virtual[id.replace(/^\\0/, \"\") as keyof typeof virtual],\n },\n ],\n },\n });\n const pages = [\n [basePath, \"index.astro\"],\n [`${basePath}/courses/[slug]`, \"course.astro\"],\n [`${basePath}/courses/[slug]/lessons/[lessonId]`, \"lesson.astro\"],\n [`${basePath}/my-learning`, \"dashboard.astro\"],\n [`${basePath}/my-learning/library`, \"library.astro\"],\n [`${basePath}/paths`, \"paths.astro\"],\n [`${basePath}/certificates/[certificateId]`, \"certificate.astro\"],\n [`${basePath}/teach`, \"teach.astro\"],\n [`${basePath}/teach/courses/[courseId]/lessons/[lessonId]`, \"author-preview.astro\"],\n [`${basePath}/cohorts/[cohortId]`, \"cohort.astro\"],\n ];\n for (const [pattern, file] of pages)\n injectRoute({\n pattern: pattern!,\n entrypoint: fileURLToPath(new URL(`../astro/pages/${file}`, import.meta.url)),\n prerender: false,\n });\n },\n \"astro:config:done\": ({ injectTypes }) => {\n injectTypes({\n filename: \"anantagnanam-lms.d.ts\",\n content:\n 'declare module \"virtual:anantagnanam-lms/config\" { export const basePath: string; export const loginPath: string; }\\ndeclare module \"virtual:anantagnanam-lms/layout\" { const Layout: import(\"astro/runtime/server/index.js\").AstroComponentFactory; export default Layout; }',\n });\n },\n },\n };\n}\nexport default lmsAstro;\n"],"mappings":";;;;AASA,SAAgB,SAAS,UAA2B,EAAE,EAAoB;CACxE,MAAM,EAAE,UAAU,cAAc,oBAAoB,QAAQ;AAC5D,QAAO;EACL,MAAM;EACN,OAAO;GACL,uBAAuB,EAAE,QAAQ,aAAa,mBAAmB;AAC/D,QAAI,OAAO,WAAW,SAAU,OAAM,IAAI,MAAM,yCAAyC;IACzF,MAAM,UAAU,QAAQ,SACpB,cAAc,IAAI,IAAI,QAAQ,QAAQ,OAAO,KAAK,CAAC,GACnD,cAAc,IAAI,IAAI,wCAAwC,OAAO,KAAK,IAAI,CAAC;IACnF,MAAM,UAAU;KACd,mCAAmC,2BAA2B,KAAK,UAAU,SAAS,CAAC,6BAA6B,KAAK,UAAU,UAAU,CAAC;KAC9I,mCAAmC,2BAA2B,KAAK,UAAU,QAAQ,WAAW,MAAM,IAAI,CAAC,CAAC;KAC7G;AACD,iBAAa,EACX,MAAM,EACJ,SAAS,CACP;KACE,MAAM;KACN,YAAY,OAAQ,MAAM,UAAU,KAAK,OAAO;KAChD,OAAO,OAAO,QAAQ,GAAG,QAAQ,OAAO,GAAG;KAC5C,CACF,EACF,EACF,CAAC;IACF,MAAM,QAAQ;KACZ,CAAC,UAAU,cAAc;KACzB,CAAC,GAAG,SAAS,kBAAkB,eAAe;KAC9C,CAAC,GAAG,SAAS,qCAAqC,eAAe;KACjE,CAAC,GAAG,SAAS,eAAe,kBAAkB;KAC9C,CAAC,GAAG,SAAS,uBAAuB,gBAAgB;KACpD,CAAC,GAAG,SAAS,SAAS,cAAc;KACpC,CAAC,GAAG,SAAS,gCAAgC,oBAAoB;KACjE,CAAC,GAAG,SAAS,SAAS,cAAc;KACpC,CAAC,GAAG,SAAS,+CAA+C,uBAAuB;KACnF,CAAC,GAAG,SAAS,sBAAsB,eAAe;KACnD;AACD,SAAK,MAAM,CAAC,SAAS,SAAS,MAC5B,aAAY;KACD;KACT,YAAY,cAAc,IAAI,IAAI,kBAAkB,QAAQ,OAAO,KAAK,IAAI,CAAC;KAC7E,WAAW;KACZ,CAAC;;GAEN,sBAAsB,EAAE,kBAAkB;AACxC,gBAAY;KACV,UAAU;KACV,SACE;KACH,CAAC;;GAEL;EACF"}
|
|
1
|
+
{"version":3,"file":"astro.js","names":[],"sources":["../src/astro.ts"],"sourcesContent":["import type { AstroIntegration } from \"astro\";\nimport { fileURLToPath } from \"node:url\";\nimport type { LmsOptions } from \"./types.js\";\nimport { normalizeLmsOptions } from \"./config.js\";\n\nexport interface LmsAstroOptions extends LmsOptions {\n layout?: string;\n}\n\nexport function lmsAstro(options: LmsAstroOptions = {}): AstroIntegration {\n const { basePath, loginPath } = normalizeLmsOptions(options);\n return {\n name: \"@anantagnanam/lms\",\n hooks: {\n \"astro:config:setup\": ({ config, injectRoute, updateConfig }) => {\n if (config.output !== \"server\") throw new Error(\"The LMS requires Astro output: server.\");\n const layouts = options.layout\n ? fileURLToPath(new URL(options.layout, config.root))\n : fileURLToPath(new URL(\"../astro/layouts/AcademyLayout.astro\", import.meta.url));\n const virtual = {\n \"virtual:anantagnanam-lms/config\": `export const basePath = ${JSON.stringify(basePath)}; export const loginPath = ${JSON.stringify(loginPath)};`,\n \"virtual:anantagnanam-lms/layout\": `export { default } from ${JSON.stringify(layouts.replaceAll(\"\\\\\", \"/\"))};`,\n };\n updateConfig({\n vite: {\n plugins: [\n {\n name: \"anantagnanam-lms-pages\",\n resolveId: (id) => (id in virtual ? `\\0${id}` : undefined),\n load: (id) => virtual[id.replace(/^\\0/, \"\") as keyof typeof virtual],\n },\n ],\n },\n });\n const pages = [\n [basePath, \"index.astro\"],\n [`${basePath}/courses/[slug]`, \"course.astro\"],\n [`${basePath}/courses/[slug]/lessons/[lessonId]`, \"lesson.astro\"],\n [`${basePath}/my-learning`, \"dashboard.astro\"],\n [`${basePath}/my-learning/library`, \"library.astro\"],\n [`${basePath}/my-learning/study`, \"study.astro\"],\n [`${basePath}/paths`, \"paths.astro\"],\n [`${basePath}/certificates/[certificateId]`, \"certificate.astro\"],\n [`${basePath}/teach`, \"teach.astro\"],\n [`${basePath}/teach/courses/[courseId]/lessons/[lessonId]`, \"author-preview.astro\"],\n [`${basePath}/cohorts/[cohortId]`, \"cohort.astro\"],\n ];\n for (const [pattern, file] of pages)\n injectRoute({\n pattern: pattern!,\n entrypoint: fileURLToPath(new URL(`../astro/pages/${file}`, import.meta.url)),\n prerender: false,\n });\n },\n \"astro:config:done\": ({ injectTypes }) => {\n injectTypes({\n filename: \"anantagnanam-lms.d.ts\",\n content:\n 'declare module \"virtual:anantagnanam-lms/config\" { export const basePath: string; export const loginPath: string; }\\ndeclare module \"virtual:anantagnanam-lms/layout\" { const Layout: import(\"astro/runtime/server/index.js\").AstroComponentFactory; export default Layout; }',\n });\n },\n },\n };\n}\nexport default lmsAstro;\n"],"mappings":";;;;AASA,SAAgB,SAAS,UAA2B,EAAE,EAAoB;CACxE,MAAM,EAAE,UAAU,cAAc,oBAAoB,QAAQ;AAC5D,QAAO;EACL,MAAM;EACN,OAAO;GACL,uBAAuB,EAAE,QAAQ,aAAa,mBAAmB;AAC/D,QAAI,OAAO,WAAW,SAAU,OAAM,IAAI,MAAM,yCAAyC;IACzF,MAAM,UAAU,QAAQ,SACpB,cAAc,IAAI,IAAI,QAAQ,QAAQ,OAAO,KAAK,CAAC,GACnD,cAAc,IAAI,IAAI,wCAAwC,OAAO,KAAK,IAAI,CAAC;IACnF,MAAM,UAAU;KACd,mCAAmC,2BAA2B,KAAK,UAAU,SAAS,CAAC,6BAA6B,KAAK,UAAU,UAAU,CAAC;KAC9I,mCAAmC,2BAA2B,KAAK,UAAU,QAAQ,WAAW,MAAM,IAAI,CAAC,CAAC;KAC7G;AACD,iBAAa,EACX,MAAM,EACJ,SAAS,CACP;KACE,MAAM;KACN,YAAY,OAAQ,MAAM,UAAU,KAAK,OAAO;KAChD,OAAO,OAAO,QAAQ,GAAG,QAAQ,OAAO,GAAG;KAC5C,CACF,EACF,EACF,CAAC;IACF,MAAM,QAAQ;KACZ,CAAC,UAAU,cAAc;KACzB,CAAC,GAAG,SAAS,kBAAkB,eAAe;KAC9C,CAAC,GAAG,SAAS,qCAAqC,eAAe;KACjE,CAAC,GAAG,SAAS,eAAe,kBAAkB;KAC9C,CAAC,GAAG,SAAS,uBAAuB,gBAAgB;KACpD,CAAC,GAAG,SAAS,qBAAqB,cAAc;KAChD,CAAC,GAAG,SAAS,SAAS,cAAc;KACpC,CAAC,GAAG,SAAS,gCAAgC,oBAAoB;KACjE,CAAC,GAAG,SAAS,SAAS,cAAc;KACpC,CAAC,GAAG,SAAS,+CAA+C,uBAAuB;KACnF,CAAC,GAAG,SAAS,sBAAsB,eAAe;KACnD;AACD,SAAK,MAAM,CAAC,SAAS,SAAS,MAC5B,aAAY;KACD;KACT,YAAY,cAAc,IAAI,IAAI,kBAAkB,QAAQ,OAAO,KAAK,IAAI,CAAC;KAC7E,WAAW;KACZ,CAAC;;GAEN,sBAAsB,EAAE,kBAAkB;AACxC,gBAAY;KACV,UAAU;KACV,SACE;KACH,CAAC;;GAEL;EACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/constants.ts
|
|
2
2
|
const PLUGIN_ID = "anantagnanam-lms";
|
|
3
|
-
const PLUGIN_VERSION = "0.
|
|
3
|
+
const PLUGIN_VERSION = "0.3.0";
|
|
4
4
|
const API_BASE = `/_emdash/api/plugins/${PLUGIN_ID}`;
|
|
5
5
|
const MAX_DOCUMENT_BYTES = 95e4;
|
|
6
6
|
const storage = {
|
|
@@ -158,4 +158,4 @@ const adminPages = [
|
|
|
158
158
|
|
|
159
159
|
//#endregion
|
|
160
160
|
export { adminPages as a, PLUGIN_VERSION as i, MAX_DOCUMENT_BYTES as n, storage as o, PLUGIN_ID as r, API_BASE as t };
|
|
161
|
-
//# sourceMappingURL=constants-
|
|
161
|
+
//# sourceMappingURL=constants-DyQbwNbP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants-
|
|
1
|
+
{"version":3,"file":"constants-DyQbwNbP.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["export const PLUGIN_ID = \"anantagnanam-lms\";\nexport const PLUGIN_VERSION = \"0.3.0\";\nexport const API_BASE = `/_emdash/api/plugins/${PLUGIN_ID}`;\nexport const MAX_DOCUMENT_BYTES = 950_000;\n\nimport type { PluginStorageConfig } from \"emdash\";\n\nexport const storage = {\n courses: {\n indexes: [\n \"status\",\n \"title\",\n \"searchTitle\",\n \"category\",\n \"level\",\n \"language\",\n \"updatedAt\",\n \"createdBy\",\n \"createdAt\",\n ],\n uniqueIndexes: [\"slug\"],\n },\n course_revisions: { indexes: [\"courseId\", \"createdAt\"] },\n course_editions: { indexes: [\"courseId\", \"createdAt\"] },\n migrations: { indexes: [\"phase\"] },\n preferences: { indexes: [] },\n saved_courses: { indexes: [\"userId\", \"saved\", \"updatedAt\"] },\n learning_paths: { indexes: [\"status\", \"updatedAt\"] },\n path_enrollments: { indexes: [\"userId\", \"pathId\", \"joinedAt\"] },\n enrollments: {\n indexes: [\n \"userId\",\n \"courseId\",\n \"status\",\n \"accessStatus\",\n \"accessSource\",\n \"enrolledAt\",\n \"completedAt\",\n \"lastActivityAt\",\n \"cohortId\",\n [\"courseId\", \"status\"],\n [\"userId\", \"status\"],\n ],\n },\n certificates: { indexes: [\"userId\", \"courseId\"] },\n discussions: {\n indexes: [\n \"courseId\",\n \"lessonId\",\n \"authorId\",\n \"status\",\n \"createdAt\",\n \"parentId\",\n [\"courseId\", \"createdAt\"],\n ],\n },\n reviews: { indexes: [\"courseId\", \"userId\", \"status\", \"createdAt\"] },\n cohorts: { indexes: [\"title\", \"createdAt\", \"createdBy\"] },\n cohort_enrollments: { indexes: [\"cohortId\", \"userId\", \"status\", \"requestedAt\"] },\n notifications: { indexes: [\"userId\", \"read\", \"createdAt\", \"emailStatus\", \"claimedAt\"] },\n audit: { indexes: [\"actorId\", \"action\", \"resourceId\", \"createdAt\"] },\n} satisfies PluginStorageConfig;\n\nexport const adminPages = [\n { path: \"/\", label: \"Learning overview\", icon: \"graduation-cap\", group: \"Learning\" },\n { path: \"/courses\", label: \"Courses\", icon: \"books\", group: \"Learning\" },\n { path: \"/learners\", label: \"Enrollments\", icon: \"users\", group: \"Learning\" },\n { path: \"/assignments\", label: \"Assignments\", icon: \"exam\", group: \"Learning\" },\n { path: \"/community\", label: \"Community\", icon: \"chats\", group: \"Learning\" },\n { path: \"/cohorts\", label: \"Cohorts\", icon: \"users-three\", group: \"Learning\" },\n { path: \"/paths\", label: \"Learning paths\", icon: \"books\", group: \"Learning\" },\n { path: \"/reports\", label: \"Reports\", icon: \"chart-bar\", group: \"Learning\" },\n { path: \"/notifications\", label: \"Notifications\", icon: \"bell\", group: \"Learning\" },\n { path: \"/audit\", label: \"Audit history\", icon: \"clock-counter-clockwise\", group: \"Learning\" },\n { path: \"/settings\", label: \"LMS settings\", icon: \"gear\", group: \"Learning\" },\n];\n"],"mappings":";AAAA,MAAa,YAAY;AACzB,MAAa,iBAAiB;AAC9B,MAAa,WAAW,wBAAwB;AAChD,MAAa,qBAAqB;AAIlC,MAAa,UAAU;CACrB,SAAS;EACP,SAAS;GACP;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACD,eAAe,CAAC,OAAO;EACxB;CACD,kBAAkB,EAAE,SAAS,CAAC,YAAY,YAAY,EAAE;CACxD,iBAAiB,EAAE,SAAS,CAAC,YAAY,YAAY,EAAE;CACvD,YAAY,EAAE,SAAS,CAAC,QAAQ,EAAE;CAClC,aAAa,EAAE,SAAS,EAAE,EAAE;CAC5B,eAAe,EAAE,SAAS;EAAC;EAAU;EAAS;EAAY,EAAE;CAC5D,gBAAgB,EAAE,SAAS,CAAC,UAAU,YAAY,EAAE;CACpD,kBAAkB,EAAE,SAAS;EAAC;EAAU;EAAU;EAAW,EAAE;CAC/D,aAAa,EACX,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,YAAY,SAAS;EACtB,CAAC,UAAU,SAAS;EACrB,EACF;CACD,cAAc,EAAE,SAAS,CAAC,UAAU,WAAW,EAAE;CACjD,aAAa,EACX,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,YAAY,YAAY;EAC1B,EACF;CACD,SAAS,EAAE,SAAS;EAAC;EAAY;EAAU;EAAU;EAAY,EAAE;CACnE,SAAS,EAAE,SAAS;EAAC;EAAS;EAAa;EAAY,EAAE;CACzD,oBAAoB,EAAE,SAAS;EAAC;EAAY;EAAU;EAAU;EAAc,EAAE;CAChF,eAAe,EAAE,SAAS;EAAC;EAAU;EAAQ;EAAa;EAAe;EAAY,EAAE;CACvF,OAAO,EAAE,SAAS;EAAC;EAAW;EAAU;EAAc;EAAY,EAAE;CACrE;AAED,MAAa,aAAa;CACxB;EAAE,MAAM;EAAK,OAAO;EAAqB,MAAM;EAAkB,OAAO;EAAY;CACpF;EAAE,MAAM;EAAY,OAAO;EAAW,MAAM;EAAS,OAAO;EAAY;CACxE;EAAE,MAAM;EAAa,OAAO;EAAe,MAAM;EAAS,OAAO;EAAY;CAC7E;EAAE,MAAM;EAAgB,OAAO;EAAe,MAAM;EAAQ,OAAO;EAAY;CAC/E;EAAE,MAAM;EAAc,OAAO;EAAa,MAAM;EAAS,OAAO;EAAY;CAC5E;EAAE,MAAM;EAAY,OAAO;EAAW,MAAM;EAAe,OAAO;EAAY;CAC9E;EAAE,MAAM;EAAU,OAAO;EAAkB,MAAM;EAAS,OAAO;EAAY;CAC7E;EAAE,MAAM;EAAY,OAAO;EAAW,MAAM;EAAa,OAAO;EAAY;CAC5E;EAAE,MAAM;EAAkB,OAAO;EAAiB,MAAM;EAAQ,OAAO;EAAY;CACnF;EAAE,MAAM;EAAU,OAAO;EAAiB,MAAM;EAA2B,OAAO;EAAY;CAC9F;EAAE,MAAM;EAAa,OAAO;EAAgB,MAAM;EAAQ,OAAO;EAAY;CAC9E"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { PluginDescriptor } from "emdash";
|
|
|
3
3
|
|
|
4
4
|
//#region src/constants.d.ts
|
|
5
5
|
declare const PLUGIN_ID = "anantagnanam-lms";
|
|
6
|
-
declare const PLUGIN_VERSION = "0.
|
|
6
|
+
declare const PLUGIN_VERSION = "0.3.0";
|
|
7
7
|
declare const API_BASE = "/_emdash/api/plugins/anantagnanam-lms";
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/index.d.ts
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as adminPages, i as PLUGIN_VERSION, r as PLUGIN_ID, t as API_BASE } from "./constants-
|
|
1
|
+
import { a as adminPages, i as PLUGIN_VERSION, r as PLUGIN_ID, t as API_BASE } from "./constants-DyQbwNbP.js";
|
|
2
2
|
import { t as normalizeLmsOptions } from "./config-BX3beTpM.js";
|
|
3
3
|
|
|
4
4
|
//#region src/index.ts
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AccessGrant, Acquisition, Actor, AuditRecord, Certificate, CertificateIndex, Cohort, CohortMembership, Course, CourseCard, CourseData, CourseDetail, CourseEdition, CourseRevision, CurriculumModule, Discussion, Enrollment, LearnerPreferences, LearningPath, Lesson, LessonProgress, LmsOptions, LmsSettings, MigrationState, Notification, Page, PathEnrollment, ProgressSummary, PublicEnrollment, PublicLesson, PublicQuizAttempt, Review, RevisionSummary, SavedCourse, Versioned } from "./types.js";
|
|
1
|
+
import { AccessGrant, Acquisition, Actor, AssignmentState, AuditRecord, Certificate, CertificateIndex, Cohort, CohortMembership, Course, CourseCard, CourseData, CourseDetail, CourseEdition, CourseRevision, CurriculumModule, Discussion, Enrollment, LearnerPreferences, LearningPath, Lesson, LessonProgress, LmsOptions, LmsSettings, MigrationState, Notification, Page, PathEnrollment, ProgressSummary, PublicEnrollment, PublicLesson, PublicQuizAttempt, Review, RevisionSummary, RubricCriterion, RubricScore, SavedCourse, StudyNote, Versioned } from "./types.js";
|
|
2
2
|
import * as emdash from "emdash";
|
|
3
3
|
import { PluginContext, StorageCollection } from "emdash";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -122,6 +122,12 @@ declare class LmsService {
|
|
|
122
122
|
passingPoints: number;
|
|
123
123
|
dueAt: string | null;
|
|
124
124
|
allowResubmission: boolean;
|
|
125
|
+
rubric?: {
|
|
126
|
+
id: string;
|
|
127
|
+
title: string;
|
|
128
|
+
description: string;
|
|
129
|
+
maxPoints: number;
|
|
130
|
+
}[] | undefined;
|
|
125
131
|
} | null;
|
|
126
132
|
}>;
|
|
127
133
|
instructor(course: Course, actor: Actor | undefined): Actor;
|
|
@@ -333,10 +339,16 @@ declare class LmsService {
|
|
|
333
339
|
saved: boolean;
|
|
334
340
|
draftRevision: number;
|
|
335
341
|
}>;
|
|
342
|
+
assignmentState(actor: Actor | undefined, courseId: string, lessonId: string): Promise<AssignmentState>;
|
|
343
|
+
saveAssignmentDraft(actor: Actor | undefined, input: unknown): Promise<{
|
|
344
|
+
saved: boolean;
|
|
345
|
+
draftRevision: number;
|
|
346
|
+
}>;
|
|
336
347
|
submitAssignment(actor: Actor | undefined, input: unknown): Promise<PublicEnrollment>;
|
|
337
348
|
gradeAssignment(actor: Actor | undefined, input: unknown): Promise<PublicEnrollment>;
|
|
338
349
|
saveNote(actor: Actor | undefined, input: unknown): Promise<{
|
|
339
350
|
note: string;
|
|
351
|
+
revision: number;
|
|
340
352
|
}>;
|
|
341
353
|
certificate(actor: Actor | undefined, courseId: string): Promise<Certificate>;
|
|
342
354
|
ownedCertificate(actor: Actor | undefined, id: string): Promise<Certificate>;
|
|
@@ -459,18 +471,16 @@ declare class LmsService {
|
|
|
459
471
|
progress: Record<string, Omit<LessonProgress, "quizAttempts"> & {
|
|
460
472
|
quizAttempts: PublicQuizAttempt[];
|
|
461
473
|
}>;
|
|
462
|
-
id: string;
|
|
463
474
|
status: "pending" | "active" | "completed" | "rejected" | "suspended" | "cancelled";
|
|
464
475
|
courseId: string;
|
|
465
|
-
cohortId: string | null;
|
|
466
476
|
userId: string;
|
|
467
|
-
accessStartsAt: string | null;
|
|
468
|
-
accessExpiresAt: string | null;
|
|
469
477
|
accessStatus: "pending" | "granted" | "suspended" | "revoked";
|
|
470
478
|
accessSource: "free" | "manual" | "cohort" | "purchase";
|
|
471
479
|
enrolledAt: string;
|
|
472
480
|
completedAt: string | null;
|
|
473
481
|
lastActivityAt: string;
|
|
482
|
+
cohortId: string | null;
|
|
483
|
+
id: string;
|
|
474
484
|
courseEditionId?: string | undefined;
|
|
475
485
|
learnerName: string;
|
|
476
486
|
grants: Record<string, AccessGrant>;
|
|
@@ -480,6 +490,9 @@ declare class LmsService {
|
|
|
480
490
|
decisionAt: string | null;
|
|
481
491
|
decisionReason: string | null;
|
|
482
492
|
approvedAt: string | null;
|
|
493
|
+
accessStartsAt: string | null;
|
|
494
|
+
accessExpiresAt: string | null;
|
|
495
|
+
studyNotes?: StudyNote[] | undefined;
|
|
483
496
|
certificate: Certificate | null;
|
|
484
497
|
completionLessonIds: string[];
|
|
485
498
|
schemaVersion: 1;
|
|
@@ -589,6 +602,8 @@ declare class LmsService {
|
|
|
589
602
|
feedback: string;
|
|
590
603
|
gradedAt: string | null;
|
|
591
604
|
gradedBy: string | null;
|
|
605
|
+
rubric?: RubricCriterion[];
|
|
606
|
+
rubricScores?: RubricScore[];
|
|
592
607
|
}[];
|
|
593
608
|
cursor?: string;
|
|
594
609
|
hasMore: boolean;
|
|
@@ -689,6 +704,12 @@ declare class LmsService {
|
|
|
689
704
|
passingPoints: number;
|
|
690
705
|
dueAt: string | null;
|
|
691
706
|
allowResubmission: boolean;
|
|
707
|
+
rubric?: {
|
|
708
|
+
id: string;
|
|
709
|
+
title: string;
|
|
710
|
+
description: string;
|
|
711
|
+
maxPoints: number;
|
|
712
|
+
}[] | undefined;
|
|
692
713
|
} | null;
|
|
693
714
|
}[];
|
|
694
715
|
}[];
|