@vue-skuilder/common-ui 0.1.11 → 0.1.12

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.
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthStore.d.ts","sourceRoot":"","sources":["../../src/stores/useAuthStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGjE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,eAAe,GAAG,SAAS,CAAC;IACnC,oBAAoB,EAAE;QACpB,IAAI,EAAE,OAAO,CAAC;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAiB/D;AAED,eAAO,MAAM,YAAY;;;;gDA4Ei3Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;kBAvGvoX,OAAO;sBACH,OAAO;2BACF,OAAO;6BACL,OAAO;;wBAEV,OAAO;;;;gDAkGi3Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;kBAvGvoX,OAAO;sBACH,OAAO;2BACF,OAAO;6BACL,OAAO;;wBAEV,OAAO;;;;gDAkGi3Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;kBAvGvoX,OAAO;sBACH,OAAO;2BACF,OAAO;6BACL,OAAO;;wBAEV,OAAO;;;;;gDAkGi3Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;;;yBA1CtnX,OAAO;uBAIT,OAAO;;;;;EAqC/B,CAAC"}
1
+ {"version":3,"file":"useAuthStore.d.ts","sourceRoot":"","sources":["../../src/stores/useAuthStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGjE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,eAAe,GAAG,SAAS,CAAC;IACnC,oBAAoB,EAAE;QACpB,IAAI,EAAE,OAAO,CAAC;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAiB/D;AAED,eAAO,MAAM,YAAY;;;;gDA4Eo8Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;kBAvG1tX,OAAO;sBACH,OAAO;2BACF,OAAO;6BACL,OAAO;;wBAEV,OAAO;;;;gDAkGo8Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;kBAvG1tX,OAAO;sBACH,OAAO;2BACF,OAAO;6BACL,OAAO;;wBAEV,OAAO;;;;gDAkGo8Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;kBAvG1tX,OAAO;sBACH,OAAO;2BACF,OAAO;6BACL,OAAO;;wBAEV,OAAO;;;;;gDAkGo8Q,QAAS,IAAI,CAAC,cAAc;;;;;;;;;;;;;;;;oFAAqpD,QAAQ,IAAI,CAAC,QAAQ;2EAAoH,QAAQ,IAAI,CAAC,QAAQ;;;;;;;;;;qHAAkjB,QAAQ,IAAI,CAAC,QAAQ;4DAAmG,QAAQ,IAAI,CAAC,QAAQ;wGAA6H,QAAQ,IAAI,CAAC,QAAQ;;;qBAAkL,CAAC;;+BAA5yG,QAAS,IAAI,CAAC,QAAQ;;;;;;;oBAAirH,CAAC;qBAAuB,CAAC;;;;;;;;;yBA1CzsX,OAAO;uBAIT,OAAO;;;;;EAqC/B,CAAC"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.1.11",
6
+ "version": "0.1.12",
7
7
  "main": "./dist/common-ui.umd.js",
8
8
  "module": "./dist/common-ui.es.js",
9
9
  "types": "./dist/index.d.ts",
@@ -34,8 +34,8 @@
34
34
  "@highlightjs/vue-plugin": "^2.1.2",
35
35
  "@mdi/font": "^7.3.67",
36
36
  "@vojtechlanka/vue-tags-input": "^3",
37
- "@vue-skuilder/common": "0.1.11",
38
- "@vue-skuilder/db": "0.1.11",
37
+ "@vue-skuilder/common": "0.1.12",
38
+ "@vue-skuilder/db": "0.1.12",
39
39
  "highlight.js": "^11.0.1",
40
40
  "marked": "^15.0.6",
41
41
  "moment": "^2.29.4",
@@ -70,5 +70,5 @@
70
70
  "vite": "^6.0.9",
71
71
  "vitest": "^3.0.5"
72
72
  },
73
- "stableVersion": "0.1.11"
73
+ "stableVersion": "0.1.12"
74
74
  }
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div v-if="sessionPrepared" class="StudySession">
3
3
  <v-row align="center">
4
- <h1 class="text-h3" v-if="courseNames[courseID]">{{ courseNames[courseID] }}:</h1>
4
+ <!-- <h1 class="text-h3" v-if="courseNames[courseID]">{{ courseNames[courseID] }}:</h1> -->
5
5
  <v-spacer></v-spacer>
6
6
  <v-progress-circular v-if="loading" color="primary" indeterminate size="32" width="4" />
7
7
  </v-row>
@@ -11,16 +11,17 @@
11
11
  <div v-if="sessionFinished" class="text-h4">
12
12
  <p>Study session finished! Great job!</p>
13
13
  <p v-if="sessionController">{{ sessionController.report }}</p>
14
- <p>
14
+ <!-- <p>
15
15
  Start <a @click="$emit('session-finished')">another study session</a>, or try
