bitsnap-react 1.7.1 → 1.8.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.
Files changed (85) hide show
  1. package/dist/CartProvider-5KAG5QGA.mjs +2 -0
  2. package/dist/CartProvider-7GJXW2IP.js +2 -0
  3. package/dist/CartProvider-7GJXW2IP.js.map +1 -0
  4. package/dist/catalog.js +1 -1
  5. package/dist/catalog.js.map +1 -1
  6. package/dist/catalog.mjs +1 -1
  7. package/dist/chunk-45AP7UZE.mjs +2 -0
  8. package/dist/chunk-45AP7UZE.mjs.map +1 -0
  9. package/dist/chunk-7XTDFTQU.js +4 -0
  10. package/dist/chunk-7XTDFTQU.js.map +1 -0
  11. package/dist/chunk-C6Z7LOHB.mjs +2 -0
  12. package/dist/chunk-C6Z7LOHB.mjs.map +1 -0
  13. package/dist/chunk-HB6KQT26.mjs +4 -0
  14. package/dist/chunk-HB6KQT26.mjs.map +1 -0
  15. package/dist/chunk-JSDGZ4NY.js +2 -0
  16. package/dist/chunk-JSDGZ4NY.js.map +1 -0
  17. package/dist/chunk-KOVKUJAW.mjs +2 -0
  18. package/dist/chunk-KOVKUJAW.mjs.map +1 -0
  19. package/dist/chunk-KOYBZORL.js +2 -0
  20. package/dist/chunk-KOYBZORL.js.map +1 -0
  21. package/dist/chunk-LWK4E5G5.js +2 -0
  22. package/dist/chunk-LWK4E5G5.js.map +1 -0
  23. package/dist/chunk-OJT3YO2R.mjs +2 -0
  24. package/dist/{chunk-6KQBDN7M.mjs.map → chunk-OJT3YO2R.mjs.map} +1 -1
  25. package/dist/chunk-OUYRKNZJ.mjs +2 -0
  26. package/dist/chunk-OUYRKNZJ.mjs.map +1 -0
  27. package/dist/chunk-P2YB25KZ.js +2 -0
  28. package/dist/chunk-P2YB25KZ.js.map +1 -0
  29. package/dist/chunk-T2POA6RW.js +2 -0
  30. package/dist/chunk-T2POA6RW.js.map +1 -0
  31. package/dist/chunk-VPKE2ZOR.mjs +2 -0
  32. package/dist/{chunk-FTYJTO6O.mjs.map → chunk-VPKE2ZOR.mjs.map} +1 -1
  33. package/dist/chunk-WRCXZMKK.js +2 -0
  34. package/dist/chunk-WRCXZMKK.js.map +1 -0
  35. package/dist/chunk-WSM4OM72.mjs +2 -0
  36. package/dist/chunk-WSM4OM72.mjs.map +1 -0
  37. package/dist/chunk-XRNTUSBH.js +2 -0
  38. package/dist/chunk-XRNTUSBH.js.map +1 -0
  39. package/dist/chunk-Z2BKIX6F.js +2 -0
  40. package/dist/chunk-Z2BKIX6F.js.map +1 -0
  41. package/dist/course.d.mts +1872 -0
  42. package/dist/course.d.ts +1872 -0
  43. package/dist/course.js +2 -0
  44. package/dist/course.js.map +1 -0
  45. package/dist/course.mjs +2 -0
  46. package/dist/course.mjs.map +1 -0
  47. package/dist/errors.js +1 -1
  48. package/dist/errors.js.map +1 -1
  49. package/dist/index.css +1 -1
  50. package/dist/index.css.map +1 -1
  51. package/dist/index.d.mts +5 -36
  52. package/dist/index.d.ts +5 -36
  53. package/dist/index.js +1 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/index.mjs +1 -1
  56. package/dist/index.mjs.map +1 -1
  57. package/dist/internal.js +1 -1
  58. package/dist/internal.js.map +1 -1
  59. package/dist/methods-ITD6WFIY.mjs +2 -0
  60. package/dist/methods-JENIGNF7.js +2 -0
  61. package/dist/methods-JENIGNF7.js.map +1 -0
  62. package/dist/models.js +1 -1
  63. package/dist/models.js.map +1 -1
  64. package/dist/returns.d.mts +5 -195
  65. package/dist/returns.d.ts +5 -195
  66. package/dist/returns.js +1 -1
  67. package/dist/returns.js.map +1 -1
  68. package/dist/returns.mjs +1 -1
  69. package/dist/texts-CIEFbJTN.d.ts +196 -0
  70. package/dist/texts-tQtAGJCT.d.mts +196 -0
  71. package/dist/types-BTm_ZolC.d.ts +40 -0
  72. package/dist/types-PSBBDdQm.d.mts +40 -0
  73. package/package.json +57 -22
  74. package/dist/CartProvider-F2VH7WFO.mjs +0 -2
  75. package/dist/chunk-3TENJTY4.mjs +0 -2
  76. package/dist/chunk-3TENJTY4.mjs.map +0 -1
  77. package/dist/chunk-4HOZFM6V.mjs +0 -2
  78. package/dist/chunk-4HOZFM6V.mjs.map +0 -1
  79. package/dist/chunk-6KQBDN7M.mjs +0 -2
  80. package/dist/chunk-FTYJTO6O.mjs +0 -2
  81. package/dist/chunk-RATFYRKZ.mjs +0 -4
  82. package/dist/chunk-RATFYRKZ.mjs.map +0 -1
  83. package/dist/methods-PFZSMZFU.mjs +0 -2
  84. /package/dist/{CartProvider-F2VH7WFO.mjs.map → CartProvider-5KAG5QGA.mjs.map} +0 -0
  85. /package/dist/{methods-PFZSMZFU.mjs.map → methods-ITD6WFIY.mjs.map} +0 -0
