@things-factory/learning 0.0.0-stage → 10.1.261

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.
Files changed (167) hide show
  1. package/dist-client/bootstrap.d.ts +2 -0
  2. package/dist-client/bootstrap.js +4 -0
  3. package/dist-client/bootstrap.js.map +1 -0
  4. package/dist-client/components/learning-assign-form.d.ts +24 -0
  5. package/dist-client/components/learning-assign-form.js +77 -0
  6. package/dist-client/components/learning-assign-form.js.map +1 -0
  7. package/dist-client/components/learning-course-form.d.ts +29 -0
  8. package/dist-client/components/learning-course-form.js +104 -0
  9. package/dist-client/components/learning-course-form.js.map +1 -0
  10. package/dist-client/components/learning-material-form.d.ts +41 -0
  11. package/dist-client/components/learning-material-form.js +202 -0
  12. package/dist-client/components/learning-material-form.js.map +1 -0
  13. package/dist-client/components/learning-question-form.d.ts +33 -0
  14. package/dist-client/components/learning-question-form.js +142 -0
  15. package/dist-client/components/learning-question-form.js.map +1 -0
  16. package/dist-client/components/learning-todo.d.ts +12 -0
  17. package/dist-client/components/learning-todo.js +43 -0
  18. package/dist-client/components/learning-todo.js.map +1 -0
  19. package/dist-client/components/learning-unit-form.d.ts +44 -0
  20. package/dist-client/components/learning-unit-form.js +151 -0
  21. package/dist-client/components/learning-unit-form.js.map +1 -0
  22. package/dist-client/index.d.ts +2 -0
  23. package/dist-client/index.js +3 -0
  24. package/dist-client/index.js.map +1 -0
  25. package/dist-client/pages/learning-course-editor.d.ts +63 -0
  26. package/dist-client/pages/learning-course-editor.js +476 -0
  27. package/dist-client/pages/learning-course-editor.js.map +1 -0
  28. package/dist-client/pages/learning-course-list.d.ts +37 -0
  29. package/dist-client/pages/learning-course-list.js +92 -0
  30. package/dist-client/pages/learning-course-list.js.map +1 -0
  31. package/dist-client/pages/learning-enrollment-status.d.ts +65 -0
  32. package/dist-client/pages/learning-enrollment-status.js +211 -0
  33. package/dist-client/pages/learning-enrollment-status.js.map +1 -0
  34. package/dist-client/pages/learning-view.d.ts +63 -0
  35. package/dist-client/pages/learning-view.js +446 -0
  36. package/dist-client/pages/learning-view.js.map +1 -0
  37. package/dist-client/pages/my-learning.d.ts +22 -0
  38. package/dist-client/pages/my-learning.js +110 -0
  39. package/dist-client/pages/my-learning.js.map +1 -0
  40. package/dist-client/route.d.ts +1 -0
  41. package/dist-client/route.js +21 -0
  42. package/dist-client/route.js.map +1 -0
  43. package/dist-client/tsconfig.tsbuildinfo +1 -0
  44. package/dist-client/utils/learning-api.d.ts +61 -0
  45. package/dist-client/utils/learning-api.js +85 -0
  46. package/dist-client/utils/learning-api.js.map +1 -0
  47. package/dist-client/utils/learning-words.d.ts +20 -0
  48. package/dist-client/utils/learning-words.js +22 -0
  49. package/dist-client/utils/learning-words.js.map +1 -0
  50. package/dist-client/utils/material-source.d.ts +12 -0
  51. package/dist-client/utils/material-source.js +77 -0
  52. package/dist-client/utils/material-source.js.map +1 -0
  53. package/dist-server/activities.d.ts +38 -0
  54. package/dist-server/activities.js +42 -0
  55. package/dist-server/activities.js.map +1 -0
  56. package/dist-server/ai-reads.d.ts +9 -0
  57. package/dist-server/ai-reads.js +70 -0
  58. package/dist-server/ai-reads.js.map +1 -0
  59. package/dist-server/attachment-reader.d.ts +1 -0
  60. package/dist-server/attachment-reader.js +23 -0
  61. package/dist-server/attachment-reader.js.map +1 -0
  62. package/dist-server/index.d.ts +4 -0
  63. package/dist-server/index.js +33 -0
  64. package/dist-server/index.js.map +1 -0
  65. package/dist-server/learning-subjects.d.ts +10 -0
  66. package/dist-server/learning-subjects.js +31 -0
  67. package/dist-server/learning-subjects.js.map +1 -0
  68. package/dist-server/role-tasks.d.ts +2 -0
  69. package/dist-server/role-tasks.js +17 -0
  70. package/dist-server/role-tasks.js.map +1 -0
  71. package/dist-server/service/course/course-mutation.d.ts +19 -0
  72. package/dist-server/service/course/course-mutation.js +177 -0
  73. package/dist-server/service/course/course-mutation.js.map +1 -0
  74. package/dist-server/service/course/course-query.d.ts +27 -0
  75. package/dist-server/service/course/course-query.js +183 -0
  76. package/dist-server/service/course/course-query.js.map +1 -0
  77. package/dist-server/service/course/course-question.d.ts +41 -0
  78. package/dist-server/service/course/course-question.js +116 -0
  79. package/dist-server/service/course/course-question.js.map +1 -0
  80. package/dist-server/service/course/course-rules.d.ts +51 -0
  81. package/dist-server/service/course/course-rules.js +93 -0
  82. package/dist-server/service/course/course-rules.js.map +1 -0
  83. package/dist-server/service/course/course-service.d.ts +72 -0
  84. package/dist-server/service/course/course-service.js +398 -0
  85. package/dist-server/service/course/course-service.js.map +1 -0
  86. package/dist-server/service/course/course-type.d.ts +56 -0
  87. package/dist-server/service/course/course-type.js +202 -0
  88. package/dist-server/service/course/course-type.js.map +1 -0
  89. package/dist-server/service/course/course-unit.d.ts +37 -0
  90. package/dist-server/service/course/course-unit.js +128 -0
  91. package/dist-server/service/course/course-unit.js.map +1 -0
  92. package/dist-server/service/course/course-version.d.ts +45 -0
  93. package/dist-server/service/course/course-version.js +151 -0
  94. package/dist-server/service/course/course-version.js.map +1 -0
  95. package/dist-server/service/course/course.d.ts +23 -0
  96. package/dist-server/service/course/course.js +92 -0
  97. package/dist-server/service/course/course.js.map +1 -0
  98. package/dist-server/service/course/index.d.ts +15 -0
  99. package/dist-server/service/course/index.js +25 -0
  100. package/dist-server/service/course/index.js.map +1 -0
  101. package/dist-server/service/course/material-audio.d.ts +1 -0
  102. package/dist-server/service/course/material-audio.js +43 -0
  103. package/dist-server/service/course/material-audio.js.map +1 -0
  104. package/dist-server/service/course/material-draft-mutation.d.ts +13 -0
  105. package/dist-server/service/course/material-draft-mutation.js +55 -0
  106. package/dist-server/service/course/material-draft-mutation.js.map +1 -0
  107. package/dist-server/service/course/material-draft-rules.d.ts +38 -0
  108. package/dist-server/service/course/material-draft-rules.js +83 -0
  109. package/dist-server/service/course/material-draft-rules.js.map +1 -0
  110. package/dist-server/service/course/material-draft-service.d.ts +15 -0
  111. package/dist-server/service/course/material-draft-service.js +162 -0
  112. package/dist-server/service/course/material-draft-service.js.map +1 -0
  113. package/dist-server/service/enrollment/enrollment-mutation.d.ts +11 -0
  114. package/dist-server/service/enrollment/enrollment-mutation.js +124 -0
  115. package/dist-server/service/enrollment/enrollment-mutation.js.map +1 -0
  116. package/dist-server/service/enrollment/enrollment-query.d.ts +24 -0
  117. package/dist-server/service/enrollment/enrollment-query.js +236 -0
  118. package/dist-server/service/enrollment/enrollment-query.js.map +1 -0
  119. package/dist-server/service/enrollment/enrollment-remind.d.ts +1 -0
  120. package/dist-server/service/enrollment/enrollment-remind.js +45 -0
  121. package/dist-server/service/enrollment/enrollment-remind.js.map +1 -0
  122. package/dist-server/service/enrollment/enrollment-service.d.ts +110 -0
  123. package/dist-server/service/enrollment/enrollment-service.js +427 -0
  124. package/dist-server/service/enrollment/enrollment-service.js.map +1 -0
  125. package/dist-server/service/enrollment/enrollment-status.d.ts +53 -0
  126. package/dist-server/service/enrollment/enrollment-status.js +194 -0
  127. package/dist-server/service/enrollment/enrollment-status.js.map +1 -0
  128. package/dist-server/service/enrollment/enrollment-type.d.ts +82 -0
  129. package/dist-server/service/enrollment/enrollment-type.js +293 -0
  130. package/dist-server/service/enrollment/enrollment-type.js.map +1 -0
  131. package/dist-server/service/enrollment/enrollment.d.ts +53 -0
  132. package/dist-server/service/enrollment/enrollment.js +191 -0
  133. package/dist-server/service/enrollment/enrollment.js.map +1 -0
  134. package/dist-server/service/enrollment/index.d.ts +15 -0
  135. package/dist-server/service/enrollment/index.js +26 -0
  136. package/dist-server/service/enrollment/index.js.map +1 -0
  137. package/dist-server/service/enrollment/learning-ai.d.ts +45 -0
  138. package/dist-server/service/enrollment/learning-ai.js +93 -0
  139. package/dist-server/service/enrollment/learning-ai.js.map +1 -0
  140. package/dist-server/service/enrollment/learning-documents.d.ts +7 -0
  141. package/dist-server/service/enrollment/learning-documents.js +159 -0
  142. package/dist-server/service/enrollment/learning-documents.js.map +1 -0
  143. package/dist-server/service/enrollment/learning-outcome.d.ts +10 -0
  144. package/dist-server/service/enrollment/learning-outcome.js +16 -0
  145. package/dist-server/service/enrollment/learning-outcome.js.map +1 -0
  146. package/dist-server/service/enrollment/progress-rules.d.ts +119 -0
  147. package/dist-server/service/enrollment/progress-rules.js +132 -0
  148. package/dist-server/service/enrollment/progress-rules.js.map +1 -0
  149. package/dist-server/service/enrollment/quiz-attempt.d.ts +34 -0
  150. package/dist-server/service/enrollment/quiz-attempt.js +105 -0
  151. package/dist-server/service/enrollment/quiz-attempt.js.map +1 -0
  152. package/dist-server/service/enrollment/unit-progress.d.ts +34 -0
  153. package/dist-server/service/enrollment/unit-progress.js +134 -0
  154. package/dist-server/service/enrollment/unit-progress.js.map +1 -0
  155. package/dist-server/service/index.d.ts +14 -0
  156. package/dist-server/service/index.js +43 -0
  157. package/dist-server/service/index.js.map +1 -0
  158. package/dist-server/tsconfig.tsbuildinfo +1 -0
  159. package/package.json +57 -4
  160. package/things-factory.config.js +14 -0
  161. package/translations/en.json +278 -0
  162. package/translations/es.json +278 -0
  163. package/translations/ja.json +278 -0
  164. package/translations/ko.json +278 -0
  165. package/translations/ms.json +278 -0
  166. package/translations/zh.json +278 -0
  167. package/README.md +0 -3
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnrollmentQuery = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const auth_base_1 = require("@things-factory/auth-base");
7
+ const shell_1 = require("@things-factory/shell");
8
+ const course_1 = require("../course/course");
9
+ const course_question_1 = require("../course/course-question");
10
+ const course_version_1 = require("../course/course-version");
11
+ const course_service_1 = require("../course/course-service");
12
+ const enrollment_1 = require("./enrollment");
13
+ const enrollment_service_1 = require("./enrollment-service");
14
+ const enrollment_status_1 = require("./enrollment-status");
15
+ const enrollment_type_1 = require("./enrollment-type");
16
+ const learning_ai_1 = require("./learning-ai");
17
+ const progress_rules_1 = require("./progress-rules");
18
+ const rowOut = (row) => ({ id: row.enrollment.id, ...row });
19
+ const pageOf = ({ rows, total }) => ({ items: rows.map(rowOut), total });
20
+ /** Whether the request reads how an enrolment went - its learner or a manager. */
21
+ async function readsInside(enrollment, context) {
22
+ return enrollment.userId === context.state.user.id || (await (0, auth_base_1.requestHolds)(context, 'course', 'query'));
23
+ }
24
+ /*
25
+ * The reads of enrolments (ADR-0194 decisions 5-11): one's own (`learning` query, the task `learning.taking`); every
26
+ * enrolment and the completion register for a manager (`course` query); a department head's people, status only.
27
+ */
28
+ let EnrollmentQuery = class EnrollmentQuery {
29
+ async myEnrollments(context) {
30
+ return await (0, enrollment_service_1.myEnrollments)(context);
31
+ }
32
+ async myEnrollment(id, context) {
33
+ return await (0, enrollment_service_1.myEnrollmentOf)(context, id);
34
+ }
35
+ async teamEnrollmentStatus(params, context) {
36
+ return pageOf(await (0, enrollment_status_1.enrollmentPage)(params, await (0, enrollment_status_1.teamReachOf)(context), context));
37
+ }
38
+ async enrollmentStatus(params, context) {
39
+ return pageOf(await (0, enrollment_status_1.enrollmentPage)(params, { kind: 'all' }, context));
40
+ }
41
+ async enrollmentStateCounts(params, context) {
42
+ const reach = (await (0, auth_base_1.requestHolds)(context, 'course', 'query')) ? { kind: 'all' } : await (0, enrollment_status_1.teamReachOf)(context);
43
+ return await (0, enrollment_status_1.enrollmentStateCounts)(params, reach, context);
44
+ }
45
+ async completionRegister(courseId, context) {
46
+ return (await (0, enrollment_status_1.completionRegister)(courseId, context)).map(rowOut);
47
+ }
48
+ async learningEnrollments(params, context) {
49
+ return await (0, learning_ai_1.readableEnrollments)(params, context);
50
+ }
51
+ async learningContent(enrollmentId, versionId, context) {
52
+ return await (0, learning_ai_1.courseContent)({ enrollmentId, versionId }, context);
53
+ }
54
+ /* ---------------------------------------------------------------- fields */
55
+ async course(enrollment) {
56
+ return enrollment.courseId ? await (0, shell_1.getRepository)(course_1.Course).findOneBy({ id: enrollment.courseId }) : null;
57
+ }
58
+ async user(enrollment) {
59
+ return enrollment.userId ? await (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: enrollment.userId }) : null;
60
+ }
61
+ async version(enrollment, context) {
62
+ return await (0, enrollment_service_1.shownVersionOf)((0, course_service_1.learningManagerOf)(context), context.state.domain, enrollment);
63
+ }
64
+ state(enrollment, context) {
65
+ return (0, progress_rules_1.overdue)(enrollment, (0, enrollment_service_1.todayIn)(context.state.domain)) ? 'OVERDUE' : enrollment.status;
66
+ }
67
+ async units(enrollment, context) {
68
+ if (!(await readsInside(enrollment, context)))
69
+ return [];
70
+ const tx = (0, course_service_1.learningManagerOf)(context);
71
+ const version = await (0, enrollment_service_1.shownVersionOf)(tx, context.state.domain, enrollment);
72
+ if (!version)
73
+ return [];
74
+ const progress = await (0, enrollment_service_1.progressesOf)(tx, enrollment.id);
75
+ return (await (0, course_service_1.unitsOf)(tx, version.id)).map(unit => ({ unit, progress: progress.find(one => one.unitId === unit.id) ?? null, counts: (0, progress_rules_1.counts)(unit) }));
76
+ }
77
+ async missing(enrollment, context) {
78
+ if (!(await readsInside(enrollment, context)))
79
+ return [];
80
+ return await (0, enrollment_service_1.missingFor)((0, course_service_1.learningManagerOf)(context), context.state.domain, enrollment);
81
+ }
82
+ async attemptsLeft(enrollment, context) {
83
+ if (!(await readsInside(enrollment, context)))
84
+ return null;
85
+ const version = await (0, enrollment_service_1.shownVersionOf)((0, course_service_1.learningManagerOf)(context), context.state.domain, enrollment);
86
+ return version?.attemptLimit != null ? Math.max(0, version.attemptLimit - (enrollment.attempts ?? 0)) : null;
87
+ }
88
+ async quizSize(enrollment, context) {
89
+ const tx = (0, course_service_1.learningManagerOf)(context);
90
+ const version = await (0, enrollment_service_1.shownVersionOf)(tx, context.state.domain, enrollment);
91
+ if (!version || version.passScore == null)
92
+ return 0;
93
+ const all = await tx.getRepository(course_question_1.CourseQuestion).count({ where: { version: { id: version.id } } });
94
+ return version.questionCount ? Math.min(version.questionCount, all) : all;
95
+ }
96
+ };
97
+ exports.EnrollmentQuery = EnrollmentQuery;
98
+ tslib_1.__decorate([
99
+ (0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
100
+ (0, type_graphql_1.Query)(returns => [enrollment_1.Enrollment], { description: "The request's own enrolments - open ones first, the soonest due first, then the completed." }),
101
+ tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
102
+ tslib_1.__metadata("design:type", Function),
103
+ tslib_1.__metadata("design:paramtypes", [Object]),
104
+ tslib_1.__metadata("design:returntype", Promise)
105
+ ], EnrollmentQuery.prototype, "myEnrollments", null);
106
+ tslib_1.__decorate([
107
+ (0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
108
+ (0, type_graphql_1.Query)(returns => enrollment_1.Enrollment, { description: "One of the request's own enrolments." }),
109
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
110
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
111
+ tslib_1.__metadata("design:type", Function),
112
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
113
+ tslib_1.__metadata("design:returntype", Promise)
114
+ ], EnrollmentQuery.prototype, "myEnrollment", null);
115
+ tslib_1.__decorate([
116
+ (0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
117
+ (0, type_graphql_1.Query)(returns => enrollment_type_1.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." }),
118
+ tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
119
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
120
+ tslib_1.__metadata("design:type", Function),
121
+ tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
122
+ tslib_1.__metadata("design:returntype", Promise)
123
+ ], EnrollmentQuery.prototype, "teamEnrollmentStatus", null);
124
+ tslib_1.__decorate([
125
+ (0, type_graphql_1.Directive)('@privilege(category: "course", privilege: "query", domainOwnerGranted: true)'),
126
+ (0, type_graphql_1.Query)(returns => enrollment_type_1.EnrollmentStatusList, { description: "Every enrolment, with its progress and evidence. Filters: course, state, sourceKind, sourceId; search: the learner's name or the course's." }),
127
+ tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
128
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
129
+ tslib_1.__metadata("design:type", Function),
130
+ tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
131
+ tslib_1.__metadata("design:returntype", Promise)
132
+ ], EnrollmentQuery.prototype, "enrollmentStatus", null);
133
+ tslib_1.__decorate([
134
+ (0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
135
+ (0, type_graphql_1.Query)(returns => [shell_1.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." }),
136
+ tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
137
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
138
+ tslib_1.__metadata("design:type", Function),
139
+ tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
140
+ tslib_1.__metadata("design:returntype", Promise)
141
+ ], EnrollmentQuery.prototype, "enrollmentStateCounts", null);
142
+ tslib_1.__decorate([
143
+ (0, type_graphql_1.Directive)('@privilege(category: "course", privilege: "query", domainOwnerGranted: true)'),
144
+ (0, type_graphql_1.Query)(returns => [enrollment_type_1.EnrollmentStatusRow], { description: 'The completion register of a course - every completion by its day.' }),
145
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('courseId')),
146
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
147
+ tslib_1.__metadata("design:type", Function),
148
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
149
+ tslib_1.__metadata("design:returntype", Promise)
150
+ ], EnrollmentQuery.prototype, "completionRegister", null);
151
+ tslib_1.__decorate([
152
+ (0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
153
+ (0, type_graphql_1.Query)(returns => enrollment_type_1.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).' }),
154
+ tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
155
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
156
+ tslib_1.__metadata("design:type", Function),
157
+ tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
158
+ tslib_1.__metadata("design:returntype", Promise)
159
+ ], EnrollmentQuery.prototype, "learningEnrollments", null);
160
+ tslib_1.__decorate([
161
+ (0, type_graphql_1.Directive)('@privilege(category: "learning", privilege: "query", domainOwnerGranted: true)'),
162
+ (0, type_graphql_1.Query)(returns => enrollment_type_1.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)." }),
163
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('enrollmentId', { nullable: true })),
164
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('versionId', { nullable: true })),
165
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
166
+ tslib_1.__metadata("design:type", Function),
167
+ tslib_1.__metadata("design:paramtypes", [String, String, Object]),
168
+ tslib_1.__metadata("design:returntype", Promise)
169
+ ], EnrollmentQuery.prototype, "learningContent", null);
170
+ tslib_1.__decorate([
171
+ (0, type_graphql_1.FieldResolver)(type => course_1.Course, { nullable: true, description: 'The course.' }),
172
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
173
+ tslib_1.__metadata("design:type", Function),
174
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment]),
175
+ tslib_1.__metadata("design:returntype", Promise)
176
+ ], EnrollmentQuery.prototype, "course", null);
177
+ tslib_1.__decorate([
178
+ (0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true, description: 'Who takes it.' }),
179
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
180
+ tslib_1.__metadata("design:type", Function),
181
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment]),
182
+ tslib_1.__metadata("design:returntype", Promise)
183
+ ], EnrollmentQuery.prototype, "user", null);
184
+ tslib_1.__decorate([
185
+ (0, type_graphql_1.FieldResolver)(type => course_version_1.CourseVersion, { nullable: true, description: 'The version it shows - its own once started, the published one before.' }),
186
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
187
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
188
+ tslib_1.__metadata("design:type", Function),
189
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment, Object]),
190
+ tslib_1.__metadata("design:returntype", Promise)
191
+ ], EnrollmentQuery.prototype, "version", null);
192
+ tslib_1.__decorate([
193
+ (0, type_graphql_1.FieldResolver)(type => String, { description: 'Where it stands today - OVERDUE for an open one past its due day.' }),
194
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
195
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
196
+ tslib_1.__metadata("design:type", Function),
197
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment, Object]),
198
+ tslib_1.__metadata("design:returntype", String)
199
+ ], EnrollmentQuery.prototype, "state", null);
200
+ tslib_1.__decorate([
201
+ (0, type_graphql_1.FieldResolver)(type => [enrollment_type_1.LearningUnit], { description: 'Its units with how far the learner went - for its learner and managers.' }),
202
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
203
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
204
+ tslib_1.__metadata("design:type", Function),
205
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment, Object]),
206
+ tslib_1.__metadata("design:returntype", Promise)
207
+ ], EnrollmentQuery.prototype, "units", null);
208
+ tslib_1.__decorate([
209
+ (0, type_graphql_1.FieldResolver)(type => [String], { description: 'What still stands before completion - units, time, quiz, acknowledgement.' }),
210
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
211
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
212
+ tslib_1.__metadata("design:type", Function),
213
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment, Object]),
214
+ tslib_1.__metadata("design:returntype", Promise)
215
+ ], EnrollmentQuery.prototype, "missing", null);
216
+ tslib_1.__decorate([
217
+ (0, type_graphql_1.FieldResolver)(type => type_graphql_1.Int, { nullable: true, description: 'The quiz attempts left - no limit, or no quiz, when empty.' }),
218
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
219
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
220
+ tslib_1.__metadata("design:type", Function),
221
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment, Object]),
222
+ tslib_1.__metadata("design:returntype", Promise)
223
+ ], EnrollmentQuery.prototype, "attemptsLeft", null);
224
+ tslib_1.__decorate([
225
+ (0, type_graphql_1.FieldResolver)(type => type_graphql_1.Int, { description: 'How many questions its quiz draws - 0 when it has none.' }),
226
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
227
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
228
+ tslib_1.__metadata("design:type", Function),
229
+ tslib_1.__metadata("design:paramtypes", [enrollment_1.Enrollment, Object]),
230
+ tslib_1.__metadata("design:returntype", Promise)
231
+ ], EnrollmentQuery.prototype, "quizSize", null);
232
+ exports.EnrollmentQuery = EnrollmentQuery = tslib_1.__decorate([
233
+ (0, type_graphql_1.Resolver)(enrollment_1.Enrollment),
234
+ (0, type_graphql_1.UseMiddleware)(shell_1.SpeakRefusals)
235
+ ], EnrollmentQuery);
236
+ //# sourceMappingURL=enrollment-query.js.map
@@ -0,0 +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, enrollmentPage, enrollmentStateCounts, StatusRow, teamReachOf } from './enrollment-status'\nimport { 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"]}
@@ -0,0 +1 @@
1
+ export declare function remindEnrollments(ids: string[], context: any): Promise<number>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.remindEnrollments = remindEnrollments;
4
+ /*
5
+ * A manager reminds learners of their open enrolments (ADR-0194 decision 10) - through notification, as every notice
6
+ * goes: the app, a web push and a mail where the domain turned it on. Sent once the request commits.
7
+ */
8
+ const typeorm_1 = require("typeorm");
9
+ const auth_base_1 = require("@things-factory/auth-base");
10
+ const translator_1 = require("@things-factory/i18n-base/translator");
11
+ const notification_1 = require("@things-factory/notification");
12
+ const course_1 = require("../course/course");
13
+ const enrollment_1 = require("./enrollment");
14
+ const enrollment_service_1 = require("./enrollment-service");
15
+ async function remindEnrollments(ids, context) {
16
+ const { domain, tx } = context.state;
17
+ if (!ids?.length)
18
+ return 0;
19
+ const rows = await tx.getRepository(enrollment_1.Enrollment).find({ where: { id: (0, typeorm_1.In)(ids), domain: { id: domain.id }, status: (0, typeorm_1.In)(enrollment_1.OPEN_ENROLLMENT_STATUSES) } });
20
+ for (const row of rows) {
21
+ const user = await tx.getRepository(auth_base_1.User).findOneBy({ id: row.userId });
22
+ const course = await tx.getRepository(course_1.Course).findOneBy({ id: row.courseId });
23
+ if (!user || !course)
24
+ continue;
25
+ const address = (0, enrollment_service_1.learningAddressOf)(row.id);
26
+ (0, notification_1.sendNoticeWhenCommitted)(context, {
27
+ type: 'learning',
28
+ label: `learning reminded ${row.id}`,
29
+ receivers: [{ id: user.id, email: user.email, locale: user.locale }],
30
+ address,
31
+ link: (0, notification_1.noticeLinkOf)(context, address),
32
+ words: (lng) => {
33
+ const t = (0, translator_1.translatorFor)(lng);
34
+ return {
35
+ subject: t('text.learning-remind-subject', { course: course.name }),
36
+ body: row.dueOn ? t('text.learning-remind-body', { course: course.name, dueOn: row.dueOn }) : t('text.learning-remind-body-no-due', { course: course.name }),
37
+ action: t('text.learning-remind-action'),
38
+ note: t('text.learning-remind-note')
39
+ };
40
+ }
41
+ });
42
+ }
43
+ return rows.length;
44
+ }
45
+ //# sourceMappingURL=enrollment-remind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrollment-remind.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment-remind.ts"],"names":[],"mappings":";;AAcA,8CA2BC;AAzCD;;;GAGG;AACH,qCAA4B;AAE5B,yDAAgD;AAChD,qEAAoE;AACpE,+DAAoF;AAEpF,6CAAyC;AACzC,6CAAmE;AACnE,6DAAwD;AAEjD,KAAK,UAAU,iBAAiB,CAAC,GAAa,EAAE,OAAY;IACjE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IACpC,IAAI,CAAC,GAAG,EAAE,MAAM;QAAE,OAAO,CAAC,CAAA;IAC1B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAA,YAAE,EAAC,qCAAwB,CAAC,EAAS,EAAE,CAAC,CAAA;IACxJ,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QACvE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,eAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC7E,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,SAAQ;QAC9B,MAAM,OAAO,GAAG,IAAA,sCAAiB,EAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACzC,IAAA,sCAAuB,EAAC,OAAO,EAAE;YAC/B,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,qBAAqB,GAAG,CAAC,EAAE,EAAE;YACpC,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YACpE,OAAO;YACP,IAAI,EAAE,IAAA,2BAAY,EAAC,OAAO,EAAE,OAAO,CAAC;YACpC,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE;gBACrB,MAAM,CAAC,GAAG,IAAA,0BAAa,EAAC,GAAG,CAAC,CAAA;gBAC5B,OAAO;oBACL,OAAO,EAAE,CAAC,CAAC,8BAA8B,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;oBACnE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kCAAkC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;oBAC5J,MAAM,EAAE,CAAC,CAAC,6BAA6B,CAAC;oBACxC,IAAI,EAAE,CAAC,CAAC,2BAA2B,CAAC;iBACrC,CAAA;YACH,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAA;AACpB,CAAC","sourcesContent":["/*\n * A manager reminds learners of their open enrolments (ADR-0194 decision 10) - through notification, as every notice\n * goes: the app, a web push and a mail where the domain turned it on. Sent once the request commits.\n */\nimport { In } from 'typeorm'\n\nimport { User } from '@things-factory/auth-base'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { noticeLinkOf, sendNoticeWhenCommitted } from '@things-factory/notification'\n\nimport { Course } from '../course/course'\nimport { Enrollment, OPEN_ENROLLMENT_STATUSES } from './enrollment'\nimport { learningAddressOf } from './enrollment-service'\n\nexport async function remindEnrollments(ids: string[], context: any): Promise<number> {\n const { domain, tx } = context.state\n if (!ids?.length) return 0\n const rows = await tx.getRepository(Enrollment).find({ where: { id: In(ids), domain: { id: domain.id }, status: In(OPEN_ENROLLMENT_STATUSES) } as any })\n for (const row of rows) {\n const user = await tx.getRepository(User).findOneBy({ id: row.userId })\n const course = await tx.getRepository(Course).findOneBy({ id: row.courseId })\n if (!user || !course) continue\n const address = learningAddressOf(row.id)\n sendNoticeWhenCommitted(context, {\n type: 'learning',\n label: `learning reminded ${row.id}`,\n receivers: [{ id: user.id, email: user.email, locale: user.locale }],\n address,\n link: noticeLinkOf(context, address),\n words: (lng: string) => {\n const t = translatorFor(lng)\n return {\n subject: t('text.learning-remind-subject', { course: course.name }),\n body: row.dueOn ? t('text.learning-remind-body', { course: course.name, dueOn: row.dueOn }) : t('text.learning-remind-body-no-due', { course: course.name }),\n action: t('text.learning-remind-action'),\n note: t('text.learning-remind-note')\n }\n }\n })\n }\n return rows.length\n}\n"]}
@@ -0,0 +1,110 @@
1
+ import { EntityManager } from 'typeorm';
2
+ import { CourseQuestion } from '../course/course-question';
3
+ import { CourseVersion } from '../course/course-version';
4
+ import { Enrollment } from './enrollment';
5
+ import { Missing } from './progress-rules';
6
+ import { QuizAttempt } from './quiz-attempt';
7
+ import { UnitProgress } from './unit-progress';
8
+ /** Who asked for an enrolment - a module's kind of record and the record. A manager's own is `learning.direct`. */
9
+ export interface LearningSource {
10
+ kind: string;
11
+ id?: string | null;
12
+ }
13
+ export declare const DIRECT_SOURCE_KIND = "learning.direct";
14
+ /** The learner's screen of one enrolment - where the to-do leads. */
15
+ export declare const learningAddressOf: (enrollmentId: string) => string;
16
+ export declare const todayIn: (domain: {
17
+ timezone?: string | null;
18
+ }, now?: Date) => string;
19
+ declare const isOpen: (status: string) => boolean;
20
+ /**
21
+ * Enrols people in a course for whoever asks (`source`), to be completed by `dueOn` - the server function a using module
22
+ * calls with the people it chose. One open enrolment per person, course and source: a person who has one is left with
23
+ * it. Each new enrolment hands out its to-do. Answers the open enrolments of everyone given.
24
+ */
25
+ export declare function enroll(source: LearningSource, userIds: string[], courseId: string, dueOn: string | null | undefined, context: any): Promise<Enrollment[]>;
26
+ /**
27
+ * Withdraws the open enrolments a source asked for - the record they were for was taken back. Each is cancelled with
28
+ * the reason and its to-do aborted; completed ones stay. Answers how many were withdrawn.
29
+ */
30
+ export declare function withdraw(source: LearningSource, reason: string, context: any): Promise<number>;
31
+ /**
32
+ * A manager cancels an enrolment with a reason (decision 8). An open one is withdrawn; a completed one stays on record as
33
+ * cancelled - never deleted - and whoever asked for it is told in the same transaction.
34
+ */
35
+ export declare function cancelEnrollment(id: string, reason: string, context: any): Promise<Enrollment>;
36
+ /**
37
+ * The people an audience names now - the domain, departments with those under them, roles and people, by organization's
38
+ * one rule (ADR-0163). Each target must be of this domain.
39
+ */
40
+ export declare function learnersOf(audiences: {
41
+ scope: string;
42
+ targetId: string;
43
+ targetName?: string;
44
+ }[], context: any): Promise<string[]>;
45
+ export declare function enrollmentOf(tx: EntityManager, domain: {
46
+ id: string;
47
+ }, id: string): Promise<Enrollment>;
48
+ /** The request's own enrolment - one answer for "none" and "not yours". */
49
+ export declare function myEnrollmentOf(context: any, id: string, tx?: EntityManager): Promise<Enrollment>;
50
+ /** The version an enrolment shows: its own once started, the published one before. */
51
+ export declare function shownVersionOf(tx: EntityManager, domain: {
52
+ id: string;
53
+ }, enrollment: Enrollment): Promise<CourseVersion | null>;
54
+ export declare function progressesOf(tx: EntityManager, enrollmentId: string): Promise<UnitProgress[]>;
55
+ /** What still stands between an enrolment and its completion - nothing for a completed one. */
56
+ export declare function missingFor(tx: EntityManager, domain: {
57
+ id: string;
58
+ }, enrollment: Enrollment): Promise<Missing[]>;
59
+ export interface TickResult {
60
+ enrollment: Enrollment;
61
+ progress: UnitProgress;
62
+ }
63
+ /**
64
+ * One tick of the learner's screen on a unit (decision 6): the server adds the gap since the unit's last tick, at most
65
+ * 15 seconds and at most what the screen says, and refuses a video position ahead of what was watched. A total the
66
+ * screen sends is never taken. A unit that reaches its condition is done, and the enrolment is completed when nothing is
67
+ * missing any more.
68
+ */
69
+ export declare function recordTick(enrollmentId: string, unitId: string, seconds: number, position: number, context: any, now?: Date): Promise<TickResult>;
70
+ /** The learner confirms the version's acknowledgement - recorded once, when they did. */
71
+ export declare function acknowledgeEnrollment(enrollmentId: string, context: any): Promise<Enrollment>;
72
+ export interface DrawnForLearner {
73
+ attempt: QuizAttempt;
74
+ questions: {
75
+ id: string;
76
+ kind: string;
77
+ text: string;
78
+ choices: {
79
+ id: string;
80
+ text: string;
81
+ }[];
82
+ }[];
83
+ }
84
+ /** The questions of an attempt as the learner is drawn them - the choices in the order shown, never whether one is right. */
85
+ export declare function forLearner(attempt: QuizAttempt, questions: CourseQuestion[]): DrawnForLearner;
86
+ export declare function startQuizAttempt(enrollmentId: string, context: any): Promise<DrawnForLearner>;
87
+ export interface QuizResult {
88
+ enrollment: Enrollment;
89
+ score: number;
90
+ passed: boolean;
91
+ attemptsLeft: number | null;
92
+ }
93
+ /**
94
+ * Scores an attempt's answers on the server against what it drew (decision 4) - only the score and whether it passed go
95
+ * back, never the right answers. The best score stays on the enrolment; passing may complete it.
96
+ */
97
+ export declare function submitQuizAttempt(attemptId: string, answers: Record<string, string[]>, context: any): Promise<QuizResult>;
98
+ /** A certificate number: the day completed and the enrolment's own id - one per completion, never reused. */
99
+ export declare const certificateNoOf: (enrollment: {
100
+ id: string;
101
+ }, day: string) => string;
102
+ /**
103
+ * Completes an open enrolment when nothing is missing - every unit done, the least time, the quiz passed, the
104
+ * acknowledgement confirmed. The evidence stays on it; whoever asked for it is told in this same transaction (a handler
105
+ * that fails takes the completion back), and the to-do ends as done.
106
+ */
107
+ export declare function completeIfMet(tx: EntityManager, domain: any, enrollment: Enrollment, context: any): Promise<Enrollment>;
108
+ /** The open and completed enrolments of the request's person, the open first and the soonest due first. */
109
+ export declare function myEnrollments(context: any): Promise<Enrollment[]>;
110
+ export { isOpen };