@falkenslab/moodle-driver 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/areas/activities/build.d.ts +47 -10
- package/dist/areas/activities/build.js +157 -24
- package/dist/areas/activities/build.js.map +1 -1
- package/dist/areas/activities/conditions.d.ts +77 -0
- package/dist/areas/activities/conditions.js +216 -0
- package/dist/areas/activities/conditions.js.map +1 -0
- package/dist/areas/activities/content.d.ts +3 -0
- package/dist/areas/activities/content.js +1 -0
- package/dist/areas/activities/content.js.map +1 -1
- package/dist/areas/assignments/grader.d.ts +32 -0
- package/dist/areas/assignments/grader.js +66 -2
- package/dist/areas/assignments/grader.js.map +1 -1
- package/dist/areas/assignments/grading.d.ts +69 -6
- package/dist/areas/assignments/grading.js +173 -13
- package/dist/areas/assignments/grading.js.map +1 -1
- package/dist/areas/assignments/student.d.ts +14 -0
- package/dist/areas/assignments/student.js +43 -2
- package/dist/areas/assignments/student.js.map +1 -1
- package/dist/areas/backup/backup.d.ts +86 -0
- package/dist/areas/backup/backup.js +368 -0
- package/dist/areas/backup/backup.js.map +1 -0
- package/dist/areas/calendar/calendar.d.ts +27 -0
- package/dist/areas/calendar/calendar.js +115 -9
- package/dist/areas/calendar/calendar.js.map +1 -1
- package/dist/areas/completion/completion.d.ts +3 -0
- package/dist/areas/completion/completion.js.map +1 -1
- package/dist/areas/courses/list.d.ts +2 -0
- package/dist/areas/courses/list.js.map +1 -1
- package/dist/areas/courses/reset.d.ts +51 -0
- package/dist/areas/courses/reset.js +123 -0
- package/dist/areas/courses/reset.js.map +1 -0
- package/dist/areas/courses/state.d.ts +17 -0
- package/dist/areas/courses/state.js +37 -6
- package/dist/areas/courses/state.js.map +1 -1
- package/dist/areas/courses/structure.d.ts +14 -2
- package/dist/areas/courses/structure.js +11 -5
- package/dist/areas/courses/structure.js.map +1 -1
- package/dist/areas/forums/discussions.d.ts +8 -0
- package/dist/areas/forums/discussions.js +10 -0
- package/dist/areas/forums/discussions.js.map +1 -1
- package/dist/areas/forums/grading.d.ts +49 -0
- package/dist/areas/forums/grading.js +125 -0
- package/dist/areas/forums/grading.js.map +1 -0
- package/dist/areas/forums/posts.d.ts +37 -0
- package/dist/areas/forums/posts.js +141 -6
- package/dist/areas/forums/posts.js.map +1 -1
- package/dist/areas/grades/export.d.ts +38 -0
- package/dist/areas/grades/export.js +88 -0
- package/dist/areas/grades/export.js.map +1 -0
- package/dist/areas/grades/gradebook.d.ts +50 -0
- package/dist/areas/grades/gradebook.js +120 -0
- package/dist/areas/grades/gradebook.js.map +1 -1
- package/dist/areas/grades/singleview.d.ts +39 -0
- package/dist/areas/grades/singleview.js +186 -0
- package/dist/areas/grades/singleview.js.map +1 -0
- package/dist/areas/h5p/h5p.d.ts +2 -0
- package/dist/areas/h5p/h5p.js +12 -7
- package/dist/areas/h5p/h5p.js.map +1 -1
- package/dist/areas/lessons/lessons.d.ts +1 -0
- package/dist/areas/lessons/lessons.js.map +1 -1
- package/dist/areas/messages/messages.d.ts +36 -1
- package/dist/areas/messages/messages.js +60 -4
- package/dist/areas/messages/messages.js.map +1 -1
- package/dist/areas/participants/enrolments.d.ts +60 -0
- package/dist/areas/participants/enrolments.js +218 -0
- package/dist/areas/participants/enrolments.js.map +1 -0
- package/dist/areas/participants/groups.d.ts +75 -0
- package/dist/areas/participants/groups.js +201 -0
- package/dist/areas/participants/groups.js.map +1 -0
- package/dist/areas/participants/methods.d.ts +56 -0
- package/dist/areas/participants/methods.js +154 -0
- package/dist/areas/participants/methods.js.map +1 -0
- package/dist/areas/participants/participants.d.ts +11 -0
- package/dist/areas/participants/participants.js +24 -19
- package/dist/areas/participants/participants.js.map +1 -1
- package/dist/areas/questions/banks.d.ts +36 -1
- package/dist/areas/questions/banks.js +140 -17
- package/dist/areas/questions/banks.js.map +1 -1
- package/dist/areas/quizzes/attempts.d.ts +2 -0
- package/dist/areas/quizzes/attempts.js +9 -0
- package/dist/areas/quizzes/attempts.js.map +1 -1
- package/dist/areas/quizzes/grading.d.ts +50 -0
- package/dist/areas/quizzes/grading.js +131 -0
- package/dist/areas/quizzes/grading.js.map +1 -0
- package/dist/areas/quizzes/results.d.ts +3 -0
- package/dist/areas/quizzes/results.js +2 -1
- package/dist/areas/quizzes/results.js.map +1 -1
- package/dist/areas/quizzes/structure.d.ts +65 -9
- package/dist/areas/quizzes/structure.js +222 -23
- package/dist/areas/quizzes/structure.js.map +1 -1
- package/dist/areas/ratings/ratings.d.ts +26 -0
- package/dist/areas/ratings/ratings.js +108 -0
- package/dist/areas/ratings/ratings.js.map +1 -0
- package/dist/areas/reports/dates.d.ts +18 -0
- package/dist/areas/reports/dates.js +134 -0
- package/dist/areas/reports/dates.js.map +1 -0
- package/dist/areas/reports/reports.d.ts +143 -0
- package/dist/areas/reports/reports.js +267 -0
- package/dist/areas/reports/reports.js.map +1 -0
- package/dist/areas/scorm/scorm.d.ts +1 -0
- package/dist/areas/scorm/scorm.js.map +1 -1
- package/dist/areas/site/users.d.ts +7 -1
- package/dist/areas/site/users.js +9 -2
- package/dist/areas/site/users.js.map +1 -1
- package/dist/areas/surveys/choice.d.ts +2 -0
- package/dist/areas/surveys/choice.js +6 -3
- package/dist/areas/surveys/choice.js.map +1 -1
- package/dist/areas/surveys/surveys.d.ts +3 -0
- package/dist/areas/surveys/surveys.js +1 -0
- package/dist/areas/surveys/surveys.js.map +1 -1
- package/dist/areas/workshops/workshops.d.ts +133 -0
- package/dist/areas/workshops/workshops.js +335 -0
- package/dist/areas/workshops/workshops.js.map +1 -0
- package/dist/browser/background.d.ts +43 -0
- package/dist/browser/background.js +164 -0
- package/dist/browser/background.js.map +1 -0
- package/dist/browser/host.d.ts +30 -0
- package/dist/browser/host.js +373 -0
- package/dist/browser/host.js.map +1 -0
- package/dist/browser/manager.d.ts +9 -0
- package/dist/browser/manager.js +8 -0
- package/dist/browser/manager.js.map +1 -1
- package/dist/categories.d.ts +1 -0
- package/dist/categories.js +67 -0
- package/dist/categories.js.map +1 -1
- package/dist/cli/args.d.ts +8 -0
- package/dist/cli/args.js +49 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/background.d.ts +23 -0
- package/dist/cli/background.js +128 -0
- package/dist/cli/background.js.map +1 -0
- package/dist/cli/command.d.ts +66 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/commands.generated.js +2636 -578
- package/dist/cli/commands.generated.js.map +1 -1
- package/dist/cli/config.d.ts +2 -0
- package/dist/cli/config.js +2 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/main.js +30 -10
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/run.d.ts +3 -14
- package/dist/cli/run.js +9 -185
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/shell.d.ts +9 -0
- package/dist/cli/shell.js +233 -0
- package/dist/cli/shell.js.map +1 -0
- package/dist/client.d.ts +71 -8
- package/dist/client.js +75 -8
- package/dist/client.js.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/files.d.ts +5 -0
- package/dist/core/files.js +7 -3
- package/dist/core/files.js.map +1 -1
- package/dist/core/forms.d.ts +33 -3
- package/dist/core/forms.js +105 -8
- package/dist/core/forms.js.map +1 -1
- package/dist/core/http.d.ts +7 -0
- package/dist/core/http.js +28 -7
- package/dist/core/http.js.map +1 -1
- package/dist/core/login.d.ts +3 -0
- package/dist/core/login.js +2 -0
- package/dist/core/login.js.map +1 -1
- package/dist/core/session.d.ts +12 -1
- package/dist/core/session.js +12 -1
- package/dist/core/session.js.map +1 -1
- package/dist/index.d.ts +35 -11
- package/dist/index.js +32 -12
- package/dist/index.js.map +1 -1
- package/dist/internals.d.ts +9 -1
- package/dist/internals.js +9 -4
- package/dist/internals.js.map +1 -1
- package/dist/options.d.ts +2 -0
- package/dist/options.js.map +1 -1
- package/dist/testing/fakeMoodle.d.ts +9 -2
- package/dist/testing/fakeMoodle.js +5 -3
- package/dist/testing/fakeMoodle.js.map +1 -1
- package/dist/testing/index.d.ts +7 -0
- package/dist/testing/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -16,6 +16,7 @@ export interface LessonField {
|
|
|
16
16
|
label: string;
|
|
17
17
|
}[];
|
|
18
18
|
}
|
|
19
|
+
/** The lesson page the person is on, as `lessonPage` and `answerLessonPage` read it. */
|
|
19
20
|
export interface LessonPage {
|
|
20
21
|
/** What the page is: content with buttons, a question, the feedback after an answer, or the lesson's end. */
|
|
21
22
|
kind: "content" | "question" | "feedback" | "end";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lessons.js","sourceRoot":"","sources":["../../../src/areas/lessons/lessons.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,kEAAkE;AAClE,MAAM,OAAO,WAAY,SAAQ,WAAW;IACjC,IAAI,GAAG,aAAa,CAAC;IAC9B,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3B,CAAC;CACF;
|
|
1
|
+
{"version":3,"file":"lessons.js","sourceRoot":"","sources":["../../../src/areas/lessons/lessons.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,kEAAkE;AAClE,MAAM,OAAO,WAAY,SAAQ,WAAW;IACjC,IAAI,GAAG,aAAa,CAAC;IAC9B,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3B,CAAC;CACF;AA2BD,+DAA+D;AAC/D,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,OAAO,MAAM,CACX,IAAI,EACJ,GAAG,EAAE;QAeH,MAAM,GAAG,GAAI,UAA0C,CAAC,QAAQ,CAAC;QACjE,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,4BAA4B,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAClG,MAAM,IAAI,GAAG,CAAC,EAAyB,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5H,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,EAAE,aAAa,CAAC,gDAAgD,CAAC,CAAC;QACvF,MAAM,QAAQ,GAAG,CAAC,IAA2B,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,sBAAsB,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC;QAC1I,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,GAAkB,EAAE,CAAC;YACjC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,4CAA4C,CAAC,CAAC,EAAE,CAAC;gBACxG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBACrD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC;gBACxD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC3B,IAAI,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;oBACtD,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,KAAK,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;wBAC1D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACrB,CAAC;oBACD,KAAK,CAAC,OAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;gBAC3E,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;oBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;qBAClH,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBACpC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC5K,CAAC;;oBAAM,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACtF,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAgB,CAAC;QAC9J,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,iEAAiE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5H,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC5B,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;gBAC5C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;aACpK,CAAC;QAClB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,EAAE,aAAa,CAAC,sCAAsC,CAAC,CAAC;QACzE,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,QAAQ,GAAG,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACtJ,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC;gBACtB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC/C,QAAQ,EAAE,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;aAC7H,CAAC;QAClB,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAgB,CAAC;IACtF,CAAC,EACD,IAAI,CACL,CAAC;AACJ,CAAC;AAED,+GAA+G;AAC/G,KAAK,UAAU,UAAU,CAAC,OAAuB,EAAE,OAAe,EAAE,UAAkB;IACpF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,0BAA0B,UAAU,EAAE,CAAC,CAAC;IAC1F,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,WAAW,CAAC,YAAY,UAAU,oGAAoG,CAAC,CAAC;QACpJ,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC;QACzE,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAE,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACjI,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAuB,EAAE,OAAe,EAAE,UAAkB;IAC3F,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC;QACH,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAuB,EACvB,OAAe,EACf,UAAkB,EAClB,MAAwE,EACxE,EAAE,KAAK,GAAG,WAAW,EAAE,UAAU,KAA+E,EAAE;IAElH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3C,2EAA2E;QAC3E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC;QACtH,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACxG,MAAM,IAAI,WAAW,CAAC,oCAAoC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QACtJ,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YACrG,MAAM,IAAI,WAAW,CAAC,yEAAyE,CAAC,CAAC;QACnG,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC1D,MAAM,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,uDAAuD,CAAC,CAAC,CAAC,sDAAsD,CAAC,CAAC;QACnK,CAAC;QACD,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9J,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,mHAAmH,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACvO,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,gDAAgD,CAAC;YAC9D,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,SAAU,EAAE,IAAI,CAAC,CAAC;YAC/C,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,wBAAwB,CAAC,CAAC,CAAC,CAAC;QAC9H,CAAC;QACD,IAAI,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,QAAgC,CAAC;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,2HAA2H,CAAC,CAAC,CAAC,CAAC;YACxN,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,uBAAuB,UAAU,iBAAiB,OAAO,CAAC,KAAK,CAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,mBAAmB,UAAU,cAAc,CAAC;QACvK,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACpE,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
|
|
@@ -5,6 +5,7 @@ export declare class MessageError extends MoodleError {
|
|
|
5
5
|
name: string;
|
|
6
6
|
constructor(message: string);
|
|
7
7
|
}
|
|
8
|
+
/** A notification the site sent the person, as `notifications` lists it. */
|
|
8
9
|
export interface Notification {
|
|
9
10
|
id: number;
|
|
10
11
|
subject: string;
|
|
@@ -28,15 +29,19 @@ export declare function notifications(context: BrowserContext, siteUrl: string,
|
|
|
28
29
|
export declare function markNotificationsRead(context: BrowserContext, siteUrl: string): Promise<{
|
|
29
30
|
changed: string;
|
|
30
31
|
}>;
|
|
32
|
+
/** One of the person's conversations, as `conversations` lists it, with its last message. */
|
|
31
33
|
export interface ConversationSummary {
|
|
32
34
|
id: number;
|
|
35
|
+
/** With one other person, a course group's, or the person's own (notes to self). */
|
|
33
36
|
type: "private" | "group" | "self";
|
|
34
37
|
/** A group conversation's name (its course group). */
|
|
35
38
|
name?: string;
|
|
39
|
+
/** Everyone in it but the person. */
|
|
36
40
|
members: {
|
|
37
41
|
userId: number;
|
|
38
42
|
fullName: string;
|
|
39
43
|
}[];
|
|
44
|
+
/** The person's unread messages in it. */
|
|
40
45
|
unread: number;
|
|
41
46
|
lastMessage?: {
|
|
42
47
|
fromUserId: number;
|
|
@@ -46,7 +51,10 @@ export interface ConversationSummary {
|
|
|
46
51
|
}
|
|
47
52
|
/** The person's conversations, latest first, with their last message as text. */
|
|
48
53
|
export declare function conversations(context: BrowserContext, siteUrl: string): Promise<ConversationSummary[]>;
|
|
49
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* A conversation's messages, oldest first, as text, and its members as `conversations()` gives them:
|
|
56
|
+
* everyone but the person, whether they wrote in it or not (the person alone in their own conversation).
|
|
57
|
+
*/
|
|
50
58
|
export declare function conversation(context: BrowserContext, siteUrl: string, conversationId: number): Promise<{
|
|
51
59
|
id: number;
|
|
52
60
|
members: {
|
|
@@ -66,3 +74,30 @@ export declare function sendMessage(context: BrowserContext, siteUrl: string, us
|
|
|
66
74
|
messageId: number;
|
|
67
75
|
conversationId?: number;
|
|
68
76
|
}>;
|
|
77
|
+
/** Who `messageParticipants` writes to: chosen users, or the participants `participants()` chooses with these filters. */
|
|
78
|
+
export type ParticipantSelection = {
|
|
79
|
+
userIds: number[];
|
|
80
|
+
} | {
|
|
81
|
+
role?: number;
|
|
82
|
+
group?: number;
|
|
83
|
+
inactiveSince?: Date;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Sends one message to several participants of a course, as the participants page's "Send a message"
|
|
87
|
+
* does for the users selected: one private message each, in one call. They are `userIds`, or the
|
|
88
|
+
* participants `participants()` chooses with `role`, `group` and `inactiveSince` (all of them when
|
|
89
|
+
* none is given), the person left out. `sentTo` lists exactly who got it, `refused` who Moodle
|
|
90
|
+
* didn't write to and why (they blocked the person, their privacy settings); someone who may message
|
|
91
|
+
* any user (a teacher, `moodle/site:messageanyuser`) gets through a block, as in Moodle's own page
|
|
92
|
+
* (confirmed empirically, Moodle 5.2). Throws `MessageError`
|
|
93
|
+
* for an empty message or nobody to write to, `NoParticipantsError` when the person can't see the
|
|
94
|
+
* course's participants.
|
|
95
|
+
*/
|
|
96
|
+
export declare function messageParticipants(context: BrowserContext, siteUrl: string, courseId: number, text: string, selection?: ParticipantSelection): Promise<{
|
|
97
|
+
changed: string;
|
|
98
|
+
sentTo: number[];
|
|
99
|
+
refused: {
|
|
100
|
+
userId: number;
|
|
101
|
+
reason: string;
|
|
102
|
+
}[];
|
|
103
|
+
}>;
|
|
@@ -3,6 +3,7 @@ import { isoDate } from "../courses/list.js";
|
|
|
3
3
|
import { htmlToTexts } from "../forums/discussions.js";
|
|
4
4
|
import { decodeEntities } from "../../core/text.js";
|
|
5
5
|
import { MoodleError } from "../../core/errors.js";
|
|
6
|
+
import { participants } from "../participants/participants.js";
|
|
6
7
|
/** Moodle didn't deliver a message. */
|
|
7
8
|
export class MessageError extends MoodleError {
|
|
8
9
|
name = "MessageError";
|
|
@@ -52,9 +53,23 @@ export async function conversations(context, siteUrl) {
|
|
|
52
53
|
};
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* A conversation's messages, oldest first, as text, and its members as `conversations()` gives them:
|
|
58
|
+
* everyone but the person, whether they wrote in it or not (the person alone in their own conversation).
|
|
59
|
+
*/
|
|
56
60
|
export async function conversation(context, siteUrl, conversationId) {
|
|
57
61
|
const { userId } = await readPageConfig(context, siteUrl);
|
|
62
|
+
// Every member, the person included.
|
|
63
|
+
const everyone = await callService(context, siteUrl, "core_message_get_conversation_members", {
|
|
64
|
+
userid: userId,
|
|
65
|
+
conversationid: conversationId,
|
|
66
|
+
includecontactrequests: false,
|
|
67
|
+
includeprivacyinfo: false,
|
|
68
|
+
limitfrom: 0,
|
|
69
|
+
limitnum: 0,
|
|
70
|
+
});
|
|
71
|
+
const others = everyone.filter((m) => m.id !== userId);
|
|
72
|
+
// Only the messages: this service's `members` are the messages' senders, not the conversation's.
|
|
58
73
|
const found = await callService(context, siteUrl, "core_message_get_conversation_messages", {
|
|
59
74
|
currentuserid: userId,
|
|
60
75
|
convid: conversationId,
|
|
@@ -65,14 +80,17 @@ export async function conversation(context, siteUrl, conversationId) {
|
|
|
65
80
|
const texts = await htmlToTexts(context, found.messages.map((m) => m.text));
|
|
66
81
|
return {
|
|
67
82
|
id: found.id,
|
|
68
|
-
members:
|
|
83
|
+
members: (others.length > 0 ? others : everyone).map((m) => ({ userId: m.id, fullName: m.fullname })),
|
|
69
84
|
messages: found.messages.map((m, i) => ({ id: m.id, fromUserId: m.useridfrom, text: texts[i] ?? "", time: isoDate(m.timecreated) })),
|
|
70
85
|
};
|
|
71
86
|
}
|
|
72
|
-
|
|
73
|
-
export async function sendMessage(context, siteUrl, userId, text) {
|
|
87
|
+
function checkNotEmpty(text) {
|
|
74
88
|
if (text.replace(/<[^>]*>/g, "").replace(/ /g, " ").trim() === "")
|
|
75
89
|
throw new MessageError("The message is empty: write something before sending it.");
|
|
90
|
+
}
|
|
91
|
+
/** Sends a private message to a user, as the messaging drawer does; returns the message and its conversation. */
|
|
92
|
+
export async function sendMessage(context, siteUrl, userId, text) {
|
|
93
|
+
checkNotEmpty(text);
|
|
76
94
|
const [sent] = await callService(context, siteUrl, "core_message_send_instant_messages", {
|
|
77
95
|
messages: [{ touserid: userId, text, textformat: 1 }],
|
|
78
96
|
});
|
|
@@ -81,4 +99,42 @@ export async function sendMessage(context, siteUrl, userId, text) {
|
|
|
81
99
|
throw new MessageError(`Moodle didn't send the message to user ${userId}: ${sent?.errormessage ?? "no reason given"}`);
|
|
82
100
|
return { changed: `Message ${sent.msgid} sent to user ${userId}.`, messageId: sent.msgid, ...(sent.conversationid ? { conversationId: sent.conversationid } : {}) };
|
|
83
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Sends one message to several participants of a course, as the participants page's "Send a message"
|
|
104
|
+
* does for the users selected: one private message each, in one call. They are `userIds`, or the
|
|
105
|
+
* participants `participants()` chooses with `role`, `group` and `inactiveSince` (all of them when
|
|
106
|
+
* none is given), the person left out. `sentTo` lists exactly who got it, `refused` who Moodle
|
|
107
|
+
* didn't write to and why (they blocked the person, their privacy settings); someone who may message
|
|
108
|
+
* any user (a teacher, `moodle/site:messageanyuser`) gets through a block, as in Moodle's own page
|
|
109
|
+
* (confirmed empirically, Moodle 5.2). Throws `MessageError`
|
|
110
|
+
* for an empty message or nobody to write to, `NoParticipantsError` when the person can't see the
|
|
111
|
+
* course's participants.
|
|
112
|
+
*/
|
|
113
|
+
export async function messageParticipants(context, siteUrl, courseId, text, selection = {}) {
|
|
114
|
+
checkNotEmpty(text);
|
|
115
|
+
let userIds;
|
|
116
|
+
if ("userIds" in selection)
|
|
117
|
+
userIds = [...new Set(selection.userIds)];
|
|
118
|
+
else {
|
|
119
|
+
const { userId: me } = await readPageConfig(context, siteUrl);
|
|
120
|
+
userIds = (await participants(context, siteUrl, courseId, selection)).map((p) => p.userId).filter((id) => id !== me);
|
|
121
|
+
}
|
|
122
|
+
if (userIds.length === 0)
|
|
123
|
+
throw new MessageError(`Nobody to write to in course ${courseId}: no participant matches.`);
|
|
124
|
+
const sent = await callService(context, siteUrl, "core_message_send_instant_messages", {
|
|
125
|
+
messages: userIds.map((touserid) => ({ touserid, text, textformat: 1 })),
|
|
126
|
+
});
|
|
127
|
+
// One answer per message, in order; a refused one has id -1 and Moodle's reason.
|
|
128
|
+
const sentTo = [];
|
|
129
|
+
const refused = [];
|
|
130
|
+
userIds.forEach((userId, i) => {
|
|
131
|
+
const answer = sent[i];
|
|
132
|
+
if (answer && answer.msgid >= 0)
|
|
133
|
+
sentTo.push(userId);
|
|
134
|
+
else
|
|
135
|
+
refused.push({ userId, reason: answer?.errormessage ?? "no reason given" });
|
|
136
|
+
});
|
|
137
|
+
const refusedText = refused.length > 0 ? `; refused for ${refused.map((r) => r.userId).join(", ")}` : "";
|
|
138
|
+
return { changed: `Message sent to ${sentTo.length} participant(s) of course ${courseId}${refusedText}.`, sentTo, refused };
|
|
139
|
+
}
|
|
84
140
|
//# sourceMappingURL=messages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/areas/messages/messages.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/areas/messages/messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { BrowserContext } from "playwright-core";
|
|
2
|
+
import { MoodleError } from "../../core/errors.js";
|
|
3
|
+
/** Moodle refused to enrol, unenrol or change a role: no manual enrolment, a role the person can't assign, a user not enrolled. */
|
|
4
|
+
export declare class EnrolmentError extends MoodleError {
|
|
5
|
+
name: string;
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/** A user the person may enrol in a course. */
|
|
9
|
+
export interface PotentialUser {
|
|
10
|
+
userId: number;
|
|
11
|
+
fullName: string;
|
|
12
|
+
/** Only when the site shows emails to the person (its identity fields). */
|
|
13
|
+
email?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Users the person may enrol in a course by manual enrolment, matching `search` anywhere in their
|
|
17
|
+
* name or the identity fields the site shows (all of them, a page of up to 100, when empty), as the
|
|
18
|
+
* "Enrol users" dialog finds them. Throws `EnrolmentError` when the course has no manual enrolment
|
|
19
|
+
* the person can use.
|
|
20
|
+
*/
|
|
21
|
+
export declare function potentialUsers(context: BrowserContext, siteUrl: string, courseId: number, search?: string): Promise<PotentialUser[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Enrols users in a course by manual enrolment, as the participants page's "Enrol users" dialog does:
|
|
24
|
+
* with `roleId` or the enrolment's default role, from `start` (now, unless given) until `end` (the
|
|
25
|
+
* enrolment's default duration, unless given). Users already enrolled keep their enrolment, with the
|
|
26
|
+
* new dates. Throws `EnrolmentError` with Moodle's reason when it refuses (a role the person can't
|
|
27
|
+
* assign, no manual enrolment).
|
|
28
|
+
*/
|
|
29
|
+
export declare function enrolUsers(context: BrowserContext, siteUrl: string, courseId: number, userIds: number[], { roleId, start, end }?: {
|
|
30
|
+
roleId?: number;
|
|
31
|
+
start?: Date;
|
|
32
|
+
end?: Date;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
changed: string;
|
|
35
|
+
count: number;
|
|
36
|
+
roleId?: number;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Unenrols a user from a course: removes every enrolment of theirs the person may remove (its
|
|
40
|
+
* unenrol link on the participants page), with their roles and group memberships in the course, as
|
|
41
|
+
* that link does. `changed` and `removed` say which ones (by enrolment method's name), `kept` those
|
|
42
|
+
* the person may not remove (a cohort sync, another teacher's method). Throws `EnrolmentError` when
|
|
43
|
+
* the user isn't enrolled.
|
|
44
|
+
*/
|
|
45
|
+
export declare function unenrolUser(context: BrowserContext, siteUrl: string, courseId: number, userId: number): Promise<{
|
|
46
|
+
changed: string;
|
|
47
|
+
removed: string[];
|
|
48
|
+
kept: string[];
|
|
49
|
+
}>;
|
|
50
|
+
/**
|
|
51
|
+
* Sets a user's roles in a course, as the participants page's roles column does: gives the roles in
|
|
52
|
+
* `roleIds` the person may assign, and takes away the others the person may assign. Roles the person
|
|
53
|
+
* can't assign that the user already holds, and those from elsewhere (a category, an enrolment that
|
|
54
|
+
* protects them), stay. Returns the user's roles afterwards, as that column shows them. Throws
|
|
55
|
+
* `EnrolmentError` with Moodle's reason for a role the person can't assign or a user not enrolled.
|
|
56
|
+
*/
|
|
57
|
+
export declare function setUserRoles(context: BrowserContext, siteUrl: string, courseId: number, userId: number, roleIds: number[]): Promise<{
|
|
58
|
+
changed: string;
|
|
59
|
+
roleIds: number[];
|
|
60
|
+
}>;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { MoodleServiceError, callService } from "../../core/ajax.js";
|
|
2
|
+
import { openSitePage } from "../../core/session.js";
|
|
3
|
+
import { siteFetch } from "../../core/http.js";
|
|
4
|
+
import { inPage } from "../../core/inPage.js";
|
|
5
|
+
import { dateSelectorParts } from "../../core/forms.js";
|
|
6
|
+
import { MoodleError } from "../../core/errors.js";
|
|
7
|
+
import { MAX_PARTICIPANT_PAGES, NoParticipantsError, PARTICIPANTS_PAGE_SIZE, participantsTablePage } from "./participants.js";
|
|
8
|
+
/** Moodle refused to enrol, unenrol or change a role: no manual enrolment, a role the person can't assign, a user not enrolled. */
|
|
9
|
+
export class EnrolmentError extends MoodleError {
|
|
10
|
+
name = "EnrolmentError";
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message, "enrolment");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Opens the participants page and reads the manual enrolment's id ("Enrol users" button), the course context and the sesskey. */
|
|
16
|
+
async function openEnrolment(context, siteUrl, courseId) {
|
|
17
|
+
const page = await openSitePage(context, siteUrl, `user/index.php?id=${courseId}`);
|
|
18
|
+
try {
|
|
19
|
+
const facts = await page.evaluate(() => {
|
|
20
|
+
const g = globalThis;
|
|
21
|
+
const enrolId = Number(g.document.querySelector('form[action*="/enrol/manual/manage.php"] input[name="enrolid"]')?.value);
|
|
22
|
+
return {
|
|
23
|
+
participants: g.document.body.id === "page-course-view-participants",
|
|
24
|
+
...(enrolId ? { enrolId } : {}),
|
|
25
|
+
...(g.M?.cfg?.contextid ? { contextId: g.M.cfg.contextid } : {}),
|
|
26
|
+
...(g.M?.cfg?.sesskey ? { sesskey: g.M.cfg.sesskey } : {}),
|
|
27
|
+
...(g.M?.cfg?.usertimezone ? { timeZone: g.M.cfg.usertimezone } : {}),
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
if (!facts.participants)
|
|
31
|
+
throw new NoParticipantsError(`You can't see the participants of course ${courseId}: it doesn't exist, or you aren't allowed.`);
|
|
32
|
+
if (!facts.enrolId || !facts.contextId || !facts.sesskey) {
|
|
33
|
+
throw new EnrolmentError(`Course ${courseId} has no manual enrolment you can enrol users with: it isn't in the course's enrolment methods, it's disabled, or you aren't allowed to enrol.`);
|
|
34
|
+
}
|
|
35
|
+
return { page, enrolId: facts.enrolId, contextId: facts.contextId, sesskey: facts.sesskey, timeZone: facts.timeZone ?? "UTC" };
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
await page.close().catch(() => undefined);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Users the person may enrol in a course by manual enrolment, matching `search` anywhere in their
|
|
44
|
+
* name or the identity fields the site shows (all of them, a page of up to 100, when empty), as the
|
|
45
|
+
* "Enrol users" dialog finds them. Throws `EnrolmentError` when the course has no manual enrolment
|
|
46
|
+
* the person can use.
|
|
47
|
+
*/
|
|
48
|
+
export async function potentialUsers(context, siteUrl, courseId, search = "") {
|
|
49
|
+
const { page, enrolId } = await openEnrolment(context, siteUrl, courseId);
|
|
50
|
+
await page.close().catch(() => undefined);
|
|
51
|
+
const found = await callService(context, siteUrl, "core_enrol_get_potential_users", {
|
|
52
|
+
courseid: courseId,
|
|
53
|
+
enrolid: enrolId,
|
|
54
|
+
search,
|
|
55
|
+
searchanywhere: true,
|
|
56
|
+
page: 0,
|
|
57
|
+
perpage: 100,
|
|
58
|
+
});
|
|
59
|
+
return found.map((u) => ({ userId: u.id, fullName: u.fullname, ...(u.email ? { email: u.email } : {}) }));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Enrols users in a course by manual enrolment, as the participants page's "Enrol users" dialog does:
|
|
63
|
+
* with `roleId` or the enrolment's default role, from `start` (now, unless given) until `end` (the
|
|
64
|
+
* enrolment's default duration, unless given). Users already enrolled keep their enrolment, with the
|
|
65
|
+
* new dates. Throws `EnrolmentError` with Moodle's reason when it refuses (a role the person can't
|
|
66
|
+
* assign, no manual enrolment).
|
|
67
|
+
*/
|
|
68
|
+
export async function enrolUsers(context, siteUrl, courseId, userIds, { roleId, start, end } = {}) {
|
|
69
|
+
if (userIds.length === 0)
|
|
70
|
+
throw new EnrolmentError("No users to enrol: give at least one user id.");
|
|
71
|
+
const { page, enrolId, contextId, sesskey, timeZone } = await openEnrolment(context, siteUrl, courseId);
|
|
72
|
+
let defaults;
|
|
73
|
+
try {
|
|
74
|
+
const { html } = await callService(context, siteUrl, "core_get_fragment", { component: "enrol_manual", callback: "enrol_users_form", contextid: contextId, args: [] });
|
|
75
|
+
// A helper inside: through inPage (see the conventions on page.evaluate).
|
|
76
|
+
defaults = await inPage(page, (html) => {
|
|
77
|
+
const g = globalThis;
|
|
78
|
+
const form = new g.DOMParser().parseFromString(html, "text/html");
|
|
79
|
+
const selected = (name) => form.querySelector(`select[name="${name}"] option[selected]`)?.value;
|
|
80
|
+
return {
|
|
81
|
+
...(selected("roletoassign") ? { roleId: selected("roletoassign") } : {}),
|
|
82
|
+
duration: selected("duration") ?? "",
|
|
83
|
+
...(selected("startdate") ? { startdate: selected("startdate") } : {}),
|
|
84
|
+
recoverGrades: form.querySelector('input[type="checkbox"][name="recovergrades"]')?.checked === true,
|
|
85
|
+
};
|
|
86
|
+
}, html);
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
await page.close().catch(() => undefined);
|
|
90
|
+
}
|
|
91
|
+
const role = roleId !== undefined ? String(roleId) : defaults.roleId;
|
|
92
|
+
const query = new URLSearchParams({ id: String(courseId), action: "enrol", enrolid: String(enrolId), sesskey });
|
|
93
|
+
for (const userId of userIds)
|
|
94
|
+
query.append("userlist[]", String(userId));
|
|
95
|
+
if (role)
|
|
96
|
+
query.set("roletoassign", role);
|
|
97
|
+
if (defaults.recoverGrades)
|
|
98
|
+
query.set("recovergrades", "1");
|
|
99
|
+
// 5 is the start menu's "Choose...": the date selector's own date.
|
|
100
|
+
if (start) {
|
|
101
|
+
query.set("startdate", "5");
|
|
102
|
+
for (const [key, value] of Object.entries(dateSelectorParts("startdateselect", start, timeZone)))
|
|
103
|
+
query.set(key, String(value));
|
|
104
|
+
}
|
|
105
|
+
else if (defaults.startdate)
|
|
106
|
+
query.set("startdate", defaults.startdate);
|
|
107
|
+
if (end) {
|
|
108
|
+
query.set("timeend[enabled]", "1");
|
|
109
|
+
for (const [key, value] of Object.entries(dateSelectorParts("timeend", end, timeZone)))
|
|
110
|
+
query.set(key, String(value));
|
|
111
|
+
}
|
|
112
|
+
else if (defaults.duration)
|
|
113
|
+
query.set("duration", defaults.duration);
|
|
114
|
+
const { body } = await siteFetch(context, new URL(`enrol/manual/ajax.php?${query}`, siteUrl).href);
|
|
115
|
+
let answer;
|
|
116
|
+
try {
|
|
117
|
+
answer = JSON.parse(body);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
throw new EnrolmentError(`Moodle didn't answer the enrolment in course ${courseId} as expected.`);
|
|
121
|
+
}
|
|
122
|
+
// Moodle answers its refusals (enrol_ajax_exception) as JSON with the reason in `error`.
|
|
123
|
+
if (answer.error)
|
|
124
|
+
throw new EnrolmentError(`Moodle didn't enrol the users in course ${courseId}: ${answer.error}`);
|
|
125
|
+
const count = answer.count ?? 0;
|
|
126
|
+
return { changed: `${count} user(s) enrolled in course ${courseId}${role ? ` with role ${role}` : ""}.`, count, ...(role ? { roleId: Number(role) } : {}) };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Unenrols a user from a course: removes every enrolment of theirs the person may remove (its
|
|
130
|
+
* unenrol link on the participants page), with their roles and group memberships in the course, as
|
|
131
|
+
* that link does. `changed` and `removed` say which ones (by enrolment method's name), `kept` those
|
|
132
|
+
* the person may not remove (a cohort sync, another teacher's method). Throws `EnrolmentError` when
|
|
133
|
+
* the user isn't enrolled.
|
|
134
|
+
*/
|
|
135
|
+
export async function unenrolUser(context, siteUrl, courseId, userId) {
|
|
136
|
+
const parser = await openSitePage(context, siteUrl, `user/index.php?id=${courseId}`);
|
|
137
|
+
let cell = { found: false, enrolments: [] };
|
|
138
|
+
try {
|
|
139
|
+
if ((await parser.locator("body#page-course-view-participants").count()) === 0) {
|
|
140
|
+
throw new NoParticipantsError(`You can't see the participants of course ${courseId}: it doesn't exist, or you aren't allowed.`);
|
|
141
|
+
}
|
|
142
|
+
for (let pagenumber = 1; pagenumber <= MAX_PARTICIPANT_PAGES && !cell.found; pagenumber++) {
|
|
143
|
+
const html = await participantsTablePage(context, siteUrl, courseId, [], pagenumber);
|
|
144
|
+
const read = await parser.evaluate(({ html, userId }) => {
|
|
145
|
+
const g = globalThis;
|
|
146
|
+
const doc = new g.DOMParser().parseFromString(html, "text/html");
|
|
147
|
+
const rows = Array.from(doc.querySelectorAll("tbody tr:not(.emptyrow)"));
|
|
148
|
+
const row = rows.find((r) => {
|
|
149
|
+
const href = r.querySelector('a[href*="/user/view.php?id="]')?.getAttribute("href") ?? "";
|
|
150
|
+
return Number(new URL(href, "http://x/").searchParams.get("id")) === userId;
|
|
151
|
+
});
|
|
152
|
+
if (!row)
|
|
153
|
+
return { rows: rows.length, cell: { found: false, enrolments: [] } };
|
|
154
|
+
// One block per enrolment, named by its method, with an unenrol link when the person may remove it.
|
|
155
|
+
const enrolments = Array.from(row.querySelectorAll("[data-enrolinstancename]")).map((block) => {
|
|
156
|
+
const link = block.querySelector('a[data-action="unenrol"]')?.getAttribute("href");
|
|
157
|
+
const ueId = link ? Number(new URL(link, "http://x/").searchParams.get("ue")) : 0;
|
|
158
|
+
return { method: block.getAttribute("data-enrolinstancename") ?? "", ...(ueId ? { ueId } : {}) };
|
|
159
|
+
});
|
|
160
|
+
return { rows: rows.length, cell: { found: true, enrolments } };
|
|
161
|
+
}, { html, userId });
|
|
162
|
+
cell = read.cell;
|
|
163
|
+
if (read.rows < PARTICIPANTS_PAGE_SIZE)
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
await parser.close().catch(() => undefined);
|
|
169
|
+
}
|
|
170
|
+
if (!cell.found)
|
|
171
|
+
throw new EnrolmentError(`User ${userId} isn't enrolled in course ${courseId}.`);
|
|
172
|
+
const removed = [];
|
|
173
|
+
const kept = [];
|
|
174
|
+
for (const enrolment of cell.enrolments) {
|
|
175
|
+
if (!enrolment.ueId) {
|
|
176
|
+
kept.push(enrolment.method);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const { result, errors } = await callService(context, siteUrl, "core_enrol_unenrol_user_enrolment", { ueid: enrolment.ueId });
|
|
180
|
+
if (!result) {
|
|
181
|
+
if (errors.length > 0)
|
|
182
|
+
throw new EnrolmentError(`Moodle didn't remove user ${userId}'s enrolment "${enrolment.method}" in course ${courseId}: ${errors.map((e) => e.message).join("; ")}`);
|
|
183
|
+
kept.push(enrolment.method);
|
|
184
|
+
}
|
|
185
|
+
else
|
|
186
|
+
removed.push(enrolment.method);
|
|
187
|
+
}
|
|
188
|
+
if (removed.length === 0)
|
|
189
|
+
throw new EnrolmentError(`You can't remove any of user ${userId}'s enrolments in course ${courseId} (${kept.join(", ")}).`);
|
|
190
|
+
const rest = kept.length > 0 ? `; kept, which you can't remove: ${kept.join(", ")}` : "";
|
|
191
|
+
return { changed: `User ${userId} unenrolled from course ${courseId}: removed ${removed.join(", ")}${rest}.`, removed, kept };
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Sets a user's roles in a course, as the participants page's roles column does: gives the roles in
|
|
195
|
+
* `roleIds` the person may assign, and takes away the others the person may assign. Roles the person
|
|
196
|
+
* can't assign that the user already holds, and those from elsewhere (a category, an enrolment that
|
|
197
|
+
* protects them), stay. Returns the user's roles afterwards, as that column shows them. Throws
|
|
198
|
+
* `EnrolmentError` with Moodle's reason for a role the person can't assign or a user not enrolled.
|
|
199
|
+
*/
|
|
200
|
+
export async function setUserRoles(context, siteUrl, courseId, userId, roleIds) {
|
|
201
|
+
let answer;
|
|
202
|
+
try {
|
|
203
|
+
answer = await callService(context, siteUrl, "core_update_inplace_editable", {
|
|
204
|
+
component: "core_user",
|
|
205
|
+
itemtype: "user_roles",
|
|
206
|
+
itemid: `${courseId}:${userId}`,
|
|
207
|
+
value: JSON.stringify(roleIds.map(String)),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
if (error instanceof MoodleServiceError)
|
|
212
|
+
throw new EnrolmentError(`Moodle didn't set user ${userId}'s roles in course ${courseId}: ${error.message}`);
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
const now = JSON.parse(answer.value || "[]").map(Number);
|
|
216
|
+
return { changed: `User ${userId}'s roles in course ${courseId} are now: ${now.join(", ") || "none"}.`, roleIds: now };
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=enrolments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrolments.js","sourceRoot":"","sources":["../../../src/areas/participants/enrolments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { BrowserContext } from "playwright-core";
|
|
2
|
+
/** A group's settings, as its form names them. */
|
|
3
|
+
export interface GroupSettings {
|
|
4
|
+
name?: string;
|
|
5
|
+
/** HTML. */
|
|
6
|
+
description?: string;
|
|
7
|
+
idNumber?: string;
|
|
8
|
+
/** The key that puts a student enrolling with self enrolment in this group. */
|
|
9
|
+
enrolmentKey?: string;
|
|
10
|
+
}
|
|
11
|
+
/** A grouping's settings, as its form names them. */
|
|
12
|
+
export interface GroupingSettings {
|
|
13
|
+
name?: string;
|
|
14
|
+
/** HTML. */
|
|
15
|
+
description?: string;
|
|
16
|
+
idNumber?: string;
|
|
17
|
+
}
|
|
18
|
+
/** A grouping of a course (a set of its groups), as `groupings` lists it. */
|
|
19
|
+
export interface Grouping {
|
|
20
|
+
id: number;
|
|
21
|
+
name: string;
|
|
22
|
+
/** The ids of its groups. */
|
|
23
|
+
groupIds: number[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a group in a course with its group form (`group/group.php`). Throws `FormError` with
|
|
27
|
+
* Moodle's reason when it refuses (a name already used, an enrolment key another group has).
|
|
28
|
+
*/
|
|
29
|
+
export declare function createGroup(context: BrowserContext, siteUrl: string, courseId: number, settings: GroupSettings & {
|
|
30
|
+
name: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
changed: string;
|
|
33
|
+
groupId: number;
|
|
34
|
+
}>;
|
|
35
|
+
/** Changes a group's name, description, ID number or enrolment key with its form; what isn't given stays. */
|
|
36
|
+
export declare function updateGroup(context: BrowserContext, siteUrl: string, groupId: number, settings: GroupSettings): Promise<{
|
|
37
|
+
changed: string;
|
|
38
|
+
}>;
|
|
39
|
+
/** Deletes a group, as the groups page's "Delete selected group" does once confirmed; its members stay in the course. */
|
|
40
|
+
export declare function deleteGroup(context: BrowserContext, siteUrl: string, groupId: number): Promise<{
|
|
41
|
+
changed: string;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Adds and removes a group's members (user ids), as its members page does. Only the course's
|
|
45
|
+
* participants can be added: ids the page doesn't offer (not enrolled, or already members) and
|
|
46
|
+
* members not in it are left as they were and named in `changed`. Returns the members afterwards.
|
|
47
|
+
*/
|
|
48
|
+
export declare function setGroupMembers(context: BrowserContext, siteUrl: string, groupId: number, { add, remove }: {
|
|
49
|
+
add?: number[];
|
|
50
|
+
remove?: number[];
|
|
51
|
+
}): Promise<{
|
|
52
|
+
changed: string;
|
|
53
|
+
members: number[];
|
|
54
|
+
}>;
|
|
55
|
+
/** A course's groupings with their groups' ids, from its groupings page and each grouping's groups page. Throws `MoodleError` with Moodle's refusal for a person who can't manage groups. */
|
|
56
|
+
export declare function groupings(context: BrowserContext, siteUrl: string, courseId: number): Promise<Grouping[]>;
|
|
57
|
+
/** Creates a grouping in a course with its form (`group/grouping.php`); add its groups with `setGroupingGroups`. */
|
|
58
|
+
export declare function createGrouping(context: BrowserContext, siteUrl: string, courseId: number, settings: GroupingSettings & {
|
|
59
|
+
name: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
changed: string;
|
|
62
|
+
groupingId: number;
|
|
63
|
+
}>;
|
|
64
|
+
/** Deletes a grouping, as its delete icon does once confirmed; its groups stay. */
|
|
65
|
+
export declare function deleteGrouping(context: BrowserContext, siteUrl: string, groupingId: number): Promise<{
|
|
66
|
+
changed: string;
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* Makes a grouping's groups exactly `groupIds`, as its groups page adds and removes them. Groups of
|
|
70
|
+
* other courses aren't offered there and are left out, named in `changed`. Returns the groups afterwards.
|
|
71
|
+
*/
|
|
72
|
+
export declare function setGroupingGroups(context: BrowserContext, siteUrl: string, groupingId: number, groupIds: number[]): Promise<{
|
|
73
|
+
changed: string;
|
|
74
|
+
groupIds: number[];
|
|
75
|
+
}>;
|