@@ -0,0 +1,1872 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { G as GetThemeOutput } from './types-PSBBDdQm.mjs';
3
+ import { Client } from '@connectrpc/connect';
4
+ import { GenService, GenMessage } from '@bufbuild/protobuf/codegenv2';
5
+ import { Timestamp } from '@bufbuild/protobuf/wkt';
6
+ import { Message } from '@bufbuild/protobuf';
7
+ import './texts-tQtAGJCT.mjs';
8
+ import 'react';
9
+ import './appearance-core-Dt2grZdl.mjs';
10
+
11
+ /**
12
+ * Shared text machinery: typed string tables per locale, the locale fallback
13
+ * and a merge with caller overrides. Each module (checkout, later returns)
14
+ * supplies its own key type and default tables.
15
+ */
16
+ /** Strings of one locale, keyed by text key. */
17
+ type TextTable<Key extends string> = Record<Key, string>;
18
+ /** Default tables for the supported locales. */
19
+ type LocaleTables<Key extends string> = {
20
+ en: TextTable<Key>;
21
+ pl: TextTable<Key>;
22
+ };
23
+
24
+ /**
25
+ * Every string of the course view. Pass a partial object through the `texts`
26
+ * prop of `PanelCourse` to override any of them, whatever the locale.
27
+ * Placeholders like `{count}` stay in overrides.
28
+ */
29
+ type CourseTexts = {
30
+ back: string;
31
+ loading: string;
32
+ retry: string;
33
+ errorGeneric: string;
34
+ errorUnauthorized: string;
35
+ errorNotFound: string;
36
+ errorUnavailable: string;
37
+ previewBadge: string;
38
+ /** Placeholders `{done}` and `{total}`. */
39
+ progressLessons: string;
40
+ /** Placeholder `{percent}`. */
41
+ progressPercent: string;
42
+ contents: string;
43
+ free: string;
44
+ locked: string;
45
+ /** Placeholder `{test}`. */
46
+ lockedByTest: string;
47
+ /** Placeholder `{test}`. */
48
+ lockedPage: string;
49
+ testBadge: string;
50
+ completed: string;
51
+ continueCourse: string;
52
+ noItem: string;
53
+ markComplete: string;
54
+ markedComplete: string;
55
+ prevItem: string;
56
+ nextItem: string;
57
+ attachments: string;
58
+ download: string;
59
+ autoplay: string;
60
+ videoError: string;
61
+ videoRetry: string;
62
+ noContent: string;
63
+ testGating: string;
64
+ testAttemptsLeft: string;
65
+ testAttemptsUnlimited: string;
66
+ testNoAttemptsLeft: string;
67
+ testPassThreshold: string;
68
+ testBestScore: string;
69
+ testSubmit: string;
70
+ testSubmitting: string;
71
+ /** Placeholder `{count}`. */
72
+ testUnanswered: string;
73
+ testPassed: string;
74
+ testFailed: string;
75
+ /** Placeholder `{percent}`. */
76
+ testScore: string;
77
+ testCorrect: string;
78
+ testIncorrect: string;
79
+ testCorrectAnswer: string;
80
+ testTryAgain: string;
81
+ testPreviousAttempts: string;
82
+ /** Placeholders `{percent}` and `{date}`. */
83
+ testAttemptRow: string;
84
+ testNoQuestions: string;
85
+ mcqSingle: string;
86
+ mcqMultiple: string;
87
+ todoHint: string;
88
+ todoRequired: string;
89
+ gapPlaceholder: string;
90
+ sortHint: string;
91
+ moveUp: string;
92
+ moveDown: string;
93
+ questionsTitle: string;
94
+ questionsEmpty: string;
95
+ questionPlaceholder: string;
96
+ questionSubmit: string;
97
+ questionSent: string;
98
+ questionMine: string;
99
+ questionTeamAnswer: string;
100
+ rateTitle: string;
101
+ /** Placeholder `{n}`. */
102
+ rateStar: string;
103
+ ratePlaceholder: string;
104
+ rateSubmit: string;
105
+ rateSaved: string;
106
+ /** Placeholders `{average}` and `{count}`. */
107
+ rateAverage: string;
108
+ };
109
+ declare const COURSE_TEXT_TABLES: LocaleTables<keyof CourseTexts>;
110
+ /** Course strings for a locale (library locale by default) with overrides. */
111
+ declare function getCourseTexts(overrides?: Partial<CourseTexts>, locale?: string): CourseTexts;
112
+
113
+ /**
114
+ * Domain model of the course view. It is independent of the generated
115
+ * protobuf messages, so a creator preview can feed `PanelCourse` through its
116
+ * own `CourseDataSource` without the RPC layer.
117
+ */
118
+ type CourseType = "standard" | "video";
119
+ type CourseItemKind = "lesson" | "test";
120
+ /** The gating test that has to be passed before the item opens. */
121
+ type LockReason = {
122
+ gatingTestId: string;
123
+ gatingTestTitle: string;
124
+ };
125
+ /** A lesson or a test in the list of a course. */
126
+ type CourseItem = {
127
+ /** Unique among all items of the course. */
128
+ id: string;
129
+ kind: CourseItemKind;
130
+ title: string;
131
+ isFree: boolean;
132
+ locked: boolean;
133
+ lockReason?: LockReason;
134
+ /** A lesson: completed. A test: passed. */
135
+ completed: boolean;
136
+ /** Video length, 0 when unknown. */
137
+ durationSeconds: number;
138
+ thumbnailUrl?: string;
139
+ /** Tests only: passing it unlocks the following sections. */
140
+ gating: boolean;
141
+ };
142
+ /** A module (standard course) or a section (video course). */
143
+ type CourseSection = {
144
+ id: string;
145
+ title: string;
146
+ description: string;
147
+ items: CourseItem[];
148
+ };
149
+ type Course = {
150
+ id: string;
151
+ type: CourseType;
152
+ title: string;
153
+ description: string;
154
+ coverUrl?: string;
155
+ totalLessons: number;
156
+ completedLessons: number;
157
+ /** 0 to 100. */
158
+ progressPercent: number;
159
+ sections: CourseSection[];
160
+ /** Tests of the whole course, after the last section. */
161
+ finalItems: CourseItem[];
162
+ /** Item to continue with; empty when everything is done. */
163
+ resumeItemId: string;
164
+ };
165
+ type ItemRef = {
166
+ id: string;
167
+ kind: CourseItemKind;
168
+ };
169
+ type LessonVideo = {
170
+ hlsUrl: string;
171
+ posterUrl?: string;
172
+ durationSeconds: number;
173
+ };
174
+ type LessonAttachment = {
175
+ id: string;
176
+ name: string;
177
+ /** Bytes. */
178
+ size: number;
179
+ url: string;
180
+ };
181
+ type Lesson = {
182
+ id: string;
183
+ sectionId: string;
184
+ title: string;
185
+ description: string;
186
+ /** Raw HTML of the editor. Always pass it through `sanitizeLessonHtml`. */
187
+ contentHtml: string;
188
+ video?: LessonVideo;
189
+ attachments: LessonAttachment[];
190
+ prev?: ItemRef;
191
+ next?: ItemRef;
192
+ completed: boolean;
193
+ /** Where the customer stopped the video. */
194
+ positionSeconds: number;
195
+ /** 0 when the customer has not rated the lesson. */
196
+ myRating: number;
197
+ averageRating: number;
198
+ ratingCount: number;
199
+ /** When the signed URLs stop working. */
200
+ urlsExpireAt?: Date;
201
+ };
202
+ type SaveProgressInput = {
203
+ lessonId: string;
204
+ completed: boolean;
205
+ positionSeconds: number;
206
+ durationSeconds: number;
207
+ };
208
+ type ProgressSaved = {
209
+ completed: boolean;
210
+ completedLessons: number;
211
+ progressPercent: number;
212
+ };
213
+ type TestChoice = {
214
+ id: string;
215
+ label: string;
216
+ };
217
+ type TestQuestionConfig = {
218
+ type: "mcq";
219
+ choices: TestChoice[];
220
+ multiple: boolean;
221
+ } | {
222
+ type: "todolist";
223
+ steps: {
224
+ id: string;
225
+ label: string;
226
+ required: boolean;
227
+ }[];
228
+ } | {
229
+ type: "fill_gap";
230
+ template: string;
231
+ blanks: string[];
232
+ } | {
233
+ type: "sort_order";
234
+ items: TestChoice[];
235
+ };
236
+ type TestQuestion = {
237
+ id: string;
238
+ prompt: string;
239
+ points: number;
240
+ config: TestQuestionConfig;
241
+ };
242
+ type QuestionAnswer = {
243
+ type: "mcq";
244
+ selectedIds: string[];
245
+ } | {
246
+ type: "todolist";
247
+ checkedIds: string[];
248
+ } | {
249
+ type: "fill_gap";
250
+ values: Record<string, string>;
251
+ } | {
252
+ type: "sort_order";
253
+ orderedIds: string[];
254
+ };
255
+ /** Answers by question id. */
256
+ type TestAnswers = Record<string, QuestionAnswer>;
257
+ type Test = {
258
+ id: string;
259
+ title: string;
260
+ description: string;
261
+ gating: boolean;
262
+ passThresholdPercent: number;
263
+ /** 0 means unlimited. */
264
+ attemptsAllowed: number;
265
+ /** `undefined` when the attempts are unlimited. */
266
+ attemptsLeft?: number;
267
+ attemptCount: number;
268
+ bestScorePercent: number;
269
+ passed: boolean;
270
+ questions: TestQuestion[];
271
+ };
272
+ type TestSubmission = {
273
+ id: string;
274
+ scorePercent: number;
275
+ passed: boolean;
276
+ durationMs: number;
277
+ createdAt?: Date;
278
+ };
279
+ type QuestionResult = {
280
+ questionId: string;
281
+ correct: boolean;
282
+ points: number;
283
+ /** Only when the show-answers rule of the test allows it. */
284
+ correctAnswer?: QuestionAnswer;
285
+ };
286
+ type TestResult = {
287
+ submission: TestSubmission;
288
+ results: QuestionResult[];
289
+ attemptsLeft?: number;
290
+ };
291
+ type TestSubmissionList = {
292
+ submissions: TestSubmission[];
293
+ bestScorePercent: number;
294
+ attemptCount: number;
295
+ };
296
+ type LessonQuestion = {
297
+ id: string;
298
+ content: string;
299
+ authorName: string;
300
+ isMine: boolean;
301
+ createdAt?: Date;
302
+ answer?: {
303
+ content: string;
304
+ createdAt?: Date;
305
+ };
306
+ };
307
+ type LessonRating = {
308
+ myRating: number;
309
+ averageRating: number;
310
+ ratingCount: number;
311
+ };
312
+ type CourseErrorCode = "unauthorized" | "course_not_found" | "item_not_found" | "item_locked" | "no_attempts_left" | "invalid_argument" | "rate_limited" | "unavailable" | "unknown";
313
+ /** Failure reported by a data source. */
314
+ declare class CourseError extends Error {
315
+ readonly code: CourseErrorCode;
316
+ constructor(code: CourseErrorCode, message?: string);
317
+ }
318
+ /**
319
+ * Everything `PanelCourse` needs from a backend, scoped to one course and one
320
+ * customer. Methods reject with `CourseError` for failures the view can
321
+ * explain (any other error is shown as a generic one).
322
+ *
323
+ * The default implementation is `createRpcCourseDataSource`; the creator
324
+ * preview of the Bitsnap dashboard passes its own.
325
+ */
326
+ interface CourseDataSource {
327
+ getCourse(): Promise<Course>;
328
+ getLesson(lessonId: string): Promise<Lesson>;
329
+ saveProgress(input: SaveProgressInput): Promise<ProgressSaved>;
330
+ getTest(testId: string): Promise<Test>;
331
+ submitTest(testId: string, answers: TestAnswers, durationMs: number): Promise<TestResult>;
332
+ listSubmissions(testId: string): Promise<TestSubmissionList>;
333
+ listQuestions(lessonId: string): Promise<LessonQuestion[]>;
334
+ askQuestion(lessonId: string, content: string): Promise<LessonQuestion>;
335
+ rate(lessonId: string, score: number, comment?: string): Promise<LessonRating>;
336
+ }
337
+
338
+ type PanelCourseProps = {
339
+ /** `UserProduct.access_id` of the purchased course. Not needed with `dataSource`. */
340
+ accessId?: string;
341
+ /** Panel session token; read from the panel session when omitted. */
342
+ accessToken?: string;
343
+ /**
344
+ * Replaces the default data source (`UserPanelCourseService` through the
345
+ * panel's transport). The creator preview of the dashboard passes its own.
346
+ */
347
+ dataSource?: CourseDataSource;
348
+ /** Creator preview: shows a badge and never saves progress. */
349
+ preview?: boolean;
350
+ /** The open lesson or test. Controlled together with `onItemChange`. */
351
+ itemId?: string;
352
+ onItemChange?: (itemId: string) => void;
353
+ /** Shows a back button. */
354
+ onBack?: () => void;
355
+ /** Course structure to render right away (server rendering, preview). */
356
+ initialCourse?: Course;
357
+ /** Text overrides; Polish and English defaults by `locale`. */
358
+ texts?: Partial<CourseTexts>;
359
+ /** Defaults to the locale of the library (`setLocale`). */
360
+ locale?: string;
361
+ /** Brand colors; the panel theme (`setTheme`) by default. */
362
+ theme?: GetThemeOutput;
363
+ className?: string;
364
+ };
365
+ /**
366
+ * The course of a customer inside the panel: structure with progress and
367
+ * locks, lessons with video, text and attachments, tests, questions and
368
+ * ratings. Standard courses get a sidebar of modules, video courses a
369
+ * playlist next to the player.
370
+ *
371
+ * Load it lazily from `bitsnap-react/course`. Inside the panel it needs only
372
+ * `accessId` of the purchased course.
373
+ */
374
+ declare function PanelCourse$1({ accessId, accessToken, dataSource: customDataSource, preview, itemId, onItemChange, onBack, initialCourse, texts: textOverrides, locale, theme, className, }: PanelCourseProps): react_jsx_runtime.JSX.Element;
375
+
376
+ type RpcCourseDataSourceOptions = {
377
+ /** `UserProduct.access_id` of the purchased course. */
378
+ accessId: string;
379
+ /**
380
+ * Panel session token. By default it is read from the panel session of the
381
+ * configured project (`setProjectID`, `setHost`) on every call.
382
+ */
383
+ accessToken?: string;
384
+ /** Bitsnap host; the panel host (`setHost`, bitsnap.pl by default) otherwise. */
385
+ host?: string;
386
+ };
387
+ /**
388
+ * Default data source: `UserPanelCourseService` on `{host}/api/rpc`, using the
389
+ * transport and the session token of the panel.
390
+ */
391
+ declare function createRpcCourseDataSource(options: RpcCourseDataSourceOptions): CourseDataSource;
392
+
393
+ /**
394
+ * Why an item is locked.
395
+ *
396
+ * @generated from message public_api.v1.PanelLockReason
397
+ */
398
+ type PanelLockReason = Message<"public_api.v1.PanelLockReason"> & {
399
+ /**
400
+ * The test (of an earlier module) that has to be passed first.
401
+ *
402
+ * @generated from field: string gating_test_id = 1;
403
+ */
404
+ gatingTestId: string;
405
+ /**
406
+ * @generated from field: string gating_test_title = 2;
407
+ */
408
+ gatingTestTitle: string;
409
+ };
410
+ /**
411
+ * A lesson or a test in the list of a course.
412
+ *
413
+ * @generated from message public_api.v1.PanelCourseItem
414
+ */
415
+ type PanelCourseItem = Message<"public_api.v1.PanelCourseItem"> & {
416
+ /**
417
+ * Unique among all items of the course, lessons and tests alike.
418
+ *
419
+ * @generated from field: string id = 1;
420
+ */
421
+ id: string;
422
+ /**
423
+ * @generated from field: public_api.v1.PanelCourseItemKind kind = 2;
424
+ */
425
+ kind: PanelCourseItemKind;
426
+ /**
427
+ * @generated from field: string title = 3;
428
+ */
429
+ title: string;
430
+ /**
431
+ * Free for everyone, shown as a badge.
432
+ *
433
+ * @generated from field: bool is_free = 4;
434
+ */
435
+ isFree: boolean;
436
+ /**
437
+ * A locked item can't be opened (GetLesson/GetTest fail with ITEM_LOCKED).
438
+ *
439
+ * @generated from field: bool locked = 5;
440
+ */
441
+ locked: boolean;
442
+ /**
443
+ * Set when locked.
444
+ *
445
+ * @generated from field: optional public_api.v1.PanelLockReason lock_reason = 6;
446
+ */
447
+ lockReason?: PanelLockReason;
448
+ /**
449
+ * A lesson: completed. A test: passed.
450
+ *
451
+ * @generated from field: bool completed = 7;
452
+ */
453
+ completed: boolean;
454
+ /**
455
+ * Video length in seconds; 0 when unknown or the lesson has no video.
456
+ *
457
+ * @generated from field: int32 duration_seconds = 8;
458
+ */
459
+ durationSeconds: number;
460
+ /**
461
+ * Signed URL of the thumbnail; unset when there is none.
462
+ *
463
+ * @generated from field: optional string thumbnail_url = 9;
464
+ */
465
+ thumbnailUrl?: string;
466
+ /**
467
+ * Tests only: lessons of the following sections stay locked until it is passed.
468
+ *
469
+ * @generated from field: bool gating = 10;
470
+ */
471
+ gating: boolean;
472
+ };
473
+ /**
474
+ * A module (standard course) or a section (video course).
475
+ *
476
+ * @generated from message public_api.v1.PanelCourseSection
477
+ */
478
+ type PanelCourseSection = Message<"public_api.v1.PanelCourseSection"> & {
479
+ /**
480
+ * @generated from field: string id = 1;
481
+ */
482
+ id: string;
483
+ /**
484
+ * @generated from field: string title = 2;
485
+ */
486
+ title: string;
487
+ /**
488
+ * @generated from field: string description = 3;
489
+ */
490
+ description: string;
491
+ /**
492
+ * Lessons in order, then the tests of the section.
493
+ *
494
+ * @generated from field: repeated public_api.v1.PanelCourseItem items = 4;
495
+ */
496
+ items: PanelCourseItem[];
497
+ };
498
+ /**
499
+ * @generated from message public_api.v1.PanelCourse
500
+ */
501
+ type PanelCourse = Message<"public_api.v1.PanelCourse"> & {
502
+ /**
503
+ * Id of the course in Bitsnap (stable, used in the URL of the panel).
504
+ *
505
+ * @generated from field: string id = 1;
506
+ */
507
+ id: string;
508
+ /**
509
+ * @generated from field: public_api.v1.PanelCourseType type = 2;
510
+ */
511
+ type: PanelCourseType;
512
+ /**
513
+ * @generated from field: string title = 3;
514
+ */
515
+ title: string;
516
+ /**
517
+ * @generated from field: string description = 4;
518
+ */
519
+ description: string;
520
+ /**
521
+ * Signed URL of the cover; unset when the course has none.
522
+ *
523
+ * @generated from field: optional string cover_url = 5;
524
+ */
525
+ coverUrl?: string;
526
+ /**
527
+ * @generated from field: int32 total_lessons = 6;
528
+ */
529
+ totalLessons: number;
530
+ /**
531
+ * @generated from field: int32 completed_lessons = 7;
532
+ */
533
+ completedLessons: number;
534
+ /**
535
+ * 0 to 100.
536
+ *
537
+ * @generated from field: int32 progress_percent = 8;
538
+ */
539
+ progressPercent: number;
540
+ /**
541
+ * @generated from field: repeated public_api.v1.PanelCourseSection sections = 9;
542
+ */
543
+ sections: PanelCourseSection[];
544
+ /**
545
+ * Tests of the whole course, shown after the last section.
546
+ *
547
+ * @generated from field: repeated public_api.v1.PanelCourseItem final_items = 10;
548
+ */
549
+ finalItems: PanelCourseItem[];
550
+ /**
551
+ * Item to continue with (first unfinished and unlocked lesson); empty when
552
+ * everything is done.
553
+ *
554
+ * @generated from field: string resume_item_id = 11;
555
+ */
556
+ resumeItemId: string;
557
+ };
558
+ /**
559
+ * @generated from message public_api.v1.UserPanelGetCourseRequest
560
+ */
561
+ type UserPanelGetCourseRequest = Message<"public_api.v1.UserPanelGetCourseRequest"> & {
562
+ /**
563
+ * @generated from field: string access_token = 1;
564
+ */
565
+ accessToken: string;
566
+ /**
567
+ * @generated from field: string access_id = 2;
568
+ */
569
+ accessId: string;
570
+ };
571
+ /**
572
+ * Describes the message public_api.v1.UserPanelGetCourseRequest.
573
+ * Use `create(UserPanelGetCourseRequestSchema)` to create a new message.
574
+ */
575
+ declare const UserPanelGetCourseRequestSchema: GenMessage<UserPanelGetCourseRequest>;
576
+ /**
577
+ * @generated from message public_api.v1.UserPanelGetCourseResponse
578
+ */
579
+ type UserPanelGetCourseResponse = Message<"public_api.v1.UserPanelGetCourseResponse"> & {
580
+ /**
581
+ * @generated from oneof public_api.v1.UserPanelGetCourseResponse.result
582
+ */
583
+ result: {
584
+ /**
585
+ * @generated from field: public_api.v1.PanelCourse success = 1;
586
+ */
587
+ value: PanelCourse;
588
+ case: "success";
589
+ } | {
590
+ /**
591
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
592
+ */
593
+ value: PanelCourseFailure;
594
+ case: "failure";
595
+ } | {
596
+ case: undefined;
597
+ value?: undefined;
598
+ };
599
+ };
600
+ /**
601
+ * Describes the message public_api.v1.UserPanelGetCourseResponse.
602
+ * Use `create(UserPanelGetCourseResponseSchema)` to create a new message.
603
+ */
604
+ declare const UserPanelGetCourseResponseSchema: GenMessage<UserPanelGetCourseResponse>;
605
+ /**
606
+ * @generated from message public_api.v1.PanelVideo
607
+ */
608
+ type PanelVideo = Message<"public_api.v1.PanelVideo"> & {
609
+ /**
610
+ * Cloudflare Stream HLS manifest URL with a signed token.
611
+ *
612
+ * @generated from field: string hls_url = 1;
613
+ */
614
+ hlsUrl: string;
615
+ /**
616
+ * @generated from field: optional string poster_url = 2;
617
+ */
618
+ posterUrl?: string;
619
+ /**
620
+ * @generated from field: int32 duration_seconds = 3;
621
+ */
622
+ durationSeconds: number;
623
+ };
624
+ /**
625
+ * @generated from message public_api.v1.PanelAttachment
626
+ */
627
+ type PanelAttachment = Message<"public_api.v1.PanelAttachment"> & {
628
+ /**
629
+ * @generated from field: string id = 1;
630
+ */
631
+ id: string;
632
+ /**
633
+ * @generated from field: string name = 2;
634
+ */
635
+ name: string;
636
+ /**
637
+ * Bytes.
638
+ *
639
+ * @generated from field: int64 size = 3;
640
+ */
641
+ size: bigint;
642
+ /**
643
+ * Presigned S3 URL.
644
+ *
645
+ * @generated from field: string url = 4;
646
+ */
647
+ url: string;
648
+ };
649
+ /**
650
+ * Neighbour of a lesson in the course order.
651
+ *
652
+ * @generated from message public_api.v1.PanelItemRef
653
+ */
654
+ type PanelItemRef = Message<"public_api.v1.PanelItemRef"> & {
655
+ /**
656
+ * @generated from field: string id = 1;
657
+ */
658
+ id: string;
659
+ /**
660
+ * @generated from field: public_api.v1.PanelCourseItemKind kind = 2;
661
+ */
662
+ kind: PanelCourseItemKind;
663
+ };
664
+ /**
665
+ * @generated from message public_api.v1.PanelLesson
666
+ */
667
+ type PanelLesson = Message<"public_api.v1.PanelLesson"> & {
668
+ /**
669
+ * @generated from field: string id = 1;
670
+ */
671
+ id: string;
672
+ /**
673
+ * @generated from field: string section_id = 2;
674
+ */
675
+ sectionId: string;
676
+ /**
677
+ * @generated from field: string title = 3;
678
+ */
679
+ title: string;
680
+ /**
681
+ * Plain text, mainly for video lessons.
682
+ *
683
+ * @generated from field: string description = 4;
684
+ */
685
+ description: string;
686
+ /**
687
+ * HTML from the editor of the creator. The client sanitises it before it
688
+ * renders it, the server should too.
689
+ *
690
+ * @generated from field: string content_html = 5;
691
+ */
692
+ contentHtml: string;
693
+ /**
694
+ * Unset when the lesson has no video.
695
+ *
696
+ * @generated from field: optional public_api.v1.PanelVideo video = 6;
697
+ */
698
+ video?: PanelVideo;
699
+ /**
700
+ * @generated from field: repeated public_api.v1.PanelAttachment attachments = 7;
701
+ */
702
+ attachments: PanelAttachment[];
703
+ /**
704
+ * Unset for the first / last item of the course.
705
+ *
706
+ * @generated from field: optional public_api.v1.PanelItemRef prev = 8;
707
+ */
708
+ prev?: PanelItemRef;
709
+ /**
710
+ * @generated from field: optional public_api.v1.PanelItemRef next = 9;
711
+ */
712
+ next?: PanelItemRef;
713
+ /**
714
+ * @generated from field: bool completed = 10;
715
+ */
716
+ completed: boolean;
717
+ /**
718
+ * Where the customer stopped the video, to resume from.
719
+ *
720
+ * @generated from field: int32 position_seconds = 11;
721
+ */
722
+ positionSeconds: number;
723
+ /**
724
+ * Rating of the customer, 0 when not rated.
725
+ *
726
+ * @generated from field: int32 my_rating = 12;
727
+ */
728
+ myRating: number;
729
+ /**
730
+ * @generated from field: float average_rating = 13;
731
+ */
732
+ averageRating: number;
733
+ /**
734
+ * @generated from field: int32 rating_count = 14;
735
+ */
736
+ ratingCount: number;
737
+ /**
738
+ * When the signed URLs (video, attachments) stop working; unset when unknown.
739
+ *
740
+ * @generated from field: optional google.protobuf.Timestamp urls_expire_at = 15;
741
+ */
742
+ urlsExpireAt?: Timestamp;
743
+ };
744
+ /**
745
+ * @generated from message public_api.v1.UserPanelGetLessonRequest
746
+ */
747
+ type UserPanelGetLessonRequest = Message<"public_api.v1.UserPanelGetLessonRequest"> & {
748
+ /**
749
+ * @generated from field: string access_token = 1;
750
+ */
751
+ accessToken: string;
752
+ /**
753
+ * @generated from field: string access_id = 2;
754
+ */
755
+ accessId: string;
756
+ /**
757
+ * @generated from field: string lesson_id = 3;
758
+ */
759
+ lessonId: string;
760
+ };
761
+ /**
762
+ * Describes the message public_api.v1.UserPanelGetLessonRequest.
763
+ * Use `create(UserPanelGetLessonRequestSchema)` to create a new message.
764
+ */
765
+ declare const UserPanelGetLessonRequestSchema: GenMessage<UserPanelGetLessonRequest>;
766
+ /**
767
+ * @generated from message public_api.v1.UserPanelGetLessonResponse
768
+ */
769
+ type UserPanelGetLessonResponse = Message<"public_api.v1.UserPanelGetLessonResponse"> & {
770
+ /**
771
+ * @generated from oneof public_api.v1.UserPanelGetLessonResponse.result
772
+ */
773
+ result: {
774
+ /**
775
+ * @generated from field: public_api.v1.PanelLesson success = 1;
776
+ */
777
+ value: PanelLesson;
778
+ case: "success";
779
+ } | {
780
+ /**
781
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
782
+ */
783
+ value: PanelCourseFailure;
784
+ case: "failure";
785
+ } | {
786
+ case: undefined;
787
+ value?: undefined;
788
+ };
789
+ };
790
+ /**
791
+ * Describes the message public_api.v1.UserPanelGetLessonResponse.
792
+ * Use `create(UserPanelGetLessonResponseSchema)` to create a new message.
793
+ */
794
+ declare const UserPanelGetLessonResponseSchema: GenMessage<UserPanelGetLessonResponse>;
795
+ /**
796
+ * @generated from message public_api.v1.UserPanelSaveLessonProgressRequest
797
+ */
798
+ type UserPanelSaveLessonProgressRequest = Message<"public_api.v1.UserPanelSaveLessonProgressRequest"> & {
799
+ /**
800
+ * @generated from field: string access_token = 1;
801
+ */
802
+ accessToken: string;
803
+ /**
804
+ * @generated from field: string access_id = 2;
805
+ */
806
+ accessId: string;
807
+ /**
808
+ * @generated from field: string lesson_id = 3;
809
+ */
810
+ lessonId: string;
811
+ /**
812
+ * Mark the lesson completed. Never un-completes a lesson.
813
+ *
814
+ * @generated from field: bool completed = 4;
815
+ */
816
+ completed: boolean;
817
+ /**
818
+ * Playback position in seconds.
819
+ *
820
+ * @generated from field: int32 position_seconds = 5;
821
+ */
822
+ positionSeconds: number;
823
+ /**
824
+ * Length of the video in seconds, so the server can compute the percentage.
825
+ *
826
+ * @generated from field: int32 duration_seconds = 6;
827
+ */
828
+ durationSeconds: number;
829
+ };
830
+ /**
831
+ * Describes the message public_api.v1.UserPanelSaveLessonProgressRequest.
832
+ * Use `create(UserPanelSaveLessonProgressRequestSchema)` to create a new message.
833
+ */
834
+ declare const UserPanelSaveLessonProgressRequestSchema: GenMessage<UserPanelSaveLessonProgressRequest>;
835
+ /**
836
+ * @generated from message public_api.v1.UserPanelSaveLessonProgressResponse
837
+ */
838
+ type UserPanelSaveLessonProgressResponse = Message<"public_api.v1.UserPanelSaveLessonProgressResponse"> & {
839
+ /**
840
+ * @generated from oneof public_api.v1.UserPanelSaveLessonProgressResponse.result
841
+ */
842
+ result: {
843
+ /**
844
+ * @generated from field: public_api.v1.UserPanelSaveLessonProgressResponse.Result success = 1;
845
+ */
846
+ value: UserPanelSaveLessonProgressResponse_Result;
847
+ case: "success";
848
+ } | {
849
+ /**
850
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
851
+ */
852
+ value: PanelCourseFailure;
853
+ case: "failure";
854
+ } | {
855
+ case: undefined;
856
+ value?: undefined;
857
+ };
858
+ };
859
+ /**
860
+ * Describes the message public_api.v1.UserPanelSaveLessonProgressResponse.
861
+ * Use `create(UserPanelSaveLessonProgressResponseSchema)` to create a new message.
862
+ */
863
+ declare const UserPanelSaveLessonProgressResponseSchema: GenMessage<UserPanelSaveLessonProgressResponse>;
864
+ /**
865
+ * @generated from message public_api.v1.UserPanelSaveLessonProgressResponse.Result
866
+ */
867
+ type UserPanelSaveLessonProgressResponse_Result = Message<"public_api.v1.UserPanelSaveLessonProgressResponse.Result"> & {
868
+ /**
869
+ * @generated from field: bool completed = 1;
870
+ */
871
+ completed: boolean;
872
+ /**
873
+ * Updated numbers of the whole course.
874
+ *
875
+ * @generated from field: int32 completed_lessons = 2;
876
+ */
877
+ completedLessons: number;
878
+ /**
879
+ * @generated from field: int32 progress_percent = 3;
880
+ */
881
+ progressPercent: number;
882
+ };
883
+ /**
884
+ * @generated from message public_api.v1.PanelChoice
885
+ */
886
+ type PanelChoice = Message<"public_api.v1.PanelChoice"> & {
887
+ /**
888
+ * @generated from field: string id = 1;
889
+ */
890
+ id: string;
891
+ /**
892
+ * @generated from field: string label = 2;
893
+ */
894
+ label: string;
895
+ };
896
+ /**
897
+ * Multiple choice question.
898
+ *
899
+ * @generated from message public_api.v1.PanelMcqConfig
900
+ */
901
+ type PanelMcqConfig = Message<"public_api.v1.PanelMcqConfig"> & {
902
+ /**
903
+ * @generated from field: repeated public_api.v1.PanelChoice choices = 1;
904
+ */
905
+ choices: PanelChoice[];
906
+ /**
907
+ * True when more than one choice may be selected (checkboxes), false for
908
+ * radio buttons. Does not tell how many answers are correct.
909
+ *
910
+ * @generated from field: bool multiple = 2;
911
+ */
912
+ multiple: boolean;
913
+ };
914
+ /**
915
+ * A checklist: all required steps have to be checked.
916
+ *
917
+ * @generated from message public_api.v1.PanelTodolistConfig
918
+ */
919
+ type PanelTodolistConfig = Message<"public_api.v1.PanelTodolistConfig"> & {
920
+ /**
921
+ * @generated from field: repeated public_api.v1.PanelTodolistConfig.Step steps = 1;
922
+ */
923
+ steps: PanelTodolistConfig_Step[];
924
+ };
925
+ /**
926
+ * @generated from message public_api.v1.PanelTodolistConfig.Step
927
+ */
928
+ type PanelTodolistConfig_Step = Message<"public_api.v1.PanelTodolistConfig.Step"> & {
929
+ /**
930
+ * @generated from field: string id = 1;
931
+ */
932
+ id: string;
933
+ /**
934
+ * @generated from field: string label = 2;
935
+ */
936
+ label: string;
937
+ /**
938
+ * @generated from field: bool required = 3;
939
+ */
940
+ required: boolean;
941
+ };
942
+ /**
943
+ * Text with gaps.
944
+ *
945
+ * @generated from message public_api.v1.PanelFillGapConfig
946
+ */
947
+ type PanelFillGapConfig = Message<"public_api.v1.PanelFillGapConfig"> & {
948
+ /**
949
+ * Text with placeholders `{{blank_id}}`, one for each id in `blanks`.
950
+ *
951
+ * @generated from field: string template = 1;
952
+ */
953
+ template: string;
954
+ /**
955
+ * @generated from field: repeated string blanks = 2;
956
+ */
957
+ blanks: string[];
958
+ };
959
+ /**
960
+ * Order the items. The server returns them already shuffled.
961
+ *
962
+ * @generated from message public_api.v1.PanelSortOrderConfig
963
+ */
964
+ type PanelSortOrderConfig = Message<"public_api.v1.PanelSortOrderConfig"> & {
965
+ /**
966
+ * @generated from field: repeated public_api.v1.PanelChoice items = 1;
967
+ */
968
+ items: PanelChoice[];
969
+ };
970
+ /**
971
+ * @generated from message public_api.v1.PanelTestQuestion
972
+ */
973
+ type PanelTestQuestion = Message<"public_api.v1.PanelTestQuestion"> & {
974
+ /**
975
+ * @generated from field: string id = 1;
976
+ */
977
+ id: string;
978
+ /**
979
+ * @generated from field: string prompt = 2;
980
+ */
981
+ prompt: string;
982
+ /**
983
+ * @generated from field: int32 points = 3;
984
+ */
985
+ points: number;
986
+ /**
987
+ * @generated from oneof public_api.v1.PanelTestQuestion.config
988
+ */
989
+ config: {
990
+ /**
991
+ * @generated from field: public_api.v1.PanelMcqConfig mcq = 10;
992
+ */
993
+ value: PanelMcqConfig;
994
+ case: "mcq";
995
+ } | {
996
+ /**
997
+ * @generated from field: public_api.v1.PanelTodolistConfig todolist = 11;
998
+ */
999
+ value: PanelTodolistConfig;
1000
+ case: "todolist";
1001
+ } | {
1002
+ /**
1003
+ * @generated from field: public_api.v1.PanelFillGapConfig fill_gap = 12;
1004
+ */
1005
+ value: PanelFillGapConfig;
1006
+ case: "fillGap";
1007
+ } | {
1008
+ /**
1009
+ * @generated from field: public_api.v1.PanelSortOrderConfig sort_order = 13;
1010
+ */
1011
+ value: PanelSortOrderConfig;
1012
+ case: "sortOrder";
1013
+ } | {
1014
+ case: undefined;
1015
+ value?: undefined;
1016
+ };
1017
+ };
1018
+ /**
1019
+ * @generated from message public_api.v1.PanelTest
1020
+ */
1021
+ type PanelTest = Message<"public_api.v1.PanelTest"> & {
1022
+ /**
1023
+ * @generated from field: string id = 1;
1024
+ */
1025
+ id: string;
1026
+ /**
1027
+ * @generated from field: string title = 2;
1028
+ */
1029
+ title: string;
1030
+ /**
1031
+ * @generated from field: string description = 3;
1032
+ */
1033
+ description: string;
1034
+ /**
1035
+ * Passing it unlocks the following sections.
1036
+ *
1037
+ * @generated from field: bool gating = 4;
1038
+ */
1039
+ gating: boolean;
1040
+ /**
1041
+ * Minimum score for a pass, 0 to 100.
1042
+ *
1043
+ * @generated from field: int32 pass_threshold_percent = 5;
1044
+ */
1045
+ passThresholdPercent: number;
1046
+ /**
1047
+ * 0 means unlimited.
1048
+ *
1049
+ * @generated from field: int32 attempts_allowed = 6;
1050
+ */
1051
+ attemptsAllowed: number;
1052
+ /**
1053
+ * Unset when the number of attempts is unlimited.
1054
+ *
1055
+ * @generated from field: optional int32 attempts_left = 7;
1056
+ */
1057
+ attemptsLeft?: number;
1058
+ /**
1059
+ * @generated from field: int32 attempt_count = 8;
1060
+ */
1061
+ attemptCount: number;
1062
+ /**
1063
+ * @generated from field: int32 best_score_percent = 9;
1064
+ */
1065
+ bestScorePercent: number;
1066
+ /**
1067
+ * @generated from field: bool passed = 10;
1068
+ */
1069
+ passed: boolean;
1070
+ /**
1071
+ * Questions in order, without the correct answers.
1072
+ *
1073
+ * @generated from field: repeated public_api.v1.PanelTestQuestion questions = 11;
1074
+ */
1075
+ questions: PanelTestQuestion[];
1076
+ };
1077
+ /**
1078
+ * @generated from message public_api.v1.UserPanelGetTestRequest
1079
+ */
1080
+ type UserPanelGetTestRequest = Message<"public_api.v1.UserPanelGetTestRequest"> & {
1081
+ /**
1082
+ * @generated from field: string access_token = 1;
1083
+ */
1084
+ accessToken: string;
1085
+ /**
1086
+ * @generated from field: string access_id = 2;
1087
+ */
1088
+ accessId: string;
1089
+ /**
1090
+ * @generated from field: string test_id = 3;
1091
+ */
1092
+ testId: string;
1093
+ };
1094
+ /**
1095
+ * Describes the message public_api.v1.UserPanelGetTestRequest.
1096
+ * Use `create(UserPanelGetTestRequestSchema)` to create a new message.
1097
+ */
1098
+ declare const UserPanelGetTestRequestSchema: GenMessage<UserPanelGetTestRequest>;
1099
+ /**
1100
+ * @generated from message public_api.v1.UserPanelGetTestResponse
1101
+ */
1102
+ type UserPanelGetTestResponse = Message<"public_api.v1.UserPanelGetTestResponse"> & {
1103
+ /**
1104
+ * @generated from oneof public_api.v1.UserPanelGetTestResponse.result
1105
+ */
1106
+ result: {
1107
+ /**
1108
+ * @generated from field: public_api.v1.PanelTest success = 1;
1109
+ */
1110
+ value: PanelTest;
1111
+ case: "success";
1112
+ } | {
1113
+ /**
1114
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
1115
+ */
1116
+ value: PanelCourseFailure;
1117
+ case: "failure";
1118
+ } | {
1119
+ case: undefined;
1120
+ value?: undefined;
1121
+ };
1122
+ };
1123
+ /**
1124
+ * Describes the message public_api.v1.UserPanelGetTestResponse.
1125
+ * Use `create(UserPanelGetTestResponseSchema)` to create a new message.
1126
+ */
1127
+ declare const UserPanelGetTestResponseSchema: GenMessage<UserPanelGetTestResponse>;
1128
+ /**
1129
+ * @generated from message public_api.v1.PanelMcqAnswer
1130
+ */
1131
+ type PanelMcqAnswer = Message<"public_api.v1.PanelMcqAnswer"> & {
1132
+ /**
1133
+ * @generated from field: repeated string selected_ids = 1;
1134
+ */
1135
+ selectedIds: string[];
1136
+ };
1137
+ /**
1138
+ * @generated from message public_api.v1.PanelTodolistAnswer
1139
+ */
1140
+ type PanelTodolistAnswer = Message<"public_api.v1.PanelTodolistAnswer"> & {
1141
+ /**
1142
+ * @generated from field: repeated string checked_ids = 1;
1143
+ */
1144
+ checkedIds: string[];
1145
+ };
1146
+ /**
1147
+ * @generated from message public_api.v1.PanelFillGapAnswer
1148
+ */
1149
+ type PanelFillGapAnswer = Message<"public_api.v1.PanelFillGapAnswer"> & {
1150
+ /**
1151
+ * blank id -> text typed by the customer.
1152
+ *
1153
+ * @generated from field: map<string, string> values = 1;
1154
+ */
1155
+ values: {
1156
+ [key: string]: string;
1157
+ };
1158
+ };
1159
+ /**
1160
+ * @generated from message public_api.v1.PanelSortOrderAnswer
1161
+ */
1162
+ type PanelSortOrderAnswer = Message<"public_api.v1.PanelSortOrderAnswer"> & {
1163
+ /**
1164
+ * @generated from field: repeated string ordered_ids = 1;
1165
+ */
1166
+ orderedIds: string[];
1167
+ };
1168
+ /**
1169
+ * An answer to one question. The variant has to match the question's config.
1170
+ *
1171
+ * @generated from message public_api.v1.PanelAnswer
1172
+ */
1173
+ type PanelAnswer = Message<"public_api.v1.PanelAnswer"> & {
1174
+ /**
1175
+ * @generated from field: string question_id = 1;
1176
+ */
1177
+ questionId: string;
1178
+ /**
1179
+ * @generated from oneof public_api.v1.PanelAnswer.value
1180
+ */
1181
+ value: {
1182
+ /**
1183
+ * @generated from field: public_api.v1.PanelMcqAnswer mcq = 10;
1184
+ */
1185
+ value: PanelMcqAnswer;
1186
+ case: "mcq";
1187
+ } | {
1188
+ /**
1189
+ * @generated from field: public_api.v1.PanelTodolistAnswer todolist = 11;
1190
+ */
1191
+ value: PanelTodolistAnswer;
1192
+ case: "todolist";
1193
+ } | {
1194
+ /**
1195
+ * @generated from field: public_api.v1.PanelFillGapAnswer fill_gap = 12;
1196
+ */
1197
+ value: PanelFillGapAnswer;
1198
+ case: "fillGap";
1199
+ } | {
1200
+ /**
1201
+ * @generated from field: public_api.v1.PanelSortOrderAnswer sort_order = 13;
1202
+ */
1203
+ value: PanelSortOrderAnswer;
1204
+ case: "sortOrder";
1205
+ } | {
1206
+ case: undefined;
1207
+ value?: undefined;
1208
+ };
1209
+ };
1210
+ /**
1211
+ * @generated from message public_api.v1.PanelTestSubmission
1212
+ */
1213
+ type PanelTestSubmission = Message<"public_api.v1.PanelTestSubmission"> & {
1214
+ /**
1215
+ * @generated from field: string id = 1;
1216
+ */
1217
+ id: string;
1218
+ /**
1219
+ * @generated from field: int32 score_percent = 2;
1220
+ */
1221
+ scorePercent: number;
1222
+ /**
1223
+ * @generated from field: bool passed = 3;
1224
+ */
1225
+ passed: boolean;
1226
+ /**
1227
+ * @generated from field: int64 duration_ms = 4;
1228
+ */
1229
+ durationMs: bigint;
1230
+ /**
1231
+ * @generated from field: google.protobuf.Timestamp created_at = 5;
1232
+ */
1233
+ createdAt?: Timestamp;
1234
+ };
1235
+ /**
1236
+ * @generated from message public_api.v1.PanelQuestionResult
1237
+ */
1238
+ type PanelQuestionResult = Message<"public_api.v1.PanelQuestionResult"> & {
1239
+ /**
1240
+ * @generated from field: string question_id = 1;
1241
+ */
1242
+ questionId: string;
1243
+ /**
1244
+ * @generated from field: bool correct = 2;
1245
+ */
1246
+ correct: boolean;
1247
+ /**
1248
+ * @generated from field: int32 points = 3;
1249
+ */
1250
+ points: number;
1251
+ /**
1252
+ * The correct answer; only set when the "show answers" rule of the test
1253
+ * allows it (after submit / after pass / never).
1254
+ *
1255
+ * @generated from field: optional public_api.v1.PanelAnswer correct_answer = 4;
1256
+ */
1257
+ correctAnswer?: PanelAnswer;
1258
+ };
1259
+ /**
1260
+ * @generated from message public_api.v1.UserPanelSubmitTestRequest
1261
+ */
1262
+ type UserPanelSubmitTestRequest = Message<"public_api.v1.UserPanelSubmitTestRequest"> & {
1263
+ /**
1264
+ * @generated from field: string access_token = 1;
1265
+ */
1266
+ accessToken: string;
1267
+ /**
1268
+ * @generated from field: string access_id = 2;
1269
+ */
1270
+ accessId: string;
1271
+ /**
1272
+ * @generated from field: string test_id = 3;
1273
+ */
1274
+ testId: string;
1275
+ /**
1276
+ * Unanswered questions may be omitted; they score zero.
1277
+ *
1278
+ * @generated from field: repeated public_api.v1.PanelAnswer answers = 4;
1279
+ */
1280
+ answers: PanelAnswer[];
1281
+ /**
1282
+ * Time spent on the test.
1283
+ *
1284
+ * @generated from field: int64 duration_ms = 5;
1285
+ */
1286
+ durationMs: bigint;
1287
+ };
1288
+ /**
1289
+ * Describes the message public_api.v1.UserPanelSubmitTestRequest.
1290
+ * Use `create(UserPanelSubmitTestRequestSchema)` to create a new message.
1291
+ */
1292
+ declare const UserPanelSubmitTestRequestSchema: GenMessage<UserPanelSubmitTestRequest>;
1293
+ /**
1294
+ * @generated from message public_api.v1.UserPanelSubmitTestResponse
1295
+ */
1296
+ type UserPanelSubmitTestResponse = Message<"public_api.v1.UserPanelSubmitTestResponse"> & {
1297
+ /**
1298
+ * @generated from oneof public_api.v1.UserPanelSubmitTestResponse.result
1299
+ */
1300
+ result: {
1301
+ /**
1302
+ * @generated from field: public_api.v1.UserPanelSubmitTestResponse.Result success = 1;
1303
+ */
1304
+ value: UserPanelSubmitTestResponse_Result;
1305
+ case: "success";
1306
+ } | {
1307
+ /**
1308
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
1309
+ */
1310
+ value: PanelCourseFailure;
1311
+ case: "failure";
1312
+ } | {
1313
+ case: undefined;
1314
+ value?: undefined;
1315
+ };
1316
+ };
1317
+ /**
1318
+ * Describes the message public_api.v1.UserPanelSubmitTestResponse.
1319
+ * Use `create(UserPanelSubmitTestResponseSchema)` to create a new message.
1320
+ */
1321
+ declare const UserPanelSubmitTestResponseSchema: GenMessage<UserPanelSubmitTestResponse>;
1322
+ /**
1323
+ * @generated from message public_api.v1.UserPanelSubmitTestResponse.Result
1324
+ */
1325
+ type UserPanelSubmitTestResponse_Result = Message<"public_api.v1.UserPanelSubmitTestResponse.Result"> & {
1326
+ /**
1327
+ * @generated from field: public_api.v1.PanelTestSubmission submission = 1;
1328
+ */
1329
+ submission?: PanelTestSubmission;
1330
+ /**
1331
+ * @generated from field: repeated public_api.v1.PanelQuestionResult results = 2;
1332
+ */
1333
+ results: PanelQuestionResult[];
1334
+ /**
1335
+ * Unset when the number of attempts is unlimited.
1336
+ *
1337
+ * @generated from field: optional int32 attempts_left = 3;
1338
+ */
1339
+ attemptsLeft?: number;
1340
+ };
1341
+ /**
1342
+ * @generated from message public_api.v1.UserPanelListTestSubmissionsRequest
1343
+ */
1344
+ type UserPanelListTestSubmissionsRequest = Message<"public_api.v1.UserPanelListTestSubmissionsRequest"> & {
1345
+ /**
1346
+ * @generated from field: string access_token = 1;
1347
+ */
1348
+ accessToken: string;
1349
+ /**
1350
+ * @generated from field: string access_id = 2;
1351
+ */
1352
+ accessId: string;
1353
+ /**
1354
+ * @generated from field: string test_id = 3;
1355
+ */
1356
+ testId: string;
1357
+ };
1358
+ /**
1359
+ * Describes the message public_api.v1.UserPanelListTestSubmissionsRequest.
1360
+ * Use `create(UserPanelListTestSubmissionsRequestSchema)` to create a new message.
1361
+ */
1362
+ declare const UserPanelListTestSubmissionsRequestSchema: GenMessage<UserPanelListTestSubmissionsRequest>;
1363
+ /**
1364
+ * @generated from message public_api.v1.UserPanelListTestSubmissionsResponse
1365
+ */
1366
+ type UserPanelListTestSubmissionsResponse = Message<"public_api.v1.UserPanelListTestSubmissionsResponse"> & {
1367
+ /**
1368
+ * @generated from oneof public_api.v1.UserPanelListTestSubmissionsResponse.result
1369
+ */
1370
+ result: {
1371
+ /**
1372
+ * @generated from field: public_api.v1.UserPanelListTestSubmissionsResponse.Result success = 1;
1373
+ */
1374
+ value: UserPanelListTestSubmissionsResponse_Result;
1375
+ case: "success";
1376
+ } | {
1377
+ /**
1378
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
1379
+ */
1380
+ value: PanelCourseFailure;
1381
+ case: "failure";
1382
+ } | {
1383
+ case: undefined;
1384
+ value?: undefined;
1385
+ };
1386
+ };
1387
+ /**
1388
+ * Describes the message public_api.v1.UserPanelListTestSubmissionsResponse.
1389
+ * Use `create(UserPanelListTestSubmissionsResponseSchema)` to create a new message.
1390
+ */
1391
+ declare const UserPanelListTestSubmissionsResponseSchema: GenMessage<UserPanelListTestSubmissionsResponse>;
1392
+ /**
1393
+ * @generated from message public_api.v1.UserPanelListTestSubmissionsResponse.Result
1394
+ */
1395
+ type UserPanelListTestSubmissionsResponse_Result = Message<"public_api.v1.UserPanelListTestSubmissionsResponse.Result"> & {
1396
+ /**
1397
+ * Newest first.
1398
+ *
1399
+ * @generated from field: repeated public_api.v1.PanelTestSubmission submissions = 1;
1400
+ */
1401
+ submissions: PanelTestSubmission[];
1402
+ /**
1403
+ * @generated from field: int32 best_score_percent = 2;
1404
+ */
1405
+ bestScorePercent: number;
1406
+ /**
1407
+ * @generated from field: int32 attempt_count = 3;
1408
+ */
1409
+ attemptCount: number;
1410
+ };
1411
+ /**
1412
+ * @generated from message public_api.v1.PanelQuestionAnswer
1413
+ */
1414
+ type PanelQuestionAnswer = Message<"public_api.v1.PanelQuestionAnswer"> & {
1415
+ /**
1416
+ * @generated from field: string content = 1;
1417
+ */
1418
+ content: string;
1419
+ /**
1420
+ * @generated from field: google.protobuf.Timestamp created_at = 2;
1421
+ */
1422
+ createdAt?: Timestamp;
1423
+ };
1424
+ /**
1425
+ * @generated from message public_api.v1.PanelLessonQuestion
1426
+ */
1427
+ type PanelLessonQuestion = Message<"public_api.v1.PanelLessonQuestion"> & {
1428
+ /**
1429
+ * @generated from field: string id = 1;
1430
+ */
1431
+ id: string;
1432
+ /**
1433
+ * @generated from field: string content = 2;
1434
+ */
1435
+ content: string;
1436
+ /**
1437
+ * Display name resolved by Bitsnap; empty for an anonymous customer.
1438
+ *
1439
+ * @generated from field: string author_name = 3;
1440
+ */
1441
+ authorName: string;
1442
+ /**
1443
+ * @generated from field: bool is_mine = 4;
1444
+ */
1445
+ isMine: boolean;
1446
+ /**
1447
+ * @generated from field: google.protobuf.Timestamp created_at = 5;
1448
+ */
1449
+ createdAt?: Timestamp;
1450
+ /**
1451
+ * Unset until the course team answers.
1452
+ *
1453
+ * @generated from field: optional public_api.v1.PanelQuestionAnswer answer = 6;
1454
+ */
1455
+ answer?: PanelQuestionAnswer;
1456
+ };
1457
+ /**
1458
+ * @generated from message public_api.v1.UserPanelListLessonQuestionsRequest
1459
+ */
1460
+ type UserPanelListLessonQuestionsRequest = Message<"public_api.v1.UserPanelListLessonQuestionsRequest"> & {
1461
+ /**
1462
+ * @generated from field: string access_token = 1;
1463
+ */
1464
+ accessToken: string;
1465
+ /**
1466
+ * @generated from field: string access_id = 2;
1467
+ */
1468
+ accessId: string;
1469
+ /**
1470
+ * @generated from field: string lesson_id = 3;
1471
+ */
1472
+ lessonId: string;
1473
+ };
1474
+ /**
1475
+ * Describes the message public_api.v1.UserPanelListLessonQuestionsRequest.
1476
+ * Use `create(UserPanelListLessonQuestionsRequestSchema)` to create a new message.
1477
+ */
1478
+ declare const UserPanelListLessonQuestionsRequestSchema: GenMessage<UserPanelListLessonQuestionsRequest>;
1479
+ /**
1480
+ * @generated from message public_api.v1.UserPanelListLessonQuestionsResponse
1481
+ */
1482
+ type UserPanelListLessonQuestionsResponse = Message<"public_api.v1.UserPanelListLessonQuestionsResponse"> & {
1483
+ /**
1484
+ * @generated from oneof public_api.v1.UserPanelListLessonQuestionsResponse.result
1485
+ */
1486
+ result: {
1487
+ /**
1488
+ * @generated from field: public_api.v1.UserPanelListLessonQuestionsResponse.Result success = 1;
1489
+ */
1490
+ value: UserPanelListLessonQuestionsResponse_Result;
1491
+ case: "success";
1492
+ } | {
1493
+ /**
1494
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
1495
+ */
1496
+ value: PanelCourseFailure;
1497
+ case: "failure";
1498
+ } | {
1499
+ case: undefined;
1500
+ value?: undefined;
1501
+ };
1502
+ };
1503
+ /**
1504
+ * Describes the message public_api.v1.UserPanelListLessonQuestionsResponse.
1505
+ * Use `create(UserPanelListLessonQuestionsResponseSchema)` to create a new message.
1506
+ */
1507
+ declare const UserPanelListLessonQuestionsResponseSchema: GenMessage<UserPanelListLessonQuestionsResponse>;
1508
+ /**
1509
+ * @generated from message public_api.v1.UserPanelListLessonQuestionsResponse.Result
1510
+ */
1511
+ type UserPanelListLessonQuestionsResponse_Result = Message<"public_api.v1.UserPanelListLessonQuestionsResponse.Result"> & {
1512
+ /**
1513
+ * Newest first.
1514
+ *
1515
+ * @generated from field: repeated public_api.v1.PanelLessonQuestion questions = 1;
1516
+ */
1517
+ questions: PanelLessonQuestion[];
1518
+ };
1519
+ /**
1520
+ * @generated from message public_api.v1.UserPanelAskLessonQuestionRequest
1521
+ */
1522
+ type UserPanelAskLessonQuestionRequest = Message<"public_api.v1.UserPanelAskLessonQuestionRequest"> & {
1523
+ /**
1524
+ * @generated from field: string access_token = 1;
1525
+ */
1526
+ accessToken: string;
1527
+ /**
1528
+ * @generated from field: string access_id = 2;
1529
+ */
1530
+ accessId: string;
1531
+ /**
1532
+ * @generated from field: string lesson_id = 3;
1533
+ */
1534
+ lessonId: string;
1535
+ /**
1536
+ * @generated from field: string content = 4;
1537
+ */
1538
+ content: string;
1539
+ };
1540
+ /**
1541
+ * Describes the message public_api.v1.UserPanelAskLessonQuestionRequest.
1542
+ * Use `create(UserPanelAskLessonQuestionRequestSchema)` to create a new message.
1543
+ */
1544
+ declare const UserPanelAskLessonQuestionRequestSchema: GenMessage<UserPanelAskLessonQuestionRequest>;
1545
+ /**
1546
+ * @generated from message public_api.v1.UserPanelAskLessonQuestionResponse
1547
+ */
1548
+ type UserPanelAskLessonQuestionResponse = Message<"public_api.v1.UserPanelAskLessonQuestionResponse"> & {
1549
+ /**
1550
+ * @generated from oneof public_api.v1.UserPanelAskLessonQuestionResponse.result
1551
+ */
1552
+ result: {
1553
+ /**
1554
+ * @generated from field: public_api.v1.PanelLessonQuestion success = 1;
1555
+ */
1556
+ value: PanelLessonQuestion;
1557
+ case: "success";
1558
+ } | {
1559
+ /**
1560
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
1561
+ */
1562
+ value: PanelCourseFailure;
1563
+ case: "failure";
1564
+ } | {
1565
+ case: undefined;
1566
+ value?: undefined;
1567
+ };
1568
+ };
1569
+ /**
1570
+ * Describes the message public_api.v1.UserPanelAskLessonQuestionResponse.
1571
+ * Use `create(UserPanelAskLessonQuestionResponseSchema)` to create a new message.
1572
+ */
1573
+ declare const UserPanelAskLessonQuestionResponseSchema: GenMessage<UserPanelAskLessonQuestionResponse>;
1574
+ /**
1575
+ * @generated from message public_api.v1.UserPanelRateLessonRequest
1576
+ */
1577
+ type UserPanelRateLessonRequest = Message<"public_api.v1.UserPanelRateLessonRequest"> & {
1578
+ /**
1579
+ * @generated from field: string access_token = 1;
1580
+ */
1581
+ accessToken: string;
1582
+ /**
1583
+ * @generated from field: string access_id = 2;
1584
+ */
1585
+ accessId: string;
1586
+ /**
1587
+ * @generated from field: string lesson_id = 3;
1588
+ */
1589
+ lessonId: string;
1590
+ /**
1591
+ * 1 to 5. Rating again replaces the previous rating.
1592
+ *
1593
+ * @generated from field: int32 score = 4;
1594
+ */
1595
+ score: number;
1596
+ /**
1597
+ * @generated from field: string comment = 5;
1598
+ */
1599
+ comment: string;
1600
+ };
1601
+ /**
1602
+ * Describes the message public_api.v1.UserPanelRateLessonRequest.
1603
+ * Use `create(UserPanelRateLessonRequestSchema)` to create a new message.
1604
+ */
1605
+ declare const UserPanelRateLessonRequestSchema: GenMessage<UserPanelRateLessonRequest>;
1606
+ /**
1607
+ * @generated from message public_api.v1.UserPanelRateLessonResponse
1608
+ */
1609
+ type UserPanelRateLessonResponse = Message<"public_api.v1.UserPanelRateLessonResponse"> & {
1610
+ /**
1611
+ * @generated from oneof public_api.v1.UserPanelRateLessonResponse.result
1612
+ */
1613
+ result: {
1614
+ /**
1615
+ * @generated from field: public_api.v1.UserPanelRateLessonResponse.Result success = 1;
1616
+ */
1617
+ value: UserPanelRateLessonResponse_Result;
1618
+ case: "success";
1619
+ } | {
1620
+ /**
1621
+ * @generated from field: public_api.v1.PanelCourseFailure failure = 2;
1622
+ */
1623
+ value: PanelCourseFailure;
1624
+ case: "failure";
1625
+ } | {
1626
+ case: undefined;
1627
+ value?: undefined;
1628
+ };
1629
+ };
1630
+ /**
1631
+ * Describes the message public_api.v1.UserPanelRateLessonResponse.
1632
+ * Use `create(UserPanelRateLessonResponseSchema)` to create a new message.
1633
+ */
1634
+ declare const UserPanelRateLessonResponseSchema: GenMessage<UserPanelRateLessonResponse>;
1635
+ /**
1636
+ * @generated from message public_api.v1.UserPanelRateLessonResponse.Result
1637
+ */
1638
+ type UserPanelRateLessonResponse_Result = Message<"public_api.v1.UserPanelRateLessonResponse.Result"> & {
1639
+ /**
1640
+ * @generated from field: int32 my_rating = 1;
1641
+ */
1642
+ myRating: number;
1643
+ /**
1644
+ * @generated from field: float average_rating = 2;
1645
+ */
1646
+ averageRating: number;
1647
+ /**
1648
+ * @generated from field: int32 rating_count = 3;
1649
+ */
1650
+ ratingCount: number;
1651
+ };
1652
+ /**
1653
+ * @generated from enum public_api.v1.PanelCourseFailure
1654
+ */
1655
+ declare enum PanelCourseFailure {
1656
+ /**
1657
+ * @generated from enum value: PANEL_COURSE_FAILURE_UNKNOWN = 0;
1658
+ */
1659
+ UNKNOWN = 0,
1660
+ /**
1661
+ * Missing, expired or foreign access token, or no paid access to access_id.
1662
+ *
1663
+ * @generated from enum value: PANEL_COURSE_FAILURE_UNAUTHORIZED = 1;
1664
+ */
1665
+ UNAUTHORIZED = 1,
1666
+ /**
1667
+ * @generated from enum value: PANEL_COURSE_FAILURE_COURSE_NOT_FOUND = 2;
1668
+ */
1669
+ COURSE_NOT_FOUND = 2,
1670
+ /**
1671
+ * Unknown lesson or test (or one of another course).
1672
+ *
1673
+ * @generated from enum value: PANEL_COURSE_FAILURE_ITEM_NOT_FOUND = 3;
1674
+ */
1675
+ ITEM_NOT_FOUND = 3,
1676
+ /**
1677
+ * The item is locked by a gating test (see PanelCourseItem.lock_reason).
1678
+ *
1679
+ * @generated from enum value: PANEL_COURSE_FAILURE_ITEM_LOCKED = 4;
1680
+ */
1681
+ ITEM_LOCKED = 4,
1682
+ /**
1683
+ * SubmitTest after the last allowed attempt.
1684
+ *
1685
+ * @generated from enum value: PANEL_COURSE_FAILURE_NO_ATTEMPTS_LEFT = 5;
1686
+ */
1687
+ NO_ATTEMPTS_LEFT = 5,
1688
+ /**
1689
+ * Malformed request, e.g. an answer to an unknown question, a rating out of
1690
+ * 1..5 or an empty question.
1691
+ *
1692
+ * @generated from enum value: PANEL_COURSE_FAILURE_INVALID_ARGUMENT = 6;
1693
+ */
1694
+ INVALID_ARGUMENT = 6,
1695
+ /**
1696
+ * @generated from enum value: PANEL_COURSE_FAILURE_RATE_LIMITED = 7;
1697
+ */
1698
+ RATE_LIMITED = 7,
1699
+ /**
1700
+ * LMS is not reachable. The client may retry.
1701
+ *
1702
+ * @generated from enum value: PANEL_COURSE_FAILURE_UNAVAILABLE = 8;
1703
+ */
1704
+ UNAVAILABLE = 8
1705
+ }
1706
+ /**
1707
+ * @generated from enum public_api.v1.PanelCourseType
1708
+ */
1709
+ declare enum PanelCourseType {
1710
+ /**
1711
+ * @generated from enum value: PANEL_COURSE_TYPE_UNKNOWN = 0;
1712
+ */
1713
+ UNKNOWN = 0,
1714
+ /**
1715
+ * Modules of lessons with HTML content, an optional video, attachments and
1716
+ * tests.
1717
+ *
1718
+ * @generated from enum value: PANEL_COURSE_TYPE_STANDARD = 1;
1719
+ */
1720
+ STANDARD = 1,
1721
+ /**
1722
+ * Sections of videos: a lesson is a video with a description, a thumbnail and
1723
+ * attachments.
1724
+ *
1725
+ * @generated from enum value: PANEL_COURSE_TYPE_VIDEO = 2;
1726
+ */
1727
+ VIDEO = 2
1728
+ }
1729
+ /**
1730
+ * @generated from enum public_api.v1.PanelCourseItemKind
1731
+ */
1732
+ declare enum PanelCourseItemKind {
1733
+ /**
1734
+ * @generated from enum value: PANEL_COURSE_ITEM_KIND_UNKNOWN = 0;
1735
+ */
1736
+ UNKNOWN = 0,
1737
+ /**
1738
+ * @generated from enum value: PANEL_COURSE_ITEM_KIND_LESSON = 1;
1739
+ */
1740
+ LESSON = 1,
1741
+ /**
1742
+ * @generated from enum value: PANEL_COURSE_ITEM_KIND_TEST = 2;
1743
+ */
1744
+ TEST = 2
1745
+ }
1746
+ /**
1747
+ * Course view of the customer panel (`bitsnap-react/course`).
1748
+ *
1749
+ * DRAFT. The panel talks only to Bitsnap's /api/rpc. Bitsnap checks the paid
1750
+ * access of the customer on every call, calls the internal LMS server to
1751
+ * server and returns content with URLs that are already signed:
1752
+ * - attachments: presigned S3 URLs,
1753
+ * - video: a Cloudflare Stream HLS manifest URL with a signed token.
1754
+ * The client never sees LMS ids or LMS credentials.
1755
+ *
1756
+ * Authentication follows the other UserPanel* calls (UserPanelGetCourseDetails,
1757
+ * UserPanelGetFileDetails): `access_token` is the panel session token and
1758
+ * `access_id` is UserProduct.access_id of the purchased course. The course is
1759
+ * resolved on the server from `access_id`, so there is no project_id and no
1760
+ * course_id in the requests. All other ids are opaque strings returned by
1761
+ * GetCourse.
1762
+ *
1763
+ * Every response is `oneof result { success, failure }` like the other panel
1764
+ * calls. Gateway level errors (network, 5xx) surface as Connect errors.
1765
+ *
1766
+ * @generated from service public_api.v1.UserPanelCourseService
1767
+ */
1768
+ declare const UserPanelCourseService: GenService<{
1769
+ /**
1770
+ * Course structure with the progress of the customer.
1771
+ *
1772
+ * @generated from rpc public_api.v1.UserPanelCourseService.GetCourse
1773
+ */
1774
+ getCourse: {
1775
+ methodKind: "unary";
1776
+ input: typeof UserPanelGetCourseRequestSchema;
1777
+ output: typeof UserPanelGetCourseResponseSchema;
1778
+ };
1779
+ /**
1780
+ * One lesson: content, signed video and attachment URLs.
1781
+ *
1782
+ * @generated from rpc public_api.v1.UserPanelCourseService.GetLesson
1783
+ */
1784
+ getLesson: {
1785
+ methodKind: "unary";
1786
+ input: typeof UserPanelGetLessonRequestSchema;
1787
+ output: typeof UserPanelGetLessonResponseSchema;
1788
+ };
1789
+ /**
1790
+ * Reports the playback position and/or completion of a lesson.
1791
+ *
1792
+ * @generated from rpc public_api.v1.UserPanelCourseService.SaveLessonProgress
1793
+ */
1794
+ saveLessonProgress: {
1795
+ methodKind: "unary";
1796
+ input: typeof UserPanelSaveLessonProgressRequestSchema;
1797
+ output: typeof UserPanelSaveLessonProgressResponseSchema;
1798
+ };
1799
+ /**
1800
+ * A test without the correct answers.
1801
+ *
1802
+ * @generated from rpc public_api.v1.UserPanelCourseService.GetTest
1803
+ */
1804
+ getTest: {
1805
+ methodKind: "unary";
1806
+ input: typeof UserPanelGetTestRequestSchema;
1807
+ output: typeof UserPanelGetTestResponseSchema;
1808
+ };
1809
+ /**
1810
+ * @generated from rpc public_api.v1.UserPanelCourseService.SubmitTest
1811
+ */
1812
+ submitTest: {
1813
+ methodKind: "unary";
1814
+ input: typeof UserPanelSubmitTestRequestSchema;
1815
+ output: typeof UserPanelSubmitTestResponseSchema;
1816
+ };
1817
+ /**
1818
+ * @generated from rpc public_api.v1.UserPanelCourseService.ListTestSubmissions
1819
+ */
1820
+ listTestSubmissions: {
1821
+ methodKind: "unary";
1822
+ input: typeof UserPanelListTestSubmissionsRequestSchema;
1823
+ output: typeof UserPanelListTestSubmissionsResponseSchema;
1824
+ };
1825
+ /**
1826
+ * @generated from rpc public_api.v1.UserPanelCourseService.ListLessonQuestions
1827
+ */
1828
+ listLessonQuestions: {
1829
+ methodKind: "unary";
1830
+ input: typeof UserPanelListLessonQuestionsRequestSchema;
1831
+ output: typeof UserPanelListLessonQuestionsResponseSchema;
1832
+ };
1833
+ /**
1834
+ * @generated from rpc public_api.v1.UserPanelCourseService.AskLessonQuestion
1835
+ */
1836
+ askLessonQuestion: {
1837
+ methodKind: "unary";
1838
+ input: typeof UserPanelAskLessonQuestionRequestSchema;
1839
+ output: typeof UserPanelAskLessonQuestionResponseSchema;
1840
+ };
1841
+ /**
1842
+ * @generated from rpc public_api.v1.UserPanelCourseService.RateLesson
1843
+ */
1844
+ rateLesson: {
1845
+ methodKind: "unary";
1846
+ input: typeof UserPanelRateLessonRequestSchema;
1847
+ output: typeof UserPanelRateLessonResponseSchema;
1848
+ };
1849
+ }>;
1850
+
1851
+ /** The part of the generated Connect client the data source calls. */
1852
+ type CourseRpcClient = Client<typeof UserPanelCourseService>;
1853
+ type CourseAuth = {
1854
+ /** `UserProduct.access_id` of the purchased course. */
1855
+ accessId: string;
1856
+ /** Panel session token; a function is read on every call. */
1857
+ accessToken: string | (() => string | undefined);
1858
+ };
1859
+ /**
1860
+ * Data source over `UserPanelCourseService`. Every call carries the access id
1861
+ * and the panel session token; failures become `CourseError`.
1862
+ */
1863
+ declare function createCourseDataSource(client: CourseRpcClient, auth: CourseAuth): CourseDataSource;
1864
+
1865
+ /**
1866
+ * Sanitizes the HTML of a lesson with the DOM of the browser. Returns an empty
1867
+ * string when there is no DOM, so call it on the client (inside an effect or
1868
+ * `useMemo` of a component that only renders content after loading).
1869
+ */
1870
+ declare function sanitizeLessonHtml(html: string | null | undefined): string;
1871
+
1872
+ export { COURSE_TEXT_TABLES, type Course, type CourseDataSource, CourseError, type CourseErrorCode, type CourseItem, type CourseItemKind, type CourseSection, type CourseTexts, type CourseType, type ItemRef, type Lesson, type LessonAttachment, type LessonQuestion, type LessonRating, type LessonVideo, type LockReason, PanelCourse$1 as PanelCourse, type PanelCourseProps, type ProgressSaved, type QuestionAnswer, type QuestionResult, type RpcCourseDataSourceOptions, type SaveProgressInput, type Test, type TestAnswers, type TestChoice, type TestQuestion, type TestQuestionConfig, type TestResult, type TestSubmission, type TestSubmissionList, createCourseDataSource, createRpcCourseDataSource, getCourseTexts, sanitizeLessonHtml };