16
16
  <router-link :to="`/edit/${courseID}`">adding some new content</router-link> to challenge yourself and others!
17
- </p>
17
+ </p> -->
18
18
  <heat-map :activity-records-getter="() => user.getActivityRecords()" />
19
19
  </div>
20
20
 
21
21
  <div v-else ref="shadowWrapper">
22
22
  <card-viewer
23
23
  ref="cardViewer"
24
+ :key="cardID"
24
25
  :class="loading ? 'muted' : ''"
25
26
  :view="view"
26
27
  :data="data"
@@ -65,35 +66,35 @@
65
66
  </template>
66
67
 
67
68
  <script lang="ts">
68
- import { defineComponent, PropType, markRaw } from 'vue';
69
- import { isQuestionView } from '../composables/CompositionViewable';
70
- import { alertUser } from './SnackbarService';
69
+ import { defineComponent, markRaw, PropType } from 'vue';
71
70
  import { ViewComponent } from '../composables';
71
+ import { isQuestionView } from '../composables/CompositionViewable';
72
+ import HeatMap from './HeatMap.vue';
72
73
  import SkMouseTrap from './SkMouseTrap.vue';
74
+ import { alertUser } from './SnackbarService';
73
75
  import StudySessionTimer from './StudySessionTimer.vue';
74
- import HeatMap from './HeatMap.vue';
75
76
  import CardViewer from './cardRendering/CardViewer.vue';
76
77
 
78
+ import { CourseElo, Status, toCourseElo, ViewData } from '@vue-skuilder/common';
77
79
  import {
78
- ContentSourceID,
79
- getStudySource,
80
- isReview,
81
- StudyContentSource,
82
- StudySessionItem,
83
- docIsDeleted,
84
80
  CardHistory,
85
81
  CardRecord,
86
- isQuestionRecord,
82
+ ClassroomDBInterface,
83
+ ContentSourceID,
87
84
  CourseRegistrationDoc,
88
85
  DataLayerProvider,
86
+ docIsDeleted,
87
+ getStudySource,
88
+ HydratedCard,
89
+ isQuestionRecord,
90
+ isReview,
91
+ ResponseResult,
92
+ SessionController,
93
+ StudyContentSource,
94
+ StudySessionRecord,
89
95
  UserDBInterface,
90
- ClassroomDBInterface,
91
96
  } from '@vue-skuilder/db';
92
- import { HydratedCard, SessionController, StudySessionRecord } from '@vue-skuilder/db';
93
- import { newInterval } from '@vue-skuilder/db';
94
- import { adjustCourseScores, CourseElo, toCourseElo, ViewData, Status } from '@vue-skuilder/common';
95
97
  import confetti from 'canvas-confetti';
96
- import moment from 'moment';
97
98
 
98
99
  import { StudySessionConfig } from './StudySession.types';
99
100
 
