@things-factory/learning 10.1.262 → 10.1.263
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-client/pages/learning-course-list.js +27 -5
- package/dist-client/pages/learning-course-list.js.map +1 -1
- package/dist-client/pages/learning-enrollment-status.js +12 -2
- package/dist-client/pages/learning-enrollment-status.js.map +1 -1
- package/dist-client/pages/learning-view.d.ts +10 -0
- package/dist-client/pages/learning-view.js +59 -3
- package/dist-client/pages/learning-view.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/ai-reads.d.ts +1 -0
- package/dist-server/ai-reads.js +26 -2
- package/dist-server/ai-reads.js.map +1 -1
- package/dist-server/service/enrollment/enrollment-mutation.d.ts +2 -0
- package/dist-server/service/enrollment/enrollment-mutation.js +18 -0
- package/dist-server/service/enrollment/enrollment-mutation.js.map +1 -1
- package/dist-server/service/enrollment/enrollment-query.d.ts +2 -0
- package/dist-server/service/enrollment/enrollment-query.js +15 -0
- package/dist-server/service/enrollment/enrollment-query.js.map +1 -1
- package/dist-server/service/enrollment/enrollment-service.d.ts +4 -0
- package/dist-server/service/enrollment/enrollment-service.js +1 -0
- package/dist-server/service/enrollment/enrollment-service.js.map +1 -1
- package/dist-server/service/enrollment/index.d.ts +3 -1
- package/dist-server/service/enrollment/index.js +3 -1
- package/dist-server/service/enrollment/index.js.map +1 -1
- package/dist-server/service/enrollment/lesson-note-service.d.ts +15 -0
- package/dist-server/service/enrollment/lesson-note-service.js +86 -0
- package/dist-server/service/enrollment/lesson-note-service.js.map +1 -0
- package/dist-server/service/enrollment/lesson-note.d.ts +35 -0
- package/dist-server/service/enrollment/lesson-note.js +107 -0
- package/dist-server/service/enrollment/lesson-note.js.map +1 -0
- package/dist-server/service/index.d.ts +2 -1
- package/dist-server/service/index.js +1 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -14
- package/translations/en.json +22 -16
- package/translations/es.json +7 -1
- package/translations/ja.json +7 -1
- package/translations/ko.json +23 -17
- package/translations/ms.json +7 -1
- package/translations/zh.json +7 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type DetailRead, type EntryTarget, type ListRead } from '@things-factory/ai-assistant';
|
|
2
2
|
export declare const LEARNING_ENROLLMENTS_READ: ListRead;
|
|
3
|
+
export declare const LEARNING_COURSES_READ: ListRead;
|
|
3
4
|
export declare const LEARNING_CONTENT_READ: DetailRead;
|
|
4
5
|
export declare const QUESTION_DRAFT_TARGET: EntryTarget;
|
|
5
6
|
export declare function registerLearningReads(): void;
|
package/dist-server/ai-reads.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LEARNING_ENTRY_TARGETS = exports.LEARNING_READ_TARGETS = exports.QUESTION_DRAFT_TARGET = exports.LEARNING_CONTENT_READ = exports.LEARNING_ENROLLMENTS_READ = void 0;
|
|
3
|
+
exports.LEARNING_ENTRY_TARGETS = exports.LEARNING_READ_TARGETS = exports.QUESTION_DRAFT_TARGET = exports.LEARNING_CONTENT_READ = exports.LEARNING_COURSES_READ = exports.LEARNING_ENROLLMENTS_READ = void 0;
|
|
4
4
|
exports.registerLearningReads = registerLearningReads;
|
|
5
5
|
/*
|
|
6
6
|
* The assistant's reads and entry of learning (ADR-0194 decision 12) - registered at load; an application names the keys
|
|
@@ -28,6 +28,29 @@ exports.LEARNING_ENROLLMENTS_READ = {
|
|
|
28
28
|
search: "learner's name or course",
|
|
29
29
|
route: 'learning-enrollment-status'
|
|
30
30
|
};
|
|
31
|
+
exports.LEARNING_COURSES_READ = {
|
|
32
|
+
key: 'learning.courses',
|
|
33
|
+
title: 'title.learning-course-list',
|
|
34
|
+
name: 'Courses (교육 과정) - each course with its category, the version learners take now (unit count, expected minutes, pass score, where its material came from), its manager, and how its enrolments stand: total (cancelled left out), not started, in progress, completed, overdue. Managers read it.',
|
|
35
|
+
listQuery: 'courses',
|
|
36
|
+
selection: 'id name category description updatedAt manager { id name } publishedVersion { number expectedSeconds passScore sourceKind } enrollmentCounts { total assigned inProgress completed overdue }',
|
|
37
|
+
columns: [
|
|
38
|
+
{ name: 'name', type: 'string', labelKey: 'field.learning-course-name' },
|
|
39
|
+
{ name: 'category', type: 'string', labelKey: 'field.learning-course-category' },
|
|
40
|
+
{ name: 'publishedVersion', path: 'publishedVersion.number', type: 'number', labelKey: 'field.learning-published-version' },
|
|
41
|
+
{ name: 'expectedSeconds', path: 'publishedVersion.expectedSeconds', type: 'number' },
|
|
42
|
+
{ name: 'passScore', path: 'publishedVersion.passScore', type: 'number', labelKey: 'field.learning-pass-score' },
|
|
43
|
+
{ name: 'enrolled', path: 'enrollmentCounts.total', type: 'number', labelKey: 'field.learning-enrolled' },
|
|
44
|
+
{ name: 'assigned', path: 'enrollmentCounts.assigned', type: 'number' },
|
|
45
|
+
{ name: 'inProgress', path: 'enrollmentCounts.inProgress', type: 'number' },
|
|
46
|
+
{ name: 'completed', path: 'enrollmentCounts.completed', type: 'number' },
|
|
47
|
+
{ name: 'overdue', path: 'enrollmentCounts.overdue', type: 'number' },
|
|
48
|
+
{ name: 'manager', path: 'manager.name', type: 'string', labelKey: 'field.learning-course-manager' },
|
|
49
|
+
{ name: 'updatedAt', type: 'date', labelKey: 'field.learning-updated-at' }
|
|
50
|
+
],
|
|
51
|
+
search: 'fields name, description, category',
|
|
52
|
+
route: 'learning-course-list'
|
|
53
|
+
};
|
|
31
54
|
exports.LEARNING_CONTENT_READ = {
|
|
32
55
|
key: 'learning.course-content',
|
|
33
56
|
labelKey: 'title.learning-units',
|
|
@@ -60,11 +83,12 @@ exports.QUESTION_DRAFT_TARGET = {
|
|
|
60
83
|
};
|
|
61
84
|
function registerLearningReads() {
|
|
62
85
|
(0, ai_assistant_1.registerReadTarget)((0, ai_assistant_1.listReadTarget)(exports.LEARNING_ENROLLMENTS_READ));
|
|
86
|
+
(0, ai_assistant_1.registerReadTarget)((0, ai_assistant_1.listReadTarget)(exports.LEARNING_COURSES_READ));
|
|
63
87
|
(0, ai_assistant_1.registerDetailRead)(exports.LEARNING_CONTENT_READ);
|
|
64
88
|
(0, ai_assistant_1.registerEntryTarget)(exports.QUESTION_DRAFT_TARGET);
|
|
65
89
|
}
|
|
66
90
|
/** The keys an application's assistant mode names to read learning. */
|
|
67
|
-
exports.LEARNING_READ_TARGETS = [exports.LEARNING_ENROLLMENTS_READ.key, exports.LEARNING_CONTENT_READ.key];
|
|
91
|
+
exports.LEARNING_READ_TARGETS = [exports.LEARNING_ENROLLMENTS_READ.key, exports.LEARNING_COURSES_READ.key, exports.LEARNING_CONTENT_READ.key];
|
|
68
92
|
/** The keys an application's assistant mode names to let the assistant enter learning records. */
|
|
69
93
|
exports.LEARNING_ENTRY_TARGETS = [exports.QUESTION_DRAFT_TARGET.key];
|
|
70
94
|
//# sourceMappingURL=ai-reads.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-reads.js","sourceRoot":"","sources":["../server/ai-reads.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The assistant's reads and entry of learning (ADR-0194 decision 12) - registered at load; an application names the keys\n * in its assistant mode's `readTargets`.\n */\nimport { listReadTarget, registerDetailRead, registerEntryTarget, registerReadTarget, type DetailRead, type EntryTarget, type ListRead } from '@things-factory/ai-assistant'\n\nimport { choicesOfText } from './service/enrollment/learning-ai'\n\nexport const LEARNING_ENROLLMENTS_READ: ListRead = {\n key: 'learning.enrollments',\n title: 'title.learning-enrollment-status',\n name: 'Course enrolments (수강) - who is to take which course by when and where each stands: ASSIGNED (not started), IN_PROGRESS, COMPLETED or OVERDUE (open past its due day), with the days left to the due day. A manager reads everyone, a department head their people, anyone else their own.',\n listQuery: 'learningEnrollments',\n selection: 'id learner departmentName course state dueOn daysLeft startedAt completedAt unitsDone units',\n columns: [\n { name: 'learner', type: 'string', labelKey: 'field.learning-learner' },\n { name: 'departmentName', type: 'string', labelKey: 'field.learning-department' },\n { name: 'course', type: 'string', labelKey: 'field.learning-course-name' },\n { name: 'state', type: 'string', labelKey: 'field.learning-state' },\n { name: 'dueOn', type: 'date', labelKey: 'field.learning-due-on' },\n { name: 'daysLeft', type: 'number', labelKey: 'field.learning-days-left' },\n { name: 'completedAt', type: 'date', labelKey: 'field.learning-completed-on' },\n { name: 'unitsDone', type: 'number', labelKey: 'field.learning-units-done' }\n ],\n status: { field: 'state', values: ['ASSIGNED', 'IN_PROGRESS', 'COMPLETED', 'OVERDUE'] },\n search: \"learner's name or course\",\n route: 'learning-enrollment-status'\n}\n\nexport const LEARNING_CONTENT_READ: DetailRead = {\n key: 'learning.course-content',\n labelKey: 'title.learning-units',\n description:\n \"The units of one course version - names and texts - to answer a question on the course the person is taking (give their enrollmentId; only that course's version, refused while their quiz attempt is open - do not help with the quiz) or, for a manager, to draft questions of a version (give versionId). Answer only from these units.\",\n query: 'query ($enrollmentId: String, $versionId: String) { learningContent(enrollmentId: $enrollmentId, versionId: $versionId) { course version units { seq kind name text } } }',\n args: [\n { name: 'enrollmentId', type: 'string', axis: 'enrollment', description: 'The enrolment open on the course screen (learning-view?id=...)' },\n { name: 'versionId', type: 'string', axis: 'course-version', description: 'A version open in the course editor - managers only' }\n ]\n}\n\nexport const QUESTION_DRAFT_TARGET: EntryTarget = {\n key: 'learning.question-draft',\n labelKey: 'title.learning-questions',\n description:\n 'A quiz question drafted from the units of a DRAFT course version (read learning.course-content with its versionId first). It is entered marked as an AI draft; a manager reviews and saves it before the version can be published. Only a draft version takes it.',\n fields: [\n { name: 'versionId', type: 'string', required: true, axis: 'course-version', description: 'The draft version the question belongs to', labelKey: 'title.learning-versions' },\n { name: 'kind', type: 'enum', required: true, values: ['SINGLE', 'MULTIPLE', 'TRUE_FALSE'], valueKeyPrefix: 'text.learning-question-', labelKey: 'field.learning-question-kind' },\n { name: 'text', type: 'text', required: true, description: 'What it asks - from the units only', labelKey: 'field.learning-question-text' },\n { name: 'choices', type: 'text', required: true, description: 'One choice a line; start each right choice with *. TRUE_FALSE has two lines.', labelKey: 'field.learning-question-choices' },\n { name: 'explanation', type: 'text', description: 'Why the answer is right, citing the unit', labelKey: 'field.learning-question-explanation' }\n ],\n mutation: 'mutation ($versionId: String!, $question: CourseQuestionInput!) { addDraftedCourseQuestion(versionId: $versionId, question: $question) { id } }',\n variables: row => ({\n versionId: row.values.versionId,\n question: { kind: row.values.kind, text: row.values.text, choices: choicesOfText(String(row.values.choices ?? '')), explanation: row.values.explanation ?? null }\n }),\n appliedOf: (data, row) => ({ id: data?.addDraftedCourseQuestion?.id, label: String(row.values.text ?? '').slice(0, 60) }),\n screen: 'learning-course-editor',\n maxRows: 30\n}\n\nexport function registerLearningReads(): void {\n registerReadTarget(listReadTarget(LEARNING_ENROLLMENTS_READ))\n registerDetailRead(LEARNING_CONTENT_READ)\n registerEntryTarget(QUESTION_DRAFT_TARGET)\n}\n\n/** The keys an application's assistant mode names to read learning. */\nexport const LEARNING_READ_TARGETS = [LEARNING_ENROLLMENTS_READ.key, LEARNING_CONTENT_READ.key]\n\n/** The keys an application's assistant mode names to let the assistant enter learning records. */\nexport const LEARNING_ENTRY_TARGETS = [QUESTION_DRAFT_TARGET.key]\n"]}
|
|
1
|
+
{"version":3,"file":"ai-reads.js","sourceRoot":"","sources":["../server/ai-reads.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The assistant's reads and entry of learning (ADR-0194 decision 12) - registered at load; an application names the keys\n * in its assistant mode's `readTargets`.\n */\nimport { listReadTarget, registerDetailRead, registerEntryTarget, registerReadTarget, type DetailRead, type EntryTarget, type ListRead } from '@things-factory/ai-assistant'\n\nimport { choicesOfText } from './service/enrollment/learning-ai'\n\nexport const LEARNING_ENROLLMENTS_READ: ListRead = {\n key: 'learning.enrollments',\n title: 'title.learning-enrollment-status',\n name: 'Course enrolments (수강) - who is to take which course by when and where each stands: ASSIGNED (not started), IN_PROGRESS, COMPLETED or OVERDUE (open past its due day), with the days left to the due day. A manager reads everyone, a department head their people, anyone else their own.',\n listQuery: 'learningEnrollments',\n selection: 'id learner departmentName course state dueOn daysLeft startedAt completedAt unitsDone units',\n columns: [\n { name: 'learner', type: 'string', labelKey: 'field.learning-learner' },\n { name: 'departmentName', type: 'string', labelKey: 'field.learning-department' },\n { name: 'course', type: 'string', labelKey: 'field.learning-course-name' },\n { name: 'state', type: 'string', labelKey: 'field.learning-state' },\n { name: 'dueOn', type: 'date', labelKey: 'field.learning-due-on' },\n { name: 'daysLeft', type: 'number', labelKey: 'field.learning-days-left' },\n { name: 'completedAt', type: 'date', labelKey: 'field.learning-completed-on' },\n { name: 'unitsDone', type: 'number', labelKey: 'field.learning-units-done' }\n ],\n status: { field: 'state', values: ['ASSIGNED', 'IN_PROGRESS', 'COMPLETED', 'OVERDUE'] },\n search: \"learner's name or course\",\n route: 'learning-enrollment-status'\n}\n\nexport const LEARNING_COURSES_READ: ListRead = {\n key: 'learning.courses',\n title: 'title.learning-course-list',\n name: 'Courses (교육 과정) - each course with its category, the version learners take now (unit count, expected minutes, pass score, where its material came from), its manager, and how its enrolments stand: total (cancelled left out), not started, in progress, completed, overdue. Managers read it.',\n listQuery: 'courses',\n selection:\n 'id name category description updatedAt manager { id name } publishedVersion { number expectedSeconds passScore sourceKind } enrollmentCounts { total assigned inProgress completed overdue }',\n columns: [\n { name: 'name', type: 'string', labelKey: 'field.learning-course-name' },\n { name: 'category', type: 'string', labelKey: 'field.learning-course-category' },\n { name: 'publishedVersion', path: 'publishedVersion.number', type: 'number', labelKey: 'field.learning-published-version' },\n { name: 'expectedSeconds', path: 'publishedVersion.expectedSeconds', type: 'number' },\n { name: 'passScore', path: 'publishedVersion.passScore', type: 'number', labelKey: 'field.learning-pass-score' },\n { name: 'enrolled', path: 'enrollmentCounts.total', type: 'number', labelKey: 'field.learning-enrolled' },\n { name: 'assigned', path: 'enrollmentCounts.assigned', type: 'number' },\n { name: 'inProgress', path: 'enrollmentCounts.inProgress', type: 'number' },\n { name: 'completed', path: 'enrollmentCounts.completed', type: 'number' },\n { name: 'overdue', path: 'enrollmentCounts.overdue', type: 'number' },\n { name: 'manager', path: 'manager.name', type: 'string', labelKey: 'field.learning-course-manager' },\n { name: 'updatedAt', type: 'date', labelKey: 'field.learning-updated-at' }\n ],\n search: 'fields name, description, category',\n route: 'learning-course-list'\n}\n\nexport const LEARNING_CONTENT_READ: DetailRead = {\n key: 'learning.course-content',\n labelKey: 'title.learning-units',\n description:\n \"The units of one course version - names and texts - to answer a question on the course the person is taking (give their enrollmentId; only that course's version, refused while their quiz attempt is open - do not help with the quiz) or, for a manager, to draft questions of a version (give versionId). Answer only from these units.\",\n query: 'query ($enrollmentId: String, $versionId: String) { learningContent(enrollmentId: $enrollmentId, versionId: $versionId) { course version units { seq kind name text } } }',\n args: [\n { name: 'enrollmentId', type: 'string', axis: 'enrollment', description: 'The enrolment open on the course screen (learning-view?id=...)' },\n { name: 'versionId', type: 'string', axis: 'course-version', description: 'A version open in the course editor - managers only' }\n ]\n}\n\nexport const QUESTION_DRAFT_TARGET: EntryTarget = {\n key: 'learning.question-draft',\n labelKey: 'title.learning-questions',\n description:\n 'A quiz question drafted from the units of a DRAFT course version (read learning.course-content with its versionId first). It is entered marked as an AI draft; a manager reviews and saves it before the version can be published. Only a draft version takes it.',\n fields: [\n { name: 'versionId', type: 'string', required: true, axis: 'course-version', description: 'The draft version the question belongs to', labelKey: 'title.learning-versions' },\n { name: 'kind', type: 'enum', required: true, values: ['SINGLE', 'MULTIPLE', 'TRUE_FALSE'], valueKeyPrefix: 'text.learning-question-', labelKey: 'field.learning-question-kind' },\n { name: 'text', type: 'text', required: true, description: 'What it asks - from the units only', labelKey: 'field.learning-question-text' },\n { name: 'choices', type: 'text', required: true, description: 'One choice a line; start each right choice with *. TRUE_FALSE has two lines.', labelKey: 'field.learning-question-choices' },\n { name: 'explanation', type: 'text', description: 'Why the answer is right, citing the unit', labelKey: 'field.learning-question-explanation' }\n ],\n mutation: 'mutation ($versionId: String!, $question: CourseQuestionInput!) { addDraftedCourseQuestion(versionId: $versionId, question: $question) { id } }',\n variables: row => ({\n versionId: row.values.versionId,\n question: { kind: row.values.kind, text: row.values.text, choices: choicesOfText(String(row.values.choices ?? '')), explanation: row.values.explanation ?? null }\n }),\n appliedOf: (data, row) => ({ id: data?.addDraftedCourseQuestion?.id, label: String(row.values.text ?? '').slice(0, 60) }),\n screen: 'learning-course-editor',\n maxRows: 30\n}\n\nexport function registerLearningReads(): void {\n registerReadTarget(listReadTarget(LEARNING_ENROLLMENTS_READ))\n registerReadTarget(listReadTarget(LEARNING_COURSES_READ))\n registerDetailRead(LEARNING_CONTENT_READ)\n registerEntryTarget(QUESTION_DRAFT_TARGET)\n}\n\n/** The keys an application's assistant mode names to read learning. */\nexport const LEARNING_READ_TARGETS = [LEARNING_ENROLLMENTS_READ.key, LEARNING_COURSES_READ.key, LEARNING_CONTENT_READ.key]\n\n/** The keys an application's assistant mode names to let the assistant enter learning records. */\nexport const LEARNING_ENTRY_TARGETS = [QUESTION_DRAFT_TARGET.key]\n"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Enrollment } from './enrollment';
|
|
2
|
+
import { LessonNote } from './lesson-note';
|
|
2
3
|
import { LearningAudienceInput, LearningTickResult, QuizAttemptView, QuizResultView } from './enrollment-type';
|
|
3
4
|
export declare class EnrollmentMutation {
|
|
4
5
|
recordLearningTick(enrollmentId: string, unitId: string, seconds: number, position: number, context: ResolverContext): Promise<LearningTickResult>;
|
|
6
|
+
saveLessonNote(enrollmentId: string, unitId: string, page: number, strokes: unknown, context: ResolverContext): Promise<LessonNote>;
|
|
5
7
|
acknowledgeEnrollment(id: string, context: ResolverContext): Promise<Enrollment>;
|
|
6
8
|
startQuizAttempt(enrollmentId: string, context: ResolverContext): Promise<QuizAttemptView>;
|
|
7
9
|
submitQuizAttempt(attemptId: string, answers: Record<string, string[]>, context: ResolverContext): Promise<QuizResultView>;
|
|
@@ -7,6 +7,8 @@ const shell_1 = require("@things-factory/shell");
|
|
|
7
7
|
const enrollment_1 = require("./enrollment");
|
|
8
8
|
const enrollment_service_1 = require("./enrollment-service");
|
|
9
9
|
const enrollment_remind_1 = require("./enrollment-remind");
|
|
10
|
+
const lesson_note_1 = require("./lesson-note");
|
|
11
|
+
const lesson_note_service_1 = require("./lesson-note-service");
|
|
10
12
|
const enrollment_type_1 = require("./enrollment-type");
|
|
11
13
|
/*
|
|
12
14
|
* The writes of enrolments (ADR-0194 decisions 4-8): a learner's ticks, acknowledgement and quiz (`learning` mutation,
|
|
@@ -17,6 +19,9 @@ let EnrollmentMutation = class EnrollmentMutation {
|
|
|
17
19
|
async recordLearningTick(enrollmentId, unitId, seconds, position, context) {
|
|
18
20
|
return await (0, enrollment_service_1.recordTick)(enrollmentId, unitId, seconds, position, context);
|
|
19
21
|
}
|
|
22
|
+
async saveLessonNote(enrollmentId, unitId, page, strokes, context) {
|
|
23
|
+
return await (0, lesson_note_service_1.saveLessonNote)(enrollmentId, unitId, page, strokes, context);
|
|
24
|
+
}
|
|
20
25
|
async acknowledgeEnrollment(id, context) {
|
|
21
26
|
return await (0, enrollment_service_1.acknowledgeEnrollment)(id, context);
|
|
22
27
|
}
|
|
@@ -53,6 +58,19 @@ tslib_1.__decorate([
|
|
|
53
58
|
tslib_1.__metadata("design:paramtypes", [String, String, Number, Number, Object]),
|
|
54
59
|
tslib_1.__metadata("design:returntype", Promise)
|
|
55
60
|
], EnrollmentMutation.prototype, "recordLearningTick", null);
|
|
61
|
+
tslib_1.__decorate([
|
|
62
|
+
(0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "mutation", domainOwnerGranted: true)'),
|
|
63
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
64
|
+
(0, type_graphql_1.Mutation)(returns => lesson_note_1.LessonNote, { description: "To keep a page's notes on a PDF unit of the learner's own enrolment - the page's whole strokes, as fractions of the page." }),
|
|
65
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('enrollmentId')),
|
|
66
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('unitId')),
|
|
67
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('page', type => type_graphql_1.Int, { description: 'The page of the PDF.' })),
|
|
68
|
+
tslib_1.__param(3, (0, type_graphql_1.Arg)('strokes', type => shell_1.ScalarObject, { description: 'The strokes - each { tool: pen | highlighter, color, width, points: [x, y, ...] }.' })),
|
|
69
|
+
tslib_1.__param(4, (0, type_graphql_1.Ctx)()),
|
|
70
|
+
tslib_1.__metadata("design:type", Function),
|
|
71
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Number, Object, Object]),
|
|
72
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
73
|
+
], EnrollmentMutation.prototype, "saveLessonNote", null);
|
|
56
74
|
tslib_1.__decorate([
|
|
57
75
|
(0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "mutation", domainOwnerGranted: true)'),
|
|
58
76
|
(0, type_graphql_1.Directive)('@transaction'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enrollment-mutation.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Int, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { ScalarObject, SpeakRefusals } from '@things-factory/shell'\n\nimport { Enrollment } from './enrollment'\nimport { acknowledgeEnrollment, cancelEnrollments, DIRECT_SOURCE_KIND, enroll, learnersOf, recordTick, startQuizAttempt, submitQuizAttempt } from './enrollment-service'\nimport { remindEnrollments } from './enrollment-remind'\nimport { LearningAudienceInput, LearningTickResult, QuizAttemptView, QuizResultView } from './enrollment-type'\n\n\n/*\n * The writes of enrolments (ADR-0194 decisions 4-8): a learner's ticks, acknowledgement and quiz (`learning` mutation,\n * the task `learning.taking`, on their own enrolments only); a manager's assigning, cancelling and reminding (`course`\n * mutation, `learning.managing`).\n */\n@Resolver(Enrollment)\n@UseMiddleware(SpeakRefusals)\nexport class EnrollmentMutation {\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => LearningTickResult, {\n description: 'To record a tick of a unit looked at - the server counts the time since the last tick (15 seconds at most) and refuses a video position ahead of what was watched.'\n })\n async recordLearningTick(\n @Arg('enrollmentId') enrollmentId: string,\n @Arg('unitId') unitId: string,\n @Arg('seconds', type => Int, { description: 'Seconds looked at since the last tick, as the screen says - it may lower what is counted, never raise it.' }) seconds: number,\n @Arg('position', type => Int, { description: 'Where the video stands, in seconds - 0 for a document.' }) position: number,\n @Ctx() context: ResolverContext\n ): Promise<LearningTickResult> {\n return await recordTick(enrollmentId, unitId, seconds, position, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Enrollment, { description: \"To confirm the course's acknowledgement.\" })\n async acknowledgeEnrollment(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Enrollment> {\n return await acknowledgeEnrollment(id, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => QuizAttemptView, { description: 'To start a quiz attempt - the questions and choices drawn and shuffled, never the answers.' })\n async startQuizAttempt(@Arg('enrollmentId') enrollmentId: string, @Ctx() context: ResolverContext): Promise<QuizAttemptView> {\n const { attempt, questions } = await startQuizAttempt(enrollmentId, context)\n return { attemptId: attempt.id, questions }\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => QuizResultView, { description: \"To send an attempt's answers - scored on the server; the score and whether it passed come back, never the right answers.\" })\n async submitQuizAttempt(\n @Arg('attemptId') attemptId: string,\n @Arg('answers', type => ScalarObject, { description: 'The choice ids picked, by question id.' }) answers: Record<string, string[]>,\n @Ctx() context: ResolverContext\n ): Promise<QuizResultView> {\n return await submitQuizAttempt(attemptId, answers, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [Enrollment], { description: 'To assign a course to an audience - the people it names now - to be completed by a day; each gets a to-do.' })\n async assignCourse(\n @Arg('courseId') courseId: string,\n @Arg('audiences', type => [LearningAudienceInput]) audiences: LearningAudienceInput[],\n @Arg('dueOn', { nullable: true, description: 'YYYY-MM-DD.' }) dueOn: string,\n @Ctx() context: ResolverContext\n ): Promise<Enrollment[]> {\n return await enroll({ kind: DIRECT_SOURCE_KIND, id: '' }, await learnersOf(audiences, context), courseId, dueOn, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [Enrollment], { description: 'To cancel enrolments with one reason, together - one refused, none is cancelled. A completed one stays on record as cancelled, and whoever asked for it is told.' })\n async cancelEnrollments(@Arg('ids', type => [String]) ids: string[], @Arg('reason') reason: string, @Ctx() context: ResolverContext): Promise<Enrollment[]> {\n return await cancelEnrollments(ids, reason, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Int, { description: 'To remind the learners of open enrolments - answers how many were reminded.' })\n async remindEnrollments(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<number> {\n return await remindEnrollments(ids, context)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"enrollment-mutation.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAA0F;AAE1F,iDAAmE;AAEnE,6CAAyC;AACzC,6DAAwK;AACxK,2DAAuD;AACvD,+CAA0C;AAC1C,+DAAsD;AACtD,uDAA8G;AAG9G;;;;GAIG;AAGI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAMvB,AAAN,KAAK,CAAC,kBAAkB,CACD,YAAoB,EAC1B,MAAc,EAC8H,OAAe,EACjE,QAAgB,EAClH,OAAwB;QAE/B,OAAO,MAAM,IAAA,+BAAU,EAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC3E,CAAC;IAKK,AAAN,KAAK,CAAC,cAAc,CACG,YAAoB,EAC1B,MAAc,EACsC,IAAY,EAC8D,OAAgB,EACtJ,OAAwB;QAE/B,OAAO,MAAM,IAAA,oCAAc,EAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC3E,CAAC;IAKK,AAAN,KAAK,CAAC,qBAAqB,CAAY,EAAU,EAAS,OAAwB;QAChF,OAAO,MAAM,IAAA,0CAAqB,EAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IACjD,CAAC;IAKK,AAAN,KAAK,CAAC,gBAAgB,CAAsB,YAAoB,EAAS,OAAwB;QAC/F,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,IAAA,qCAAgB,EAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QAC5E,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,CAAA;IAC7C,CAAC;IAKK,AAAN,KAAK,CAAC,iBAAiB,CACH,SAAiB,EAC8D,OAAiC,EAC3H,OAAwB;QAE/B,OAAO,MAAM,IAAA,sCAAiB,EAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7D,CAAC;IAKK,AAAN,KAAK,CAAC,YAAY,CACC,QAAgB,EACkB,SAAkC,EACvB,KAAa,EACpE,OAAwB;QAE/B,OAAO,MAAM,IAAA,2BAAM,EAAC,EAAE,IAAI,EAAE,uCAAkB,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,IAAA,+BAAU,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;IAC3H,CAAC;IAKK,AAAN,KAAK,CAAC,iBAAiB,CAA+B,GAAa,EAAiB,MAAc,EAAS,OAAwB;QACjI,OAAO,MAAM,IAAA,sCAAiB,EAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;IAKK,AAAN,KAAK,CAAC,iBAAiB,CAA+B,GAAa,EAAS,OAAwB;QAClG,OAAO,MAAM,IAAA,qCAAiB,EAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;CACF,CAAA;AAhFY,gDAAkB;AAMvB;IALL,IAAA,wBAAS,EAAC,mFAAmF,CAAC;IAC9F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oCAAkB,EAAE;QACvC,WAAW,EAAE,oKAAoK;KAClL,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,EAAC,QAAQ,CAAC,CAAA;IACb,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,2GAA2G,EAAE,CAAC,CAAA;IACzJ,mBAAA,IAAA,kBAAG,EAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC,CAAA;IACvG,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;4DAGP;AAKK;IAHL,IAAA,wBAAS,EAAC,mFAAmF,CAAC;IAC9F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,wBAAU,EAAE,EAAE,WAAW,EAAE,2HAA2H,EAAE,CAAC;IAE3K,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,EAAC,QAAQ,CAAC,CAAA;IACb,mBAAA,IAAA,kBAAG,EAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAA;IACjE,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,oFAAoF,EAAE,CAAC,CAAA;IAC3I,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wDAGP;AAKK;IAHL,IAAA,wBAAS,EAAC,mFAAmF,CAAC;IAC9F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,EAAE,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;IAChE,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;+DAExD;AAKK;IAHL,IAAA,wBAAS,EAAC,mFAAmF,CAAC;IAC9F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,iCAAe,EAAE,EAAE,WAAW,EAAE,4FAA4F,EAAE,CAAC;IAC5H,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IAAwB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;0DAGvE;AAKK;IAHL,IAAA,wBAAS,EAAC,mFAAmF,CAAC;IAC9F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,gCAAc,EAAE,EAAE,WAAW,EAAE,0HAA0H,EAAE,CAAC;IAE9K,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC,CAAA;IAC/F,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DAGP;AAKK;IAHL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,uBAAU,CAAC,EAAE,EAAE,WAAW,EAAE,4GAA4G,EAAE,CAAC;IAE9J,mBAAA,IAAA,kBAAG,EAAC,UAAU,CAAC,CAAA;IACf,mBAAA,IAAA,kBAAG,EAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,uCAAqB,CAAC,CAAC,CAAA;IACjD,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAA;IAC5D,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;sDAGP;AAKK;IAHL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,uBAAU,CAAC,EAAE,EAAE,WAAW,EAAE,kKAAkK,EAAE,CAAC;IAC9L,mBAAA,IAAA,kBAAG,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAAiB,mBAAA,IAAA,kBAAG,EAAC,QAAQ,CAAC,CAAA;IAAkB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DAEzG;AAKK;IAHL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,6EAA6E,EAAE,CAAC;IAChG,mBAAA,IAAA,kBAAG,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAAiB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DAE1E;6BA/EU,kBAAkB;IAF9B,IAAA,uBAAQ,EAAC,uBAAU,CAAC;IACpB,IAAA,4BAAa,EAAC,qBAAa,CAAC;GAChB,kBAAkB,CAgF9B","sourcesContent":["import { Arg, Ctx, Directive, Int, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { ScalarObject, SpeakRefusals } from '@things-factory/shell'\n\nimport { Enrollment } from './enrollment'\nimport { acknowledgeEnrollment, cancelEnrollments, DIRECT_SOURCE_KIND, enroll, learnersOf, recordTick, startQuizAttempt, submitQuizAttempt } from './enrollment-service'\nimport { remindEnrollments } from './enrollment-remind'\nimport { LessonNote } from './lesson-note'\nimport { saveLessonNote } from './lesson-note-service'\nimport { LearningAudienceInput, LearningTickResult, QuizAttemptView, QuizResultView } from './enrollment-type'\n\n\n/*\n * The writes of enrolments (ADR-0194 decisions 4-8): a learner's ticks, acknowledgement and quiz (`learning` mutation,\n * the task `learning.taking`, on their own enrolments only); a manager's assigning, cancelling and reminding (`course`\n * mutation, `learning.managing`).\n */\n@Resolver(Enrollment)\n@UseMiddleware(SpeakRefusals)\nexport class EnrollmentMutation {\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => LearningTickResult, {\n description: 'To record a tick of a unit looked at - the server counts the time since the last tick (15 seconds at most) and refuses a video position ahead of what was watched.'\n })\n async recordLearningTick(\n @Arg('enrollmentId') enrollmentId: string,\n @Arg('unitId') unitId: string,\n @Arg('seconds', type => Int, { description: 'Seconds looked at since the last tick, as the screen says - it may lower what is counted, never raise it.' }) seconds: number,\n @Arg('position', type => Int, { description: 'Where the video stands, in seconds - 0 for a document.' }) position: number,\n @Ctx() context: ResolverContext\n ): Promise<LearningTickResult> {\n return await recordTick(enrollmentId, unitId, seconds, position, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => LessonNote, { description: \"To keep a page's notes on a PDF unit of the learner's own enrolment - the page's whole strokes, as fractions of the page.\" })\n async saveLessonNote(\n @Arg('enrollmentId') enrollmentId: string,\n @Arg('unitId') unitId: string,\n @Arg('page', type => Int, { description: 'The page of the PDF.' }) page: number,\n @Arg('strokes', type => ScalarObject, { description: 'The strokes - each { tool: pen | highlighter, color, width, points: [x, y, ...] }.' }) strokes: unknown,\n @Ctx() context: ResolverContext\n ): Promise<LessonNote> {\n return await saveLessonNote(enrollmentId, unitId, page, strokes, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Enrollment, { description: \"To confirm the course's acknowledgement.\" })\n async acknowledgeEnrollment(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Enrollment> {\n return await acknowledgeEnrollment(id, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => QuizAttemptView, { description: 'To start a quiz attempt - the questions and choices drawn and shuffled, never the answers.' })\n async startQuizAttempt(@Arg('enrollmentId') enrollmentId: string, @Ctx() context: ResolverContext): Promise<QuizAttemptView> {\n const { attempt, questions } = await startQuizAttempt(enrollmentId, context)\n return { attemptId: attempt.id, questions }\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => QuizResultView, { description: \"To send an attempt's answers - scored on the server; the score and whether it passed come back, never the right answers.\" })\n async submitQuizAttempt(\n @Arg('attemptId') attemptId: string,\n @Arg('answers', type => ScalarObject, { description: 'The choice ids picked, by question id.' }) answers: Record<string, string[]>,\n @Ctx() context: ResolverContext\n ): Promise<QuizResultView> {\n return await submitQuizAttempt(attemptId, answers, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [Enrollment], { description: 'To assign a course to an audience - the people it names now - to be completed by a day; each gets a to-do.' })\n async assignCourse(\n @Arg('courseId') courseId: string,\n @Arg('audiences', type => [LearningAudienceInput]) audiences: LearningAudienceInput[],\n @Arg('dueOn', { nullable: true, description: 'YYYY-MM-DD.' }) dueOn: string,\n @Ctx() context: ResolverContext\n ): Promise<Enrollment[]> {\n return await enroll({ kind: DIRECT_SOURCE_KIND, id: '' }, await learnersOf(audiences, context), courseId, dueOn, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [Enrollment], { description: 'To cancel enrolments with one reason, together - one refused, none is cancelled. A completed one stays on record as cancelled, and whoever asked for it is told.' })\n async cancelEnrollments(@Arg('ids', type => [String]) ids: string[], @Arg('reason') reason: string, @Ctx() context: ResolverContext): Promise<Enrollment[]> {\n return await cancelEnrollments(ids, reason, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Int, { description: 'To remind the learners of open enrolments - answers how many were reminded.' })\n async remindEnrollments(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<number> {\n return await remindEnrollments(ids, context)\n }\n}\n"]}
|
|
@@ -4,8 +4,10 @@ import { Course } from '../course/course';
|
|
|
4
4
|
import { CourseVersion } from '../course/course-version';
|
|
5
5
|
import { Enrollment } from './enrollment';
|
|
6
6
|
import { CourseEnrollmentCounts, EnrollmentStatusList, EnrollmentStatusRow, LearningContent, LearningEnrollmentList, LearningUnit } from './enrollment-type';
|
|
7
|
+
import { LessonNote } from './lesson-note';
|
|
7
8
|
export declare class EnrollmentQuery {
|
|
8
9
|
myEnrollments(context: ResolverContext): Promise<Enrollment[]>;
|
|
10
|
+
myLessonNotes(enrollmentId: string, unitId: string, context: ResolverContext): Promise<LessonNote[]>;
|
|
9
11
|
myEnrollment(id: string, context: ResolverContext): Promise<Enrollment>;
|
|
10
12
|
teamEnrollmentStatus(params: ListParam, context: ResolverContext): Promise<EnrollmentStatusList>;
|
|
11
13
|
enrollmentStatus(params: ListParam, context: ResolverContext): Promise<EnrollmentStatusList>;
|
|
@@ -14,6 +14,8 @@ const enrollment_service_1 = require("./enrollment-service");
|
|
|
14
14
|
const enrollment_status_1 = require("./enrollment-status");
|
|
15
15
|
const enrollment_type_1 = require("./enrollment-type");
|
|
16
16
|
const learning_ai_1 = require("./learning-ai");
|
|
17
|
+
const lesson_note_1 = require("./lesson-note");
|
|
18
|
+
const lesson_note_service_1 = require("./lesson-note-service");
|
|
17
19
|
const progress_rules_1 = require("./progress-rules");
|
|
18
20
|
const rowOut = (row) => ({ id: row.enrollment.id, ...row });
|
|
19
21
|
const pageOf = ({ rows, total }) => ({ items: rows.map(rowOut), total });
|
|
@@ -29,6 +31,9 @@ let EnrollmentQuery = class EnrollmentQuery {
|
|
|
29
31
|
async myEnrollments(context) {
|
|
30
32
|
return await (0, enrollment_service_1.myEnrollments)(context);
|
|
31
33
|
}
|
|
34
|
+
async myLessonNotes(enrollmentId, unitId, context) {
|
|
35
|
+
return await (0, lesson_note_service_1.myLessonNotes)(enrollmentId, unitId, context);
|
|
36
|
+
}
|
|
32
37
|
async myEnrollment(id, context) {
|
|
33
38
|
return await (0, enrollment_service_1.myEnrollmentOf)(context, id);
|
|
34
39
|
}
|
|
@@ -103,6 +108,16 @@ tslib_1.__decorate([
|
|
|
103
108
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
104
109
|
tslib_1.__metadata("design:returntype", Promise)
|
|
105
110
|
], EnrollmentQuery.prototype, "myEnrollments", null);
|
|
111
|
+
tslib_1.__decorate([
|
|
112
|
+
(0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
|
|
113
|
+
(0, type_graphql_1.Query)(returns => [lesson_note_1.LessonNote], { description: "The request's own notes on a PDF unit of their own enrolment, by page - nobody else's are read." }),
|
|
114
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('enrollmentId')),
|
|
115
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('unitId')),
|
|
116
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
117
|
+
tslib_1.__metadata("design:type", Function),
|
|
118
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Object]),
|
|
119
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
120
|
+
], EnrollmentQuery.prototype, "myLessonNotes", null);
|
|
106
121
|
tslib_1.__decorate([
|
|
107
122
|
(0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
|
|
108
123
|
(0, type_graphql_1.Query)(returns => enrollment_1.Enrollment, { description: "One of the request's own enrolments." }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enrollment-query.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Int, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\n\nimport { requestHolds, User } from '@things-factory/auth-base'\nimport { getRepository, ListParam, ListValueCount, SpeakRefusals } from '@things-factory/shell'\n\nimport { Course } from '../course/course'\nimport { CourseQuestion } from '../course/course-question'\nimport { CourseVersion } from '../course/course-version'\nimport { learningManagerOf, unitsOf } from '../course/course-service'\nimport { Enrollment } from './enrollment'\nimport { missingFor, myEnrollmentOf, myEnrollments, progressesOf, shownVersionOf, todayIn } from './enrollment-service'\nimport { completionRegister, courseEnrollmentCounts, enrollmentPage, enrollmentStateCounts, StatusRow, teamReachOf } from './enrollment-status'\nimport { CourseEnrollmentCounts, EnrollmentStatusList, EnrollmentStatusRow, LearningContent, LearningEnrollmentList, LearningUnit } from './enrollment-type'\nimport { courseContent, readableEnrollments } from './learning-ai'\nimport { counts, overdue } from './progress-rules'\n\n\nconst rowOut = (row: StatusRow): EnrollmentStatusRow => ({ id: row.enrollment.id, ...row })\n\nconst pageOf = ({ rows, total }: { rows: StatusRow[]; total: number }): EnrollmentStatusList => ({ items: rows.map(rowOut), total })\n\n/** Whether the request reads how an enrolment went - its learner or a manager. */\nasync function readsInside(enrollment: Enrollment, context: any): Promise<boolean> {\n return enrollment.userId === context.state.user.id || (await requestHolds(context, 'course', 'query'))\n}\n\n/*\n * The reads of enrolments (ADR-0194 decisions 5-11): one's own (`learning` query, the task `learning.taking`); every\n * enrolment and the completion register for a manager (`course` query); a department head's people, status only.\n */\n@Resolver(Enrollment)\n@UseMiddleware(SpeakRefusals)\nexport class EnrollmentQuery {\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [Enrollment], { description: \"The request's own enrolments - open ones first, the soonest due first, then the completed.\" })\n async myEnrollments(@Ctx() context: ResolverContext): Promise<Enrollment[]> {\n return await myEnrollments(context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => Enrollment, { description: \"One of the request's own enrolments.\" })\n async myEnrollment(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Enrollment> {\n return await myEnrollmentOf(context, id)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EnrollmentStatusList, { description: \"Where the people of the request's departments stand - for a department head, status and days only. Filters: course, state, sourceKind, sourceId; search: the learner's name or the course's.\" })\n async teamEnrollmentStatus(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EnrollmentStatusList> {\n return pageOf(await enrollmentPage(params, await teamReachOf(context), context))\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EnrollmentStatusList, { description: \"Every enrolment, with its progress and evidence. Filters: course, state, sourceKind, sourceId; search: the learner's name or the course's.\" })\n async enrollmentStatus(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EnrollmentStatusList> {\n return pageOf(await enrollmentPage(params, { kind: 'all' }, context))\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [ListValueCount], { description: \"How many enrolments stand in each state under the list's other conditions, every state in order - of everyone for a manager, else of a department head's people (refused to anyone heading none), as the status list reads them.\" })\n async enrollmentStateCounts(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ListValueCount[]> {\n const reach = (await requestHolds(context, 'course', 'query')) ? ({ kind: 'all' } as const) : await teamReachOf(context)\n return await enrollmentStateCounts(params, reach, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [EnrollmentStatusRow], { description: 'The completion register of a course - every completion by its day.' })\n async completionRegister(@Arg('courseId') courseId: string, @Ctx() context: ResolverContext): Promise<EnrollmentStatusRow[]> {\n return (await completionRegister(courseId, context)).map(rowOut)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => LearningEnrollmentList, { description: 'The enrolments the request may read - a manager every one, a department head their people (status only), anyone else their own - for the assistant (ADR-0194 decision 12).' })\n async learningEnrollments(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<LearningEnrollmentList> {\n return await readableEnrollments(params, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => LearningContent, { description: \"The units of one course version for the assistant - a learner's own enrolment's (not while a quiz attempt is open), or a version for a manager (ADR-0194 decision 12).\" })\n async learningContent(@Arg('enrollmentId', { nullable: true }) enrollmentId: string, @Arg('versionId', { nullable: true }) versionId: string, @Ctx() context: ResolverContext): Promise<LearningContent> {\n return await courseContent({ enrollmentId, versionId }, context)\n }\n\n /* ---------------------------------------------------------------- fields */\n\n @FieldResolver(type => Course, { nullable: true, description: 'The course.' })\n async course(@Root() enrollment: Enrollment): Promise<Course | null> {\n return enrollment.courseId ? await getRepository(Course).findOneBy({ id: enrollment.courseId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true, description: 'Who takes it.' })\n async user(@Root() enrollment: Enrollment): Promise<User | null> {\n return enrollment.userId ? await getRepository(User).findOneBy({ id: enrollment.userId }) : null\n }\n\n @FieldResolver(type => CourseVersion, { nullable: true, description: 'The version it shows - its own once started, the published one before.' })\n async version(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<CourseVersion | null> {\n return await shownVersionOf(learningManagerOf(context), context.state.domain, enrollment)\n }\n\n @FieldResolver(type => String, { description: 'Where it stands today - OVERDUE for an open one past its due day.' })\n state(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): string {\n return overdue(enrollment, todayIn(context.state.domain)) ? 'OVERDUE' : enrollment.status\n }\n\n @FieldResolver(type => [LearningUnit], { description: 'Its units with how far the learner went - for its learner and managers.' })\n async units(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<LearningUnit[]> {\n if (!(await readsInside(enrollment, context))) return []\n const tx = learningManagerOf(context)\n const version = await shownVersionOf(tx, context.state.domain, enrollment)\n if (!version) return []\n const progress = await progressesOf(tx, enrollment.id)\n return (await unitsOf(tx, version.id)).map(unit => ({ unit, progress: progress.find(one => one.unitId === unit.id) ?? null, counts: counts(unit) }))\n }\n\n @FieldResolver(type => [String], { description: 'What still stands before completion - units, time, quiz, acknowledgement.' })\n async missing(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<string[]> {\n if (!(await readsInside(enrollment, context))) return []\n return await missingFor(learningManagerOf(context), context.state.domain, enrollment)\n }\n\n @FieldResolver(type => Int, { nullable: true, description: 'The quiz attempts left - no limit, or no quiz, when empty.' })\n async attemptsLeft(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<number | null> {\n if (!(await readsInside(enrollment, context))) return null\n const version = await shownVersionOf(learningManagerOf(context), context.state.domain, enrollment)\n return version?.attemptLimit != null ? Math.max(0, version.attemptLimit - (enrollment.attempts ?? 0)) : null\n }\n\n @FieldResolver(type => Int, { description: 'How many questions its quiz draws - 0 when it has none.' })\n async quizSize(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<number> {\n const tx = learningManagerOf(context)\n const version = await shownVersionOf(tx, context.state.domain, enrollment)\n if (!version || version.passScore == null) return 0\n const all = await tx.getRepository(CourseQuestion).count({ where: { version: { id: version.id } } as any })\n return version.questionCount ? Math.min(version.questionCount, all) : all\n }\n}\n\n/* How a course's enrolments stand, on the course - for a manager (`course` query); nothing for anyone else. */\n@Resolver(Course)\nexport class CourseEnrollmentFields {\n @FieldResolver(type => CourseEnrollmentCounts, { nullable: true, description: \"Where its enrolments stand - cancelled ones left out. For a manager; empty for anyone else.\" })\n async enrollmentCounts(@Root() course: Course, @Ctx() context: ResolverContext): Promise<CourseEnrollmentCounts | null> {\n if (!(await requestHolds(context, 'course', 'query'))) return null\n return (await courseEnrollmentCounts(context)).get(course.id) ?? { total: 0, assigned: 0, inProgress: 0, completed: 0, overdue: 0 }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"enrollment-query.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Int, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\n\nimport { requestHolds, User } from '@things-factory/auth-base'\nimport { getRepository, ListParam, ListValueCount, SpeakRefusals } from '@things-factory/shell'\n\nimport { Course } from '../course/course'\nimport { CourseQuestion } from '../course/course-question'\nimport { CourseVersion } from '../course/course-version'\nimport { learningManagerOf, unitsOf } from '../course/course-service'\nimport { Enrollment } from './enrollment'\nimport { missingFor, myEnrollmentOf, myEnrollments, progressesOf, shownVersionOf, todayIn } from './enrollment-service'\nimport { completionRegister, courseEnrollmentCounts, enrollmentPage, enrollmentStateCounts, StatusRow, teamReachOf } from './enrollment-status'\nimport { CourseEnrollmentCounts, EnrollmentStatusList, EnrollmentStatusRow, LearningContent, LearningEnrollmentList, LearningUnit } from './enrollment-type'\nimport { courseContent, readableEnrollments } from './learning-ai'\nimport { LessonNote } from './lesson-note'\nimport { myLessonNotes } from './lesson-note-service'\nimport { counts, overdue } from './progress-rules'\n\n\nconst rowOut = (row: StatusRow): EnrollmentStatusRow => ({ id: row.enrollment.id, ...row })\n\nconst pageOf = ({ rows, total }: { rows: StatusRow[]; total: number }): EnrollmentStatusList => ({ items: rows.map(rowOut), total })\n\n/** Whether the request reads how an enrolment went - its learner or a manager. */\nasync function readsInside(enrollment: Enrollment, context: any): Promise<boolean> {\n return enrollment.userId === context.state.user.id || (await requestHolds(context, 'course', 'query'))\n}\n\n/*\n * The reads of enrolments (ADR-0194 decisions 5-11): one's own (`learning` query, the task `learning.taking`); every\n * enrolment and the completion register for a manager (`course` query); a department head's people, status only.\n */\n@Resolver(Enrollment)\n@UseMiddleware(SpeakRefusals)\nexport class EnrollmentQuery {\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [Enrollment], { description: \"The request's own enrolments - open ones first, the soonest due first, then the completed.\" })\n async myEnrollments(@Ctx() context: ResolverContext): Promise<Enrollment[]> {\n return await myEnrollments(context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [LessonNote], { description: \"The request's own notes on a PDF unit of their own enrolment, by page - nobody else's are read.\" })\n async myLessonNotes(@Arg('enrollmentId') enrollmentId: string, @Arg('unitId') unitId: string, @Ctx() context: ResolverContext): Promise<LessonNote[]> {\n return await myLessonNotes(enrollmentId, unitId, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => Enrollment, { description: \"One of the request's own enrolments.\" })\n async myEnrollment(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Enrollment> {\n return await myEnrollmentOf(context, id)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EnrollmentStatusList, { description: \"Where the people of the request's departments stand - for a department head, status and days only. Filters: course, state, sourceKind, sourceId; search: the learner's name or the course's.\" })\n async teamEnrollmentStatus(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EnrollmentStatusList> {\n return pageOf(await enrollmentPage(params, await teamReachOf(context), context))\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EnrollmentStatusList, { description: \"Every enrolment, with its progress and evidence. Filters: course, state, sourceKind, sourceId; search: the learner's name or the course's.\" })\n async enrollmentStatus(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EnrollmentStatusList> {\n return pageOf(await enrollmentPage(params, { kind: 'all' }, context))\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [ListValueCount], { description: \"How many enrolments stand in each state under the list's other conditions, every state in order - of everyone for a manager, else of a department head's people (refused to anyone heading none), as the status list reads them.\" })\n async enrollmentStateCounts(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ListValueCount[]> {\n const reach = (await requestHolds(context, 'course', 'query')) ? ({ kind: 'all' } as const) : await teamReachOf(context)\n return await enrollmentStateCounts(params, reach, context)\n }\n\n @Directive('@privilege(category: \"course\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [EnrollmentStatusRow], { description: 'The completion register of a course - every completion by its day.' })\n async completionRegister(@Arg('courseId') courseId: string, @Ctx() context: ResolverContext): Promise<EnrollmentStatusRow[]> {\n return (await completionRegister(courseId, context)).map(rowOut)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => LearningEnrollmentList, { description: 'The enrolments the request may read - a manager every one, a department head their people (status only), anyone else their own - for the assistant (ADR-0194 decision 12).' })\n async learningEnrollments(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<LearningEnrollmentList> {\n return await readableEnrollments(params, context)\n }\n\n @Directive('@privilege(category: \"learning\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => LearningContent, { description: \"The units of one course version for the assistant - a learner's own enrolment's (not while a quiz attempt is open), or a version for a manager (ADR-0194 decision 12).\" })\n async learningContent(@Arg('enrollmentId', { nullable: true }) enrollmentId: string, @Arg('versionId', { nullable: true }) versionId: string, @Ctx() context: ResolverContext): Promise<LearningContent> {\n return await courseContent({ enrollmentId, versionId }, context)\n }\n\n /* ---------------------------------------------------------------- fields */\n\n @FieldResolver(type => Course, { nullable: true, description: 'The course.' })\n async course(@Root() enrollment: Enrollment): Promise<Course | null> {\n return enrollment.courseId ? await getRepository(Course).findOneBy({ id: enrollment.courseId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true, description: 'Who takes it.' })\n async user(@Root() enrollment: Enrollment): Promise<User | null> {\n return enrollment.userId ? await getRepository(User).findOneBy({ id: enrollment.userId }) : null\n }\n\n @FieldResolver(type => CourseVersion, { nullable: true, description: 'The version it shows - its own once started, the published one before.' })\n async version(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<CourseVersion | null> {\n return await shownVersionOf(learningManagerOf(context), context.state.domain, enrollment)\n }\n\n @FieldResolver(type => String, { description: 'Where it stands today - OVERDUE for an open one past its due day.' })\n state(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): string {\n return overdue(enrollment, todayIn(context.state.domain)) ? 'OVERDUE' : enrollment.status\n }\n\n @FieldResolver(type => [LearningUnit], { description: 'Its units with how far the learner went - for its learner and managers.' })\n async units(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<LearningUnit[]> {\n if (!(await readsInside(enrollment, context))) return []\n const tx = learningManagerOf(context)\n const version = await shownVersionOf(tx, context.state.domain, enrollment)\n if (!version) return []\n const progress = await progressesOf(tx, enrollment.id)\n return (await unitsOf(tx, version.id)).map(unit => ({ unit, progress: progress.find(one => one.unitId === unit.id) ?? null, counts: counts(unit) }))\n }\n\n @FieldResolver(type => [String], { description: 'What still stands before completion - units, time, quiz, acknowledgement.' })\n async missing(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<string[]> {\n if (!(await readsInside(enrollment, context))) return []\n return await missingFor(learningManagerOf(context), context.state.domain, enrollment)\n }\n\n @FieldResolver(type => Int, { nullable: true, description: 'The quiz attempts left - no limit, or no quiz, when empty.' })\n async attemptsLeft(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<number | null> {\n if (!(await readsInside(enrollment, context))) return null\n const version = await shownVersionOf(learningManagerOf(context), context.state.domain, enrollment)\n return version?.attemptLimit != null ? Math.max(0, version.attemptLimit - (enrollment.attempts ?? 0)) : null\n }\n\n @FieldResolver(type => Int, { description: 'How many questions its quiz draws - 0 when it has none.' })\n async quizSize(@Root() enrollment: Enrollment, @Ctx() context: ResolverContext): Promise<number> {\n const tx = learningManagerOf(context)\n const version = await shownVersionOf(tx, context.state.domain, enrollment)\n if (!version || version.passScore == null) return 0\n const all = await tx.getRepository(CourseQuestion).count({ where: { version: { id: version.id } } as any })\n return version.questionCount ? Math.min(version.questionCount, all) : all\n }\n}\n\n/* How a course's enrolments stand, on the course - for a manager (`course` query); nothing for anyone else. */\n@Resolver(Course)\nexport class CourseEnrollmentFields {\n @FieldResolver(type => CourseEnrollmentCounts, { nullable: true, description: \"Where its enrolments stand - cancelled ones left out. For a manager; empty for anyone else.\" })\n async enrollmentCounts(@Root() course: Course, @Ctx() context: ResolverContext): Promise<CourseEnrollmentCounts | null> {\n if (!(await requestHolds(context, 'course', 'query'))) return null\n return (await courseEnrollmentCounts(context)).get(course.id) ?? { total: 0, assigned: 0, inProgress: 0, completed: 0, overdue: 0 }\n }\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EntityManager } from 'typeorm';
|
|
2
2
|
import { CourseQuestion } from '../course/course-question';
|
|
3
|
+
import { CourseUnit } from '../course/course-unit';
|
|
3
4
|
import { CourseVersion } from '../course/course-version';
|
|
4
5
|
import { Enrollment } from './enrollment';
|
|
5
6
|
import { Missing } from './progress-rules';
|
|
@@ -57,6 +58,9 @@ export declare function progressesOf(tx: EntityManager, enrollmentId: string): P
|
|
|
57
58
|
export declare function missingFor(tx: EntityManager, domain: {
|
|
58
59
|
id: string;
|
|
59
60
|
}, enrollment: Enrollment): Promise<Missing[]>;
|
|
61
|
+
export declare function unitOfVersion(tx: EntityManager, version: {
|
|
62
|
+
id: string;
|
|
63
|
+
}, unitId: string): Promise<CourseUnit>;
|
|
60
64
|
export interface TickResult {
|
|
61
65
|
enrollment: Enrollment;
|
|
62
66
|
progress: UnitProgress;
|
|
@@ -10,6 +10,7 @@ exports.myEnrollmentOf = myEnrollmentOf;
|
|
|
10
10
|
exports.shownVersionOf = shownVersionOf;
|
|
11
11
|
exports.progressesOf = progressesOf;
|
|
12
12
|
exports.missingFor = missingFor;
|
|
13
|
+
exports.unitOfVersion = unitOfVersion;
|
|
13
14
|
exports.recordTick = recordTick;
|
|
14
15
|
exports.acknowledgeEnrollment = acknowledgeEnrollment;
|
|
15
16
|
exports.forLearner = forLearner;
|