@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 @@
1
+ {"version":3,"file":"enrollment-type.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, InputType, Int, ObjectType } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\n\nimport { Course } from '../course/course'\nimport { CourseUnit } from '../course/course-unit'\nimport { Enrollment } from './enrollment'\nimport { UnitProgress } from './unit-progress'\n\n@ObjectType({ description: 'A unit as its learner sees it - with how far they went through it' })\nexport class LearningUnit {\n @Field(type => CourseUnit, { description: 'The unit.' })\n unit: CourseUnit\n\n @Field(type => UnitProgress, { nullable: true, description: 'How far the learner went - none before they started it.' })\n progress?: UnitProgress | null\n\n @Field({ description: 'Whether it counts toward completion - a link does not.' })\n counts: boolean\n}\n\n@ObjectType({ description: 'A choice as a learner is drawn it - never whether it is right' })\nexport class QuizChoiceView {\n @Field({ description: 'The choice id.' })\n id: string\n\n @Field({ description: 'What it says.' })\n text: string\n}\n\n@ObjectType({ description: 'A question as a learner is drawn it - its choices in the order shown, no answer' })\nexport class QuizQuestionView {\n @Field({ description: 'The question id.' })\n id: string\n\n @Field({ description: 'SINGLE, MULTIPLE or TRUE_FALSE.' })\n kind: string\n\n @Field({ description: 'What it asks.' })\n text: string\n\n @Field(type => [QuizChoiceView], { description: 'Its choices, shuffled.' })\n choices: QuizChoiceView[]\n}\n\n@ObjectType({ description: 'An attempt as a learner is drawn it' })\nexport class QuizAttemptView {\n @Field({ description: 'The attempt id - its answers are sent with it.' })\n attemptId: string\n\n @Field(type => [QuizQuestionView], { description: 'The questions drawn, shuffled.' })\n questions: QuizQuestionView[]\n}\n\n@ObjectType({ description: \"An attempt's result - the score and whether it passed; never the right answers\" })\nexport class QuizResultView {\n @Field(type => Int, { description: 'The score, out of 100.' })\n score: number\n\n @Field({ description: 'Whether it passed.' })\n passed: boolean\n\n @Field(type => Int, { nullable: true, description: 'Attempts left - no limit when empty.' })\n attemptsLeft?: number | null\n\n @Field(type => Enrollment, { description: 'The enrolment after it - completed when nothing else is missing.' })\n enrollment: Enrollment\n}\n\n@ObjectType({ description: \"A tick's result - the unit's progress and the enrolment after it\" })\nexport class LearningTickResult {\n @Field(type => Enrollment, { description: 'The enrolment.' })\n enrollment: Enrollment\n\n @Field(type => UnitProgress, { description: \"The unit's progress.\" })\n progress: UnitProgress\n}\n\n@ObjectType({ description: 'One enrolment as the status reads it' })\nexport class EnrollmentStatusRow {\n @Field({ description: 'The enrolment id.' })\n id: string\n\n @Field(type => Enrollment, { description: 'The enrolment - for a department head its status and days only.' })\n enrollment: Enrollment\n\n @Field(type => User, { nullable: true, description: 'Who takes it.' })\n user?: User | null\n\n @Field(type => Course, { nullable: true, description: 'The course.' })\n course?: Course | null\n\n @Field({ nullable: true, description: 'Their department.' })\n departmentName?: string | null\n\n @Field({ description: 'ASSIGNED, IN_PROGRESS, COMPLETED, CANCELLED, or OVERDUE for an open one past its due day.' })\n state: string\n\n @Field(type => Int, { description: 'The units that count.' })\n units: number\n\n @Field(type => Int, { description: 'The units done.' })\n unitsDone: number\n\n @Field(type => Int, { nullable: true, description: 'The version taken.' })\n versionNumber?: number | null\n}\n\n@ObjectType({ description: 'A page of enrolments as the status reads them' })\nexport class EnrollmentStatusList {\n @Field(type => [EnrollmentStatusRow], { description: 'The enrolments of the page.' })\n items: EnrollmentStatusRow[]\n\n @Field(type => Int, { description: 'How many there are under the conditions.' })\n total: number\n}\n\n@InputType({ description: 'One target of an audience - the domain, a department (with those under it), a role or a person' })\nexport class LearningAudienceInput {\n @Field({ description: 'DOMAIN | DEPARTMENT | ROLE | USER.' })\n scope: string\n\n @Field({ description: 'The id of the domain, department, role or user.' })\n targetId: string\n\n @Field({ nullable: true, description: 'Its name, as shown.' })\n targetName?: string\n}\n\n@ObjectType({ description: 'An enrolment as the assistant lists it' })\nexport class LearningEnrollmentRow {\n @Field({ description: 'The enrolment id.' }) id: string\n @Field({ description: 'Who takes it.' }) learner: string\n @Field({ nullable: true, description: 'Their department.' }) departmentName?: string | null\n @Field({ description: 'The course.' }) course: string\n @Field({ description: 'ASSIGNED, IN_PROGRESS, COMPLETED or OVERDUE.' }) state: string\n @Field({ nullable: true, description: 'YYYY-MM-DD it is due.' }) dueOn?: string | null\n @Field(type => Int, { nullable: true, description: 'Days to the due day - negative past it.' }) daysLeft?: number | null\n @Field({ nullable: true, description: 'When it was started.' }) startedAt?: Date | null\n @Field({ nullable: true, description: 'When it was completed.' }) completedAt?: Date | null\n @Field(type => Int, { description: 'Units done.' }) unitsDone: number\n @Field(type => Int, { description: 'Units that count.' }) units: number\n}\n\n@ObjectType({ description: 'A page of enrolments as the assistant lists them' })\nexport class LearningEnrollmentList {\n @Field(type => [LearningEnrollmentRow], { description: 'The enrolments.' }) items: LearningEnrollmentRow[]\n @Field(type => Int, { description: 'How many there are.' }) total: number\n}\n\n@ObjectType({ description: 'A unit as the assistant reads it' })\nexport class LearningContentUnit {\n @Field(type => Int, { description: 'Its place.' }) seq: number\n @Field({ description: 'VIDEO, PDF, MARKDOWN or LINK.' }) kind: string\n @Field({ description: 'Its name.' }) name: string\n @Field({ nullable: true, description: 'The text of a MARKDOWN unit, the address of a LINK.' }) text?: string | null\n}\n\n@ObjectType({ description: 'The units of one course version, as the assistant reads them' })\nexport class LearningContent {\n @Field({ description: 'The course.' }) course: string\n @Field(type => Int, { description: 'The version number.' }) version: number\n @Field(type => [LearningContentUnit], { description: 'Its units.' }) units: LearningContentUnit[]\n}\n"]}
@@ -0,0 +1,53 @@
1
+ import { User } from '@things-factory/auth-base';
2
+ import { Domain } from '@things-factory/shell';
3
+ import { Course } from '../course/course';
4
+ import { CourseVersion } from '../course/course-version';
5
+ /** Where an enrolment stands - one past its due day and not completed reads as overdue, it is not kept. */
6
+ export declare enum EnrollmentStatus {
7
+ ASSIGNED = "ASSIGNED",
8
+ IN_PROGRESS = "IN_PROGRESS",
9
+ COMPLETED = "COMPLETED",
10
+ CANCELLED = "CANCELLED"
11
+ }
12
+ /** The statuses of an open enrolment - one per person, course and source. */
13
+ export declare const OPEN_ENROLLMENT_STATUSES: EnrollmentStatus[];
14
+ /**
15
+ * 수강 (ADR-0194 decisions 5, 7, 8) - one person to take one course by a day, for whoever asked (`sourceKind` and
16
+ * `sourceId`: `compliance.training-session` and the session, `learning.direct` for a manager's own). The version is fixed when
17
+ * the person starts. Open ones are one per person, course and source (a partial unique index). A completion keeps its
18
+ * evidence - minutes, score, attempts, when it was confirmed, the version - and is never deleted: a wrong one is
19
+ * cancelled with a reason.
20
+ */
21
+ export declare class Enrollment {
22
+ readonly id: string;
23
+ domain?: Domain;
24
+ domainId?: string;
25
+ user?: User;
26
+ userId?: string;
27
+ course?: Course;
28
+ courseId?: string;
29
+ version?: CourseVersion;
30
+ versionId?: string;
31
+ dueOn?: string;
32
+ sourceKind: string;
33
+ sourceId: string;
34
+ status: EnrollmentStatus;
35
+ startedAt?: Date;
36
+ learnedSeconds: number;
37
+ acknowledgedAt?: Date;
38
+ score?: number;
39
+ attempts: number;
40
+ completedAt?: Date;
41
+ certificateNo?: string;
42
+ cancelledAt?: Date;
43
+ cancelReason?: string;
44
+ todoInstanceId?: string;
45
+ lastUnitId?: string;
46
+ createdAt?: Date;
47
+ updatedAt?: Date;
48
+ deletedAt?: Date;
49
+ creator?: User;
50
+ creatorId?: string;
51
+ updater?: User;
52
+ updaterId?: string;
53
+ }
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Enrollment = exports.OPEN_ENROLLMENT_STATUSES = exports.EnrollmentStatus = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const typeorm_1 = require("typeorm");
7
+ const auth_base_1 = require("@things-factory/auth-base");
8
+ const shell_1 = require("@things-factory/shell");
9
+ const course_1 = require("../course/course");
10
+ const course_version_1 = require("../course/course-version");
11
+ /** Where an enrolment stands - one past its due day and not completed reads as overdue, it is not kept. */
12
+ var EnrollmentStatus;
13
+ (function (EnrollmentStatus) {
14
+ EnrollmentStatus["ASSIGNED"] = "ASSIGNED";
15
+ EnrollmentStatus["IN_PROGRESS"] = "IN_PROGRESS";
16
+ EnrollmentStatus["COMPLETED"] = "COMPLETED";
17
+ EnrollmentStatus["CANCELLED"] = "CANCELLED";
18
+ })(EnrollmentStatus || (exports.EnrollmentStatus = EnrollmentStatus = {}));
19
+ (0, type_graphql_1.registerEnumType)(EnrollmentStatus, { name: 'EnrollmentStatus', description: 'ASSIGNED - not started; IN_PROGRESS - started; COMPLETED - every condition met; CANCELLED - withdrawn by who asked for it, or by a manager.' });
20
+ /** The statuses of an open enrolment - one per person, course and source. */
21
+ exports.OPEN_ENROLLMENT_STATUSES = [EnrollmentStatus.ASSIGNED, EnrollmentStatus.IN_PROGRESS];
22
+ /**
23
+ * 수강 (ADR-0194 decisions 5, 7, 8) - one person to take one course by a day, for whoever asked (`sourceKind` and
24
+ * `sourceId`: `compliance.training-session` and the session, `learning.direct` for a manager's own). The version is fixed when
25
+ * the person starts. Open ones are one per person, course and source (a partial unique index). A completion keeps its
26
+ * evidence - minutes, score, attempts, when it was confirmed, the version - and is never deleted: a wrong one is
27
+ * cancelled with a reason.
28
+ */
29
+ let Enrollment = class Enrollment {
30
+ };
31
+ exports.Enrollment = Enrollment;
32
+ tslib_1.__decorate([
33
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
34
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID, { description: 'Enrollment id.' }),
35
+ tslib_1.__metadata("design:type", String)
36
+ ], Enrollment.prototype, "id", void 0);
37
+ tslib_1.__decorate([
38
+ (0, typeorm_1.ManyToOne)(type => shell_1.Domain),
39
+ (0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true, description: 'The domain.' }),
40
+ tslib_1.__metadata("design:type", shell_1.Domain)
41
+ ], Enrollment.prototype, "domain", void 0);
42
+ tslib_1.__decorate([
43
+ (0, typeorm_1.RelationId)((row) => row.domain),
44
+ tslib_1.__metadata("design:type", String)
45
+ ], Enrollment.prototype, "domainId", void 0);
46
+ tslib_1.__decorate([
47
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User),
48
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who takes it.' }),
49
+ tslib_1.__metadata("design:type", auth_base_1.User)
50
+ ], Enrollment.prototype, "user", void 0);
51
+ tslib_1.__decorate([
52
+ (0, typeorm_1.RelationId)((row) => row.user),
53
+ tslib_1.__metadata("design:type", String)
54
+ ], Enrollment.prototype, "userId", void 0);
55
+ tslib_1.__decorate([
56
+ (0, typeorm_1.ManyToOne)(type => course_1.Course),
57
+ (0, type_graphql_1.Field)(type => course_1.Course, { nullable: true, description: 'The course.' }),
58
+ tslib_1.__metadata("design:type", course_1.Course)
59
+ ], Enrollment.prototype, "course", void 0);
60
+ tslib_1.__decorate([
61
+ (0, typeorm_1.RelationId)((row) => row.course),
62
+ tslib_1.__metadata("design:type", String)
63
+ ], Enrollment.prototype, "courseId", void 0);
64
+ tslib_1.__decorate([
65
+ (0, typeorm_1.ManyToOne)(type => course_version_1.CourseVersion, { nullable: true }),
66
+ (0, type_graphql_1.Field)(type => course_version_1.CourseVersion, { nullable: true, description: 'The version taken - fixed when the person starts.' }),
67
+ tslib_1.__metadata("design:type", course_version_1.CourseVersion)
68
+ ], Enrollment.prototype, "version", void 0);
69
+ tslib_1.__decorate([
70
+ (0, typeorm_1.RelationId)((row) => row.version),
71
+ tslib_1.__metadata("design:type", String)
72
+ ], Enrollment.prototype, "versionId", void 0);
73
+ tslib_1.__decorate([
74
+ (0, typeorm_1.Column)({ nullable: true }),
75
+ (0, type_graphql_1.Field)({ nullable: true, description: 'YYYY-MM-DD it is to be completed by.' }),
76
+ tslib_1.__metadata("design:type", String)
77
+ ], Enrollment.prototype, "dueOn", void 0);
78
+ tslib_1.__decorate([
79
+ (0, typeorm_1.Column)(),
80
+ (0, type_graphql_1.Field)({ description: 'The module and kind of record that asked for it - compliance.training-session, learning.direct ...' }),
81
+ tslib_1.__metadata("design:type", String)
82
+ ], Enrollment.prototype, "sourceKind", void 0);
83
+ tslib_1.__decorate([
84
+ (0, typeorm_1.Column)({ default: '' }),
85
+ (0, type_graphql_1.Field)({ description: 'The record that asked for it - empty for a manager\'s own.' }),
86
+ tslib_1.__metadata("design:type", String)
87
+ ], Enrollment.prototype, "sourceId", void 0);
88
+ tslib_1.__decorate([
89
+ (0, typeorm_1.Column)({ default: EnrollmentStatus.ASSIGNED }),
90
+ (0, type_graphql_1.Field)(type => EnrollmentStatus, { description: 'Where it stands.' }),
91
+ tslib_1.__metadata("design:type", String)
92
+ ], Enrollment.prototype, "status", void 0);
93
+ tslib_1.__decorate([
94
+ (0, typeorm_1.Column)({ nullable: true }),
95
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When the person started.' }),
96
+ tslib_1.__metadata("design:type", Date)
97
+ ], Enrollment.prototype, "startedAt", void 0);
98
+ tslib_1.__decorate([
99
+ (0, typeorm_1.Column)({ type: 'int', default: 0 }),
100
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'The seconds the server counted on its units.' }),
101
+ tslib_1.__metadata("design:type", Number)
102
+ ], Enrollment.prototype, "learnedSeconds", void 0);
103
+ tslib_1.__decorate([
104
+ (0, typeorm_1.Column)({ nullable: true }),
105
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When the person confirmed the acknowledgement.' }),
106
+ tslib_1.__metadata("design:type", Date)
107
+ ], Enrollment.prototype, "acknowledgedAt", void 0);
108
+ tslib_1.__decorate([
109
+ (0, typeorm_1.Column)({ type: 'int', nullable: true }),
110
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { nullable: true, description: 'The best score of the quiz, out of 100.' }),
111
+ tslib_1.__metadata("design:type", Number)
112
+ ], Enrollment.prototype, "score", void 0);
113
+ tslib_1.__decorate([
114
+ (0, typeorm_1.Column)({ type: 'int', default: 0 }),
115
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'How many quiz attempts were sent.' }),
116
+ tslib_1.__metadata("design:type", Number)
117
+ ], Enrollment.prototype, "attempts", void 0);
118
+ tslib_1.__decorate([
119
+ (0, typeorm_1.Column)({ nullable: true }),
120
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When it was completed.' }),
121
+ tslib_1.__metadata("design:type", Date)
122
+ ], Enrollment.prototype, "completedAt", void 0);
123
+ tslib_1.__decorate([
124
+ (0, typeorm_1.Column)({ nullable: true }),
125
+ (0, type_graphql_1.Field)({ nullable: true, description: 'The certificate number - given at completion.' }),
126
+ tslib_1.__metadata("design:type", String)
127
+ ], Enrollment.prototype, "certificateNo", void 0);
128
+ tslib_1.__decorate([
129
+ (0, typeorm_1.Column)({ nullable: true }),
130
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When it was cancelled.' }),
131
+ tslib_1.__metadata("design:type", Date)
132
+ ], Enrollment.prototype, "cancelledAt", void 0);
133
+ tslib_1.__decorate([
134
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
135
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Why it was cancelled.' }),
136
+ tslib_1.__metadata("design:type", String)
137
+ ], Enrollment.prototype, "cancelReason", void 0);
138
+ tslib_1.__decorate([
139
+ (0, typeorm_1.Column)({ nullable: true }),
140
+ (0, type_graphql_1.Field)({ nullable: true, description: 'The worklist to-do handed out for it.' }),
141
+ tslib_1.__metadata("design:type", String)
142
+ ], Enrollment.prototype, "todoInstanceId", void 0);
143
+ tslib_1.__decorate([
144
+ (0, typeorm_1.Column)({ nullable: true }),
145
+ (0, type_graphql_1.Field)({ nullable: true, description: 'The unit learned last - the course opens on it again, on any device.' }),
146
+ tslib_1.__metadata("design:type", String)
147
+ ], Enrollment.prototype, "lastUnitId", void 0);
148
+ tslib_1.__decorate([
149
+ (0, typeorm_1.CreateDateColumn)(),
150
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Creation timestamp.' }),
151
+ tslib_1.__metadata("design:type", Date)
152
+ ], Enrollment.prototype, "createdAt", void 0);
153
+ tslib_1.__decorate([
154
+ (0, typeorm_1.UpdateDateColumn)(),
155
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Last update timestamp.' }),
156
+ tslib_1.__metadata("design:type", Date)
157
+ ], Enrollment.prototype, "updatedAt", void 0);
158
+ tslib_1.__decorate([
159
+ (0, typeorm_1.DeleteDateColumn)(),
160
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Soft delete timestamp.' }),
161
+ tslib_1.__metadata("design:type", Date)
162
+ ], Enrollment.prototype, "deletedAt", void 0);
163
+ tslib_1.__decorate([
164
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
165
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who made it.' }),
166
+ tslib_1.__metadata("design:type", auth_base_1.User)
167
+ ], Enrollment.prototype, "creator", void 0);
168
+ tslib_1.__decorate([
169
+ (0, typeorm_1.RelationId)((row) => row.creator),
170
+ tslib_1.__metadata("design:type", String)
171
+ ], Enrollment.prototype, "creatorId", void 0);
172
+ tslib_1.__decorate([
173
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
174
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who changed it last.' }),
175
+ tslib_1.__metadata("design:type", auth_base_1.User)
176
+ ], Enrollment.prototype, "updater", void 0);
177
+ tslib_1.__decorate([
178
+ (0, typeorm_1.RelationId)((row) => row.updater),
179
+ tslib_1.__metadata("design:type", String)
180
+ ], Enrollment.prototype, "updaterId", void 0);
181
+ exports.Enrollment = Enrollment = tslib_1.__decorate([
182
+ (0, typeorm_1.Entity)({ name: 'learning_enrollments' }),
183
+ (0, typeorm_1.Index)('ix_learning_enrollment_0', (row) => [row.domain, row.user, row.course, row.sourceKind, row.sourceId], {
184
+ unique: true,
185
+ where: `"deleted_at" IS NULL AND "status" IN ('ASSIGNED', 'IN_PROGRESS')`
186
+ }),
187
+ (0, typeorm_1.Index)('ix_learning_enrollment_1', (row) => [row.domain, row.course, row.status]),
188
+ (0, typeorm_1.Index)('ix_learning_enrollment_2', (row) => [row.domain, row.sourceKind, row.sourceId]),
189
+ (0, type_graphql_1.ObjectType)({ description: 'An enrolment - one person to take one course by a day, for whoever asked, with the evidence of its completion.' })
190
+ ], Enrollment);
191
+ //# sourceMappingURL=enrollment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrollment.js","sourceRoot":"","sources":["../../../server/service/enrollment/enrollment.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, Int, ObjectType, registerEnumType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain } from '@things-factory/shell'\n\nimport { Course } from '../course/course'\nimport { CourseVersion } from '../course/course-version'\n\n/** Where an enrolment stands - one past its due day and not completed reads as overdue, it is not kept. */\nexport enum EnrollmentStatus {\n ASSIGNED = 'ASSIGNED',\n IN_PROGRESS = 'IN_PROGRESS',\n COMPLETED = 'COMPLETED',\n CANCELLED = 'CANCELLED'\n}\n\nregisterEnumType(EnrollmentStatus, { name: 'EnrollmentStatus', description: 'ASSIGNED - not started; IN_PROGRESS - started; COMPLETED - every condition met; CANCELLED - withdrawn by who asked for it, or by a manager.' })\n\n/** The statuses of an open enrolment - one per person, course and source. */\nexport const OPEN_ENROLLMENT_STATUSES = [EnrollmentStatus.ASSIGNED, EnrollmentStatus.IN_PROGRESS]\n\n/**\n * 수강 (ADR-0194 decisions 5, 7, 8) - one person to take one course by a day, for whoever asked (`sourceKind` and\n * `sourceId`: `compliance.training-session` and the session, `learning.direct` for a manager's own). The version is fixed when\n * the person starts. Open ones are one per person, course and source (a partial unique index). A completion keeps its\n * evidence - minutes, score, attempts, when it was confirmed, the version - and is never deleted: a wrong one is\n * cancelled with a reason.\n */\n@Entity({ name: 'learning_enrollments' })\n@Index('ix_learning_enrollment_0', (row: Enrollment) => [row.domain, row.user, row.course, row.sourceKind, row.sourceId], {\n unique: true,\n where: `\"deleted_at\" IS NULL AND \"status\" IN ('ASSIGNED', 'IN_PROGRESS')`\n})\n@Index('ix_learning_enrollment_1', (row: Enrollment) => [row.domain, row.course, row.status])\n@Index('ix_learning_enrollment_2', (row: Enrollment) => [row.domain, row.sourceKind, row.sourceId])\n@ObjectType({ description: 'An enrolment - one person to take one course by a day, for whoever asked, with the evidence of its completion.' })\nexport class Enrollment {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Enrollment id.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain.' })\n domain?: Domain\n\n @RelationId((row: Enrollment) => row.domain)\n domainId?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'Who takes it.' })\n user?: User\n\n @RelationId((row: Enrollment) => row.user)\n userId?: string\n\n @ManyToOne(type => Course)\n @Field(type => Course, { nullable: true, description: 'The course.' })\n course?: Course\n\n @RelationId((row: Enrollment) => row.course)\n courseId?: string\n\n @ManyToOne(type => CourseVersion, { nullable: true })\n @Field(type => CourseVersion, { nullable: true, description: 'The version taken - fixed when the person starts.' })\n version?: CourseVersion\n\n @RelationId((row: Enrollment) => row.version)\n versionId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'YYYY-MM-DD it is to be completed by.' })\n dueOn?: string\n\n @Column()\n @Field({ description: 'The module and kind of record that asked for it - compliance.training-session, learning.direct ...' })\n sourceKind: string\n\n @Column({ default: '' })\n @Field({ description: 'The record that asked for it - empty for a manager\\'s own.' })\n sourceId: string\n\n @Column({ default: EnrollmentStatus.ASSIGNED })\n @Field(type => EnrollmentStatus, { description: 'Where it stands.' })\n status: EnrollmentStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the person started.' })\n startedAt?: Date\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'The seconds the server counted on its units.' })\n learnedSeconds: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the person confirmed the acknowledgement.' })\n acknowledgedAt?: Date\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'The best score of the quiz, out of 100.' })\n score?: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'How many quiz attempts were sent.' })\n attempts: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When it was completed.' })\n completedAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The certificate number - given at completion.' })\n certificateNo?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When it was cancelled.' })\n cancelledAt?: Date\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Why it was cancelled.' })\n cancelReason?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The worklist to-do handed out for it.' })\n todoInstanceId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The unit learned last - the course opens on it again, on any device.' })\n lastUnitId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft delete timestamp.' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who made it.' })\n creator?: User\n\n @RelationId((row: Enrollment) => row.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who changed it last.' })\n updater?: User\n\n @RelationId((row: Enrollment) => row.updater)\n updaterId?: string\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import { Enrollment } from './enrollment';
2
+ import { QuizAttempt } from './quiz-attempt';
3
+ import { UnitProgress } from './unit-progress';
4
+ import { EnrollmentMutation } from './enrollment-mutation';
5
+ import { EnrollmentQuery } from './enrollment-query';
6
+ export * from './enrollment';
7
+ export * from './quiz-attempt';
8
+ export * from './unit-progress';
9
+ export * from './learning-outcome';
10
+ export { cancelEnrollment, DIRECT_SOURCE_KIND, enroll, learningAddressOf, withdraw } from './enrollment-service';
11
+ export type { LearningSource } from './enrollment-service';
12
+ export { LEARNING_CERTIFICATE_KIND, LEARNING_REGISTER_KIND } from './learning-documents';
13
+ export declare const entities: (typeof Enrollment | typeof QuizAttempt | typeof UnitProgress)[];
14
+ export declare const resolvers: (typeof EnrollmentMutation | typeof EnrollmentQuery)[];
15
+ export declare const subscribers: any[];
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.subscribers = exports.resolvers = exports.entities = exports.LEARNING_REGISTER_KIND = exports.LEARNING_CERTIFICATE_KIND = exports.withdraw = exports.learningAddressOf = exports.enroll = exports.DIRECT_SOURCE_KIND = exports.cancelEnrollment = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const enrollment_1 = require("./enrollment");
6
+ const quiz_attempt_1 = require("./quiz-attempt");
7
+ const unit_progress_1 = require("./unit-progress");
8
+ const enrollment_mutation_1 = require("./enrollment-mutation");
9
+ const enrollment_query_1 = require("./enrollment-query");
10
+ tslib_1.__exportStar(require("./enrollment"), exports);
11
+ tslib_1.__exportStar(require("./quiz-attempt"), exports);
12
+ tslib_1.__exportStar(require("./unit-progress"), exports);
13
+ tslib_1.__exportStar(require("./learning-outcome"), exports);
14
+ var enrollment_service_1 = require("./enrollment-service");
15
+ Object.defineProperty(exports, "cancelEnrollment", { enumerable: true, get: function () { return enrollment_service_1.cancelEnrollment; } });
16
+ Object.defineProperty(exports, "DIRECT_SOURCE_KIND", { enumerable: true, get: function () { return enrollment_service_1.DIRECT_SOURCE_KIND; } });
17
+ Object.defineProperty(exports, "enroll", { enumerable: true, get: function () { return enrollment_service_1.enroll; } });
18
+ Object.defineProperty(exports, "learningAddressOf", { enumerable: true, get: function () { return enrollment_service_1.learningAddressOf; } });
19
+ Object.defineProperty(exports, "withdraw", { enumerable: true, get: function () { return enrollment_service_1.withdraw; } });
20
+ var learning_documents_1 = require("./learning-documents");
21
+ Object.defineProperty(exports, "LEARNING_CERTIFICATE_KIND", { enumerable: true, get: function () { return learning_documents_1.LEARNING_CERTIFICATE_KIND; } });
22
+ Object.defineProperty(exports, "LEARNING_REGISTER_KIND", { enumerable: true, get: function () { return learning_documents_1.LEARNING_REGISTER_KIND; } });
23
+ exports.entities = [enrollment_1.Enrollment, unit_progress_1.UnitProgress, quiz_attempt_1.QuizAttempt];
24
+ exports.resolvers = [enrollment_query_1.EnrollmentQuery, enrollment_mutation_1.EnrollmentMutation];
25
+ exports.subscribers = [];
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/enrollment/index.ts"],"names":[],"mappings":";;;;AAAA,6CAAyC;AACzC,iDAA4C;AAC5C,mDAA8C;AAC9C,+DAA0D;AAC1D,yDAAoD;AAEpD,uDAA4B;AAC5B,yDAA8B;AAC9B,0DAA+B;AAC/B,6DAAkC;AAClC,2DAAgH;AAAvG,sHAAA,gBAAgB,OAAA;AAAE,wHAAA,kBAAkB,OAAA;AAAE,4GAAA,MAAM,OAAA;AAAE,uHAAA,iBAAiB,OAAA;AAAE,8GAAA,QAAQ,OAAA;AAElF,2DAAwF;AAA/E,+HAAA,yBAAyB,OAAA;AAAE,4HAAA,sBAAsB,OAAA;AAE7C,QAAA,QAAQ,GAAG,CAAC,uBAAU,EAAE,4BAAY,EAAE,0BAAW,CAAC,CAAA;AAClD,QAAA,SAAS,GAAG,CAAC,kCAAe,EAAE,wCAAkB,CAAC,CAAA;AACjD,QAAA,WAAW,GAAG,EAAE,CAAA","sourcesContent":["import { Enrollment } from './enrollment'\nimport { QuizAttempt } from './quiz-attempt'\nimport { UnitProgress } from './unit-progress'\nimport { EnrollmentMutation } from './enrollment-mutation'\nimport { EnrollmentQuery } from './enrollment-query'\n\nexport * from './enrollment'\nexport * from './quiz-attempt'\nexport * from './unit-progress'\nexport * from './learning-outcome'\nexport { cancelEnrollment, DIRECT_SOURCE_KIND, enroll, learningAddressOf, withdraw } from './enrollment-service'\nexport type { LearningSource } from './enrollment-service'\nexport { LEARNING_CERTIFICATE_KIND, LEARNING_REGISTER_KIND } from './learning-documents'\n\nexport const entities = [Enrollment, UnitProgress, QuizAttempt]\nexport const resolvers = [EnrollmentQuery, EnrollmentMutation]\nexport const subscribers = []\n"]}
@@ -0,0 +1,45 @@
1
+ import { ListParam } from '@things-factory/shell';
2
+ export interface ReadableEnrollment {
3
+ id: string;
4
+ learner: string;
5
+ departmentName: string | null;
6
+ course: string;
7
+ state: string;
8
+ dueOn: string | null;
9
+ daysLeft: number | null;
10
+ startedAt: Date | null;
11
+ completedAt: Date | null;
12
+ unitsDone: number;
13
+ units: number;
14
+ }
15
+ /**
16
+ * A page of the enrolments the person may read, as rows the assistant lists - cancelled ones left out. Conditions, search
17
+ * and page by the list rule of the status screen (`enrollmentPage`).
18
+ */
19
+ export declare function readableEnrollments(params: ListParam, context: any): Promise<{
20
+ items: ReadableEnrollment[];
21
+ total: number;
22
+ }>;
23
+ export interface CourseContent {
24
+ course: string;
25
+ version: number;
26
+ units: {
27
+ seq: number;
28
+ kind: string;
29
+ name: string;
30
+ text: string | null;
31
+ }[];
32
+ }
33
+ /**
34
+ * The units of one version as the assistant reads them. With an enrolment - the person's own - its version and nothing
35
+ * else, refused while a quiz attempt of it is open: the assistant does not answer the quiz. With a version - a manager's.
36
+ */
37
+ export declare function courseContent(args: {
38
+ enrollmentId?: string | null;
39
+ versionId?: string | null;
40
+ }, context: any): Promise<CourseContent>;
41
+ /** "a\n*b\nc" - one choice a line, the right ones starting with `*` - as the editor's choices. */
42
+ export declare function choicesOfText(text: string): {
43
+ text: string;
44
+ correct: boolean;
45
+ }[];
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readableEnrollments = readableEnrollments;
4
+ exports.courseContent = courseContent;
5
+ exports.choicesOfText = choicesOfText;
6
+ /*
7
+ * What the assistant reads and enters of learning (ADR-0194 decision 12), as the person asking:
8
+ *
9
+ * - `learning.enrollments` - the enrolments the person may read: a manager every one, a department head their people's
10
+ * (status only), anyone else their own - 「기한이 일주일 남았는데 시작하지 않은 사람」.
11
+ * - `learning.course-content` - the units of one version, to answer a question on a course or to draft its questions:
12
+ * a learner the version of their own enrolment and nothing else, never while a quiz attempt of theirs is open; a manager
13
+ * any version.
14
+ * - `learning.question-draft` - questions drafted from the units, entered into a draft version only, each marked drafted
15
+ * until a manager looks it over and saves it; a version with one is not published.
16
+ */
17
+ const typeorm_1 = require("typeorm");
18
+ const auth_base_1 = require("@things-factory/auth-base");
19
+ const shell_1 = require("@things-factory/shell");
20
+ const course_1 = require("../course/course");
21
+ const course_version_1 = require("../course/course-version");
22
+ const course_service_1 = require("../course/course-service");
23
+ const enrollment_1 = require("./enrollment");
24
+ const enrollment_service_1 = require("./enrollment-service");
25
+ const enrollment_status_1 = require("./enrollment-status");
26
+ const quiz_attempt_1 = require("./quiz-attempt");
27
+ const daysBetween = (from, to) => Math.round((Date.parse(`${to}T00:00:00Z`) - Date.parse(`${from}T00:00:00Z`)) / 86_400_000);
28
+ /**
29
+ * A page of the enrolments the person may read, as rows the assistant lists - cancelled ones left out. Conditions, search
30
+ * and page by the list rule of the status screen (`enrollmentPage`).
31
+ */
32
+ async function readableEnrollments(params, context) {
33
+ const { domain } = context.state;
34
+ const { rows, total } = await (0, enrollment_status_1.enrollmentPage)(params, await (0, enrollment_status_1.reachOf)(context), context, builder => builder.andWhere('E.status <> :learningAiCancelled', { learningAiCancelled: enrollment_1.EnrollmentStatus.CANCELLED }));
35
+ const today = (0, enrollment_service_1.todayIn)(domain);
36
+ return {
37
+ total,
38
+ items: rows.map(row => ({
39
+ id: row.enrollment.id,
40
+ learner: row.user?.name ?? '',
41
+ departmentName: row.departmentName,
42
+ course: row.course?.name ?? '',
43
+ state: row.state,
44
+ dueOn: row.enrollment.dueOn ?? null,
45
+ daysLeft: row.enrollment.dueOn ? daysBetween(today, row.enrollment.dueOn) : null,
46
+ startedAt: row.enrollment.startedAt ?? null,
47
+ completedAt: row.enrollment.completedAt ?? null,
48
+ unitsDone: row.unitsDone,
49
+ units: row.units
50
+ }))
51
+ };
52
+ }
53
+ /**
54
+ * The units of one version as the assistant reads them. With an enrolment - the person's own - its version and nothing
55
+ * else, refused while a quiz attempt of it is open: the assistant does not answer the quiz. With a version - a manager's.
56
+ */
57
+ async function courseContent(args, context) {
58
+ const { domain } = context.state;
59
+ const tx = (0, course_service_1.learningManagerOf)(context);
60
+ let version;
61
+ if (args.enrollmentId) {
62
+ const enrollment = await (0, enrollment_service_1.myEnrollmentOf)(context, args.enrollmentId, tx);
63
+ const open = await tx.getRepository(quiz_attempt_1.QuizAttempt).count({ where: { enrollment: { id: enrollment.id }, submittedAt: (0, typeorm_1.IsNull)() } });
64
+ if (open && enrollment_1.OPEN_ENROLLMENT_STATUSES.includes(enrollment.status))
65
+ throw new shell_1.Refusal('learning-quiz-in-progress', {}, 'a quiz attempt is open - the course is not explained until it is sent');
66
+ version = await (0, enrollment_service_1.shownVersionOf)(tx, domain, enrollment);
67
+ }
68
+ else if (args.versionId) {
69
+ if (!(await (0, auth_base_1.requestHolds)(context, 'course', 'query')))
70
+ throw new shell_1.Refusal('learning-not-found', {}, 'the record was not found. reload and try again.');
71
+ version = await tx.getRepository(course_version_1.CourseVersion).findOne({ where: { id: args.versionId, domain: { id: domain.id } }, withDeleted: true });
72
+ }
73
+ else
74
+ throw new shell_1.Refusal('learning-content-what', {}, 'name the enrolment or the version');
75
+ if (!version)
76
+ throw new shell_1.Refusal('learning-not-found', {}, 'the record was not found. reload and try again.');
77
+ const course = await tx.getRepository(course_1.Course).findOneBy({ id: version.courseId });
78
+ const units = await (0, course_service_1.unitsOf)(tx, version.id);
79
+ return {
80
+ course: course?.name ?? '',
81
+ version: version.number,
82
+ units: units.map(unit => ({ seq: unit.seq, kind: unit.kind, name: unit.name, text: unit.kind === 'MARKDOWN' ? unit.body ?? null : unit.kind === 'LINK' ? unit.url ?? null : null }))
83
+ };
84
+ }
85
+ /** "a\n*b\nc" - one choice a line, the right ones starting with `*` - as the editor's choices. */
86
+ function choicesOfText(text) {
87
+ return String(text ?? '')
88
+ .split(/\r?\n/)
89
+ .map(line => line.trim())
90
+ .filter(Boolean)
91
+ .map(line => ({ text: line.replace(/^\*\s*/, ''), correct: line.startsWith('*') }));
92
+ }
93
+ //# sourceMappingURL=learning-ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-ai.js","sourceRoot":"","sources":["../../../server/service/enrollment/learning-ai.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the assistant reads and enters of learning (ADR-0194 decision 12), as the person asking:\n *\n * - `learning.enrollments` - the enrolments the person may read: a manager every one, a department head their people's\n * (status only), anyone else their own - 「기한이 일주일 남았는데 시작하지 않은 사람」.\n * - `learning.course-content` - the units of one version, to answer a question on a course or to draft its questions:\n * a learner the version of their own enrolment and nothing else, never while a quiz attempt of theirs is open; a manager\n * any version.\n * - `learning.question-draft` - questions drafted from the units, entered into a draft version only, each marked drafted\n * until a manager looks it over and saves it; a version with one is not published.\n */\nimport { EntityManager, IsNull } from 'typeorm'\n\nimport { requestHolds } from '@things-factory/auth-base'\nimport { ListParam, Refusal } from '@things-factory/shell'\n\nimport { Course } from '../course/course'\nimport { CourseUnit } from '../course/course-unit'\nimport { CourseVersion } from '../course/course-version'\nimport { learningManagerOf, unitsOf } from '../course/course-service'\nimport { Enrollment, EnrollmentStatus, OPEN_ENROLLMENT_STATUSES } from './enrollment'\nimport { myEnrollmentOf, shownVersionOf, todayIn } from './enrollment-service'\nimport { enrollmentPage, reachOf } from './enrollment-status'\nimport { QuizAttempt } from './quiz-attempt'\n\nexport interface ReadableEnrollment {\n id: string\n learner: string\n departmentName: string | null\n course: string\n state: string\n dueOn: string | null\n daysLeft: number | null\n startedAt: Date | null\n completedAt: Date | null\n unitsDone: number\n units: number\n}\n\nconst daysBetween = (from: string, to: string) => Math.round((Date.parse(`${to}T00:00:00Z`) - Date.parse(`${from}T00:00:00Z`)) / 86_400_000)\n\n/**\n * A page of the enrolments the person may read, as rows the assistant lists - cancelled ones left out. Conditions, search\n * and page by the list rule of the status screen (`enrollmentPage`).\n */\nexport async function readableEnrollments(params: ListParam, context: any): Promise<{ items: ReadableEnrollment[]; total: number }> {\n const { domain } = context.state\n const { rows, total } = await enrollmentPage(params, await reachOf(context), context, builder => builder.andWhere('E.status <> :learningAiCancelled', { learningAiCancelled: EnrollmentStatus.CANCELLED }))\n const today = todayIn(domain)\n return {\n total,\n items: rows.map(row => ({\n id: row.enrollment.id,\n learner: row.user?.name ?? '',\n departmentName: row.departmentName,\n course: row.course?.name ?? '',\n state: row.state,\n dueOn: row.enrollment.dueOn ?? null,\n daysLeft: row.enrollment.dueOn ? daysBetween(today, row.enrollment.dueOn) : null,\n startedAt: row.enrollment.startedAt ?? null,\n completedAt: row.enrollment.completedAt ?? null,\n unitsDone: row.unitsDone,\n units: row.units\n }))\n }\n}\n\nexport interface CourseContent {\n course: string\n version: number\n units: { seq: number; kind: string; name: string; text: string | null }[]\n}\n\n/**\n * The units of one version as the assistant reads them. With an enrolment - the person's own - its version and nothing\n * else, refused while a quiz attempt of it is open: the assistant does not answer the quiz. With a version - a manager's.\n */\nexport async function courseContent(args: { enrollmentId?: string | null; versionId?: string | null }, context: any): Promise<CourseContent> {\n const { domain } = context.state\n const tx: EntityManager = learningManagerOf(context)\n let version: CourseVersion | null\n if (args.enrollmentId) {\n const enrollment = await myEnrollmentOf(context, args.enrollmentId, tx)\n const open = await tx.getRepository(QuizAttempt).count({ where: { enrollment: { id: enrollment.id }, submittedAt: IsNull() } as any })\n if (open && (OPEN_ENROLLMENT_STATUSES as string[]).includes(enrollment.status))\n throw new Refusal('learning-quiz-in-progress', {}, 'a quiz attempt is open - the course is not explained until it is sent')\n version = await shownVersionOf(tx, domain, enrollment)\n } else if (args.versionId) {\n if (!(await requestHolds(context, 'course', 'query'))) throw new Refusal('learning-not-found', {}, 'the record was not found. reload and try again.')\n version = await tx.getRepository(CourseVersion).findOne({ where: { id: args.versionId, domain: { id: domain.id } } as any, withDeleted: true })\n } else throw new Refusal('learning-content-what', {}, 'name the enrolment or the version')\n if (!version) throw new Refusal('learning-not-found', {}, 'the record was not found. reload and try again.')\n const course = await tx.getRepository(Course).findOneBy({ id: version.courseId! })\n const units: CourseUnit[] = await unitsOf(tx, version.id)\n return {\n course: course?.name ?? '',\n version: version.number,\n units: units.map(unit => ({ seq: unit.seq, kind: unit.kind, name: unit.name, text: unit.kind === 'MARKDOWN' ? unit.body ?? null : unit.kind === 'LINK' ? unit.url ?? null : null }))\n }\n}\n\n/** \"a\\n*b\\nc\" - one choice a line, the right ones starting with `*` - as the editor's choices. */\nexport function choicesOfText(text: string): { text: string; correct: boolean }[] {\n return String(text ?? '')\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(Boolean)\n .map(line => ({ text: line.replace(/^\\*\\s*/, ''), correct: line.startsWith('*') }))\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export declare const LEARNING_CERTIFICATE_KIND = "learning.certificate";
2
+ export declare const LEARNING_REGISTER_KIND = "learning.completion-register";
3
+ /** The certificate's template in code - a domain's own `PDFTemplate` of the kind prints in its place. */
4
+ export declare const CERTIFICATE_TEMPLATE = "<!doctype html><html lang=\"ko\"><head><meta charset=\"utf-8\"><style>\n@page { size: A4; margin: 0 }\nbody { margin: 0; font-family: \"Apple SD Gothic Neo\", \"Malgun Gothic\", \"Noto Sans KR\", sans-serif; color: #222 }\n.page { position: relative; box-sizing: border-box; width: 210mm; min-height: 297mm; padding: 30mm 24mm }\n.number { position: absolute; top: 16mm; left: 24mm; font-size: 9.5pt; color: #666 }\nh1 { margin: 6mm 0 16mm; text-align: center; font-size: 26pt; letter-spacing: 12pt }\ntable { width: 100%; border-collapse: collapse; font-size: 11.5pt }\nth, td { border: 1px solid #444; padding: 3.2mm 4mm; text-align: left; vertical-align: middle }\nth { background: #f2f2f2; font-weight: 600; text-align: center }\n.statement { margin: 22mm 0 0; text-align: center; font-size: 13pt; line-height: 2 }\n.date { margin-top: 18mm; text-align: center; font-size: 13pt; letter-spacing: 1pt }\n.issuer { position: relative; margin: 20mm auto 0; width: max-content; font-size: 14pt; line-height: 2; text-align: left; padding-right: 22mm }\n.issuer img { position: absolute; right: 0; top: 2mm; width: 22mm; opacity: .9 }\nth { width: 32mm }\n</style></head><body><div class=\"page\">\n<div class=\"number\">\uBC1C\uAE09\uBC88\uD638 {{issue.number}}</div>\n<h1>\uC218\uB8CC\uC99D</h1>\n<table>\n<tr><th>\uC131\uBA85</th><td>{{learner.name}}</td></tr>\n<tr><th>\uACFC\uC815</th><td>{{course.name}} (\uAC1C\uC815\uBCF8 {{course.version}})</td></tr>\n<tr><th>\uC774\uC218\uC77C</th><td>{{completion.completedOn}}</td></tr>\n<tr><th>\uD559\uC2B5 \uC2DC\uAC04</th><td>{{completion.minutes}}\uBD84</td></tr>\n{{#if completion.score}}<tr><th>\uD3C9\uAC00 \uC810\uC218</th><td>{{completion.score}}\uC810</td></tr>{{/if}}\n<tr><th>\uC218\uB8CC \uBC88\uD638</th><td>{{completion.certificateNo}}</td></tr>\n</table>\n<p class=\"statement\">\uC704 \uC0AC\uB78C\uC740 \uC704 \uACFC\uC815\uC744 \uC774\uC218\uD558\uC600\uC74C\uC744 \uC99D\uBA85\uD569\uB2C8\uB2E4.</p>\n<div class=\"date\">{{issue.issuedOn}}</div>\n<div class=\"issuer\">\n<div>\uC0C1\uD638 : {{company.name}}</div>\n{{#if company.address}}<div>\uC8FC\uC18C : {{company.address}}</div>{{/if}}\n<div>\uB300\uD45C\uC774\uC0AC : {{company.representative}}</div>\n{{#if company.seal}}<img src=\"{{company.seal}}\" alt=\"\">{{/if}}\n</div>\n</div></body></html>";
5
+ /** The completion register's template - one row per completion. */
6
+ export declare const REGISTER_TEMPLATE = "<!doctype html><html lang=\"ko\"><head><meta charset=\"utf-8\"><style>\n@page { size: A4; margin: 0 }\nbody { margin: 0; font-family: \"Apple SD Gothic Neo\", \"Malgun Gothic\", \"Noto Sans KR\", sans-serif; color: #222 }\n.page { position: relative; box-sizing: border-box; width: 210mm; min-height: 297mm; padding: 30mm 24mm }\n.number { position: absolute; top: 16mm; left: 24mm; font-size: 9.5pt; color: #666 }\nh1 { margin: 6mm 0 16mm; text-align: center; font-size: 26pt; letter-spacing: 12pt }\ntable { width: 100%; border-collapse: collapse; font-size: 11.5pt }\nth, td { border: 1px solid #444; padding: 3.2mm 4mm; text-align: left; vertical-align: middle }\nth { background: #f2f2f2; font-weight: 600; text-align: center }\n.statement { margin: 22mm 0 0; text-align: center; font-size: 13pt; line-height: 2 }\n.date { margin-top: 18mm; text-align: center; font-size: 13pt; letter-spacing: 1pt }\n.issuer { position: relative; margin: 20mm auto 0; width: max-content; font-size: 14pt; line-height: 2; text-align: left; padding-right: 22mm }\n.issuer img { position: absolute; right: 0; top: 2mm; width: 22mm; opacity: .9 }\n.page { padding: 24mm 16mm }\nh1 { font-size: 20pt; letter-spacing: 4pt; margin-bottom: 8mm }\n.meta { margin-bottom: 6mm; font-size: 10.5pt }\ntable { font-size: 9.5pt }\nth, td { padding: 2mm 2.4mm }\n</style></head><body><div class=\"page\">\n<div class=\"number\">\uBC1C\uAE09\uBC88\uD638 {{issue.number}}</div>\n<h1>\uC774\uC218 \uB300\uC7A5</h1>\n<div class=\"meta\">\uACFC\uC815 : {{course.name}} \u00B7 \uAE30\uC900\uC77C : {{issue.asOf}} \u00B7 \uC774\uC218\uC790 {{count}}\uBA85</div>\n<table>\n<tr><th>\uBC88\uD638</th><th>\uC131\uBA85</th><th>\uBD80\uC11C</th><th>\uAC1C\uC815\uBCF8</th><th>\uC774\uC218\uC77C</th><th>\uD559\uC2B5 \uC2DC\uAC04(\uBD84)</th><th>\uC810\uC218</th><th>\uC218\uB8CC \uBC88\uD638</th></tr>\n{{#each rows}}<tr><td>{{this.no}}</td><td>{{this.name}}</td><td>{{this.department}}</td><td>{{this.version}}</td><td>{{this.completedOn}}</td><td>{{this.minutes}}</td><td>{{this.score}}</td><td>{{this.certificateNo}}</td></tr>{{/each}}\n</table>\n<div class=\"date\">{{issue.issuedOn}}</div>\n<div class=\"issuer\">\n<div>\uC0C1\uD638 : {{company.name}}</div>\n{{#if company.address}}<div>\uC8FC\uC18C : {{company.address}}</div>{{/if}}\n<div>\uB300\uD45C\uC774\uC0AC : {{company.representative}}</div>\n{{#if company.seal}}<img src=\"{{company.seal}}\" alt=\"\">{{/if}}\n</div>\n</div></body></html>";
7
+ export declare function registerLearningDocuments(): void;