@@ -371,140 +372,83 @@ export default defineComponent({
371
372
  this.currentCard.records.push(r);
372
373
 
373
374
  console.log(`[StudySession] StudySession.processResponse is running...`);
375
+ // DEBUG: Added logging to track hanging issue - can be removed if issue resolved
376
+ // console.log(`[StudySession] About to call logCardRecord...`);
374
377
  const cardHistory = this.logCardRecord(r);
378
+ // console.log(`[StudySession] logCardRecord called, cardHistory promise created...`);
379
+
380
+ // Get view constraints for response processing
381
+ let maxAttemptsPerView = 1;
382
+ let maxSessionViews = 1;
383
+ if (isQuestionView(this.$refs.cardViewer?.$refs.activeView)) {
384
+ const view = this.$refs.cardViewer.$refs.activeView;
385
+ maxAttemptsPerView = view.maxAttemptsPerView;
386
+ maxSessionViews = view.maxSessionViews;
387
+ }
388
+ const sessionViews = this.countCardViews(this.courseID, this.cardID);
389
+
390
+ // Process response through SessionController
391
+ // DEBUG: Added logging to track hanging issue - can be removed if issue resolved
392
+ // console.log(`[StudySession] About to call submitResponse...`);
393
+ const result: ResponseResult = await this.sessionController!.submitResponse(
394
+ r,
395
+ cardHistory,
396
+ this.userCourseRegDoc!,
397
+ this.currentCard,
398
+ this.courseID,
399
+ this.cardID,
400
+ maxAttemptsPerView,
401
+ maxSessionViews,
402
+ sessionViews
403
+ );
404
+ // DEBUG: Added logging to track hanging issue - can be removed if issue resolved
405
+ // console.log(`[StudySession] submitResponse completed, result:`, result);
406
+
407
+ // Handle UI feedback based on result
408
+ this.handleUIFeedback(result);
409
+
410
+ // Handle navigation based on result
411
+ if (result.shouldLoadNextCard) {
412
+ this.loadCard(await this.sessionController!.nextCard(result.nextCardAction));
413
+ }
375
414
 
376
- if (isQuestionRecord(r)) {
377
- console.log(`[StudySession] Question is ${r.isCorrect ? '' : 'in'}correct`);
378
- if (r.isCorrect) {
379
- try {
380
- if (this.$refs.shadowWrapper) {
381
- this.$refs.shadowWrapper.setAttribute(
382
- 'style',
383
- `--r: ${255 * (1 - (r.performance as number))}; --g:${255}`
384
- );
385
- this.$refs.shadowWrapper.classList.add('correct');
386
- }
387
- } catch (e) {
388
- // swallow error
389
- console.warn(`[StudySession] Error setting shadowWrapper style: ${e}`);
390
- }
391
-
392
- if (this.sessionConfig.likesConfetti) {
393
- confetti({
394
- origin: {
395
- y: 1,
396
- x: 0.25 + 0.5 * Math.random(),
397
- },
398
- disableForReducedMotion: true,
399
- angle: 60 + 60 * Math.random(),
400
- });
401
- }
415
+ // Clear feedback shadow if requested
416
+ if (result.shouldClearFeedbackShadow) {
417
+ this.clearFeedbackShadow();
418
+ }
419
+ },
402
420
 
403
- if (r.priorAttemps === 0) {
404
- const item: StudySessionItem = {
405
- ...this.currentCard.item,
406
- };
407
- this.loadCard(await this.sessionController!.nextCard('dismiss-success'));
408
-
409
- cardHistory.then((history: CardHistory<CardRecord>) => {
410
- this.scheduleReview(history, item);
411
- if (history.records.length === 1) {
412
- this.updateUserAndCardElo(0.5 + (r.performance as number) / 2, this.courseID, this.cardID);
413
- } else {
414
- const k = Math.ceil(32 / history.records.length);
415
- this.updateUserAndCardElo(0.5 + (r.performance as number) / 2, this.courseID, this.cardID, k);
416
- }
417
- });
418
- } else {
419
- this.loadCard(await this.sessionController!.nextCard('marked-failed'));
420
- }
421
- } else {
422
- /* !r.isCorrect */
423
- try {
424
- if (this.$refs.shadowWrapper) {
425
- this.$refs.shadowWrapper.classList.add('incorrect');
426
- }
427
- } catch (e) {
428
- // swallow error
429
- console.warn(`[StudySession] Error setting shadowWrapper style: ${e}`);
421
+ handleUIFeedback(result: ResponseResult) {
422
+ if (result.isCorrect) {
423
+ // Handle correct response UI
424
+ try {
425
+ if (this.$refs.shadowWrapper && result.performanceScore !== undefined) {
426
+ this.$refs.shadowWrapper.setAttribute('style', `--r: ${255 * (1 - result.performanceScore)}; --g:${255}`);
427
+ this.$refs.shadowWrapper.classList.add('correct');
430
428
  }
429
+ } catch (e) {
430
+ console.warn(`[StudySession] Error setting shadowWrapper style: ${e}`);
431
+ }
431
432
 
432
- cardHistory.then((history: CardHistory<CardRecord>) => {
433
- if (history.records.length !== 1 && r.priorAttemps === 0) {
434
- this.updateUserAndCardElo(0, this.courseID, this.cardID);
435
- }
433
+ // Show confetti for correct responses
434
+ if (this.sessionConfig.likesConfetti) {
435
+ confetti({
436
+ origin: {
437
+ y: 1,
438
+ x: 0.25 + 0.5 * Math.random(),
439
+ },
440
+ disableForReducedMotion: true,
441
+ angle: 60 + 60 * Math.random(),
436
442
  });
437
-
438
- // [ ] v3 version. Keep an eye on this -
439
- if (isQuestionView(this.$refs.cardViewer?.$refs.activeView)) {
440
- const view = this.$refs.cardViewer.$refs.activeView;
441
-
442
- if (this.currentCard.records.length >= view.maxAttemptsPerView) {
443
- const sessionViews: number = this.countCardViews(this.courseID, this.cardID);
444
- if (sessionViews >= view.maxSessionViews) {
445
- this.loadCard(await this.sessionController!.nextCard('dismiss-failed'));
446
- this.updateUserAndCardElo(0, this.courseID, this.cardID);
447
- } else {
448
- this.loadCard(await this.sessionController!.nextCard('marked-failed'));
449
- }
450
- }
451
- }
452
443
  }
453
444
  } else {
454
- this.loadCard(await this.sessionController!.nextCard('dismiss-success'));
455
- }
456
-
457
- this.clearFeedbackShadow();
458
- },
459
-
460
- async updateUserAndCardElo(userScore: number, course_id: string, card_id: string, k?: number) {
461
- if (k) {
462
- console.warn(`k value interpretation not currently implemented`);
463
- }
464
- const courseDB = this.dataLayer.getCourseDB(this.currentCard.card.course_id);
465
- const userElo = toCourseElo(this.userCourseRegDoc!.courses.find((c) => c.courseID === course_id)!.elo);
466
- const cardElo = (await courseDB.getCardEloData([this.currentCard.card.card_id]))[0];
467
-
468
- if (cardElo && userElo) {
469
- const eloUpdate = adjustCourseScores(userElo, cardElo, userScore);
470
- this.userCourseRegDoc!.courses.find((c) => c.courseID === course_id)!.elo = eloUpdate.userElo;
471
-
472
- const results = await Promise.allSettled([
473
- this.user!.updateUserElo(course_id, eloUpdate.userElo),
474
- courseDB.updateCardElo(card_id, eloUpdate.cardElo),
475
- ]);
476
-
477
- // Check the results of each operation
478
- const userEloStatus = results[0].status === 'fulfilled';
479
- const cardEloStatus = results[1].status === 'fulfilled';
480
-
481
- if (userEloStatus && cardEloStatus) {
482
- const user = results[0].value;
483
- const card = results[1].value;
484
-
485
- if (user.ok && card && card.ok) {
486
- console.log(
487
- `[StudySession] Updated ELOS:
488
- \tUser: ${JSON.stringify(eloUpdate.userElo)})
489
- \tCard: ${JSON.stringify(eloUpdate.cardElo)})
490
- `
491
- );
492
- }
493
- } else {
494
- // Log which operations succeeded and which failed
495
- console.log(
496
- `[StudySession] Partial ELO update:
497
- \tUser ELO update: ${userEloStatus ? 'SUCCESS' : 'FAILED'}
498
- \tCard ELO update: ${cardEloStatus ? 'SUCCESS' : 'FAILED'}`
499
- );
500
-
501
- if (!userEloStatus && results[0].status === 'rejected') {
502
- console.error('[StudySession] User ELO update error:', results[0].reason);
503
- }
504
-
505
- if (!cardEloStatus && results[1].status === 'rejected') {
506
- console.error('[StudySession] Card ELO update error:', results[1].reason);
445
+ // Handle incorrect response UI
446
+ try {
447
+ if (this.$refs.shadowWrapper) {
448
+ this.$refs.shadowWrapper.classList.add('incorrect');
507
449
  }
450
+ } catch (e) {
451
+ console.warn(`[StudySession] Error setting shadowWrapper style: ${e}`);
508
452
  }
509
453
  }
510
454
  },
@@ -523,26 +467,11 @@ export default defineComponent({
523
467
  },
524
468
 
525
469
  async logCardRecord(r: CardRecord): Promise<CardHistory<CardRecord>> {
526
- return await this.user!.putCardRecord(r);
527
- },
528
-
529
- async scheduleReview(history: CardHistory<CardRecord>, item: StudySessionItem) {
530
- const nextInterval = newInterval(this.$props.user, history);
531
- const nextReviewTime = moment.utc().add(nextInterval, 'seconds');
532
-
533
- if (isReview(item)) {
534
- console.log(`[StudySession] Removing previously scheduled review for: ${item.cardID}`);
535
- this.user!.removeScheduledCardReview(item.reviewID);
536
- }
537
-
538
- this.user!.scheduleCardReview({
539
- user: this.user!.getUsername(),
540
- course_id: history.courseID,
541
- card_id: history.cardID,
542
- time: nextReviewTime,
543
- scheduledFor: item.contentSourceType,
544
- schedulingAgentId: item.contentSourceID,
545
- });
470
+ // DEBUG: Added logging to track hanging issue - can be removed if issue resolved
471
+ // console.log(`[StudySession] About to call user.putCardRecord...`);
472
+ const result = await this.user!.putCardRecord(r);
473
+ // console.log(`[StudySession] user.putCardRecord completed`);
474
+ return result;
546
475
  },
547
476
 
548
477
  async loadCard(card: HydratedCard | null) {
@@ -84,7 +84,7 @@ export default defineComponent({
84
84
 
85
85
  async loadCard() {
86
86
  const qualified_id = this.qualified_id;
87
- console.log(`Card Loader displaying: ${qualified_id.courseID}-${qualified_id.cardID}`);
87
+ console.log(`Card Loader displaying: ${qualified_id.courseID}::${qualified_id.cardID}`);
88
88
 
89
89
  this.loading = true;
90
90
  const _courseID = qualified_id.courseID;