From 391cd291e1e450e0cf77b53730a8850a3e793269 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Tue, 8 Jul 2025 10:49:48 -0300 Subject: [PATCH 1/6] add auto-registration in sui context... standalone course deployments are de-facto full registration. visitors to these site are explicitly opting into interacting with the site. Differentiated from platform-ui where users select content from a broader menu --- packages/standalone-ui/src/main.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/standalone-ui/src/main.ts b/packages/standalone-ui/src/main.ts index 93dc7ce07..2c129e2e6 100644 --- a/packages/standalone-ui/src/main.ts +++ b/packages/standalone-ui/src/main.ts @@ -14,7 +14,7 @@ import * as directives from 'vuetify/directives'; import { aliases, mdi } from 'vuetify/iconsets/mdi'; // data layer -import { initializeDataLayer } from '@vue-skuilder/db'; +import { initializeDataLayer, getDataLayer } from '@vue-skuilder/db'; // auth store import { useAuthStore } from '@vue-skuilder/common-ui'; @@ -163,5 +163,28 @@ import config from '../skuilder.config.json'; await useAuthStore().init(); + // Auto-register user for the course in standalone mode + if (config.course) { + try { + const authStore = useAuthStore(); + const user = getDataLayer().getUserDB(); + + // Check if user is already registered for the course + const courseRegistrations = await user.getCourseRegistrationsDoc(); + const isRegistered = courseRegistrations.courses.some(c => c.courseID === config.course); + + if (!isRegistered) { + console.log(`[Standalone] Auto-registering user for course: ${config.course}`); + await user.registerForCourse(config.course, false); // non-preview mode + console.log(`[Standalone] Auto-registration completed for course: ${config.course}`); + } else { + console.log(`[Standalone] User already registered for course: ${config.course}`); + } + } catch (error) { + console.warn(`[Standalone] Failed to auto-register for course ${config.course}:`, error); + // Don't block app startup on registration failure + } + } + app.mount('#app'); })(); From 4d1c4f7b97829560d05c8a47f982c56f1d0b3738 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Tue, 8 Jul 2025 11:15:37 -0300 Subject: [PATCH 2/6] serialize moment objs before writing to pouch --- packages/db/src/core/types/user.ts | 10 ++++++++-- packages/db/src/impl/common/userDBHelpers.ts | 4 ++-- packages/db/src/impl/couch/index.ts | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/db/src/core/types/user.ts b/packages/db/src/core/types/user.ts index 0c5d3b7dd..01a93a122 100644 --- a/packages/db/src/core/types/user.ts +++ b/packages/db/src/core/types/user.ts @@ -48,13 +48,19 @@ export interface ScheduledCard { * * (Should probably be UTC adjusted so that performance is * not wonky across time zones) + * + * Note: Stored as ISO string for PouchDB serialization compatibility, + * but can be consumed as Moment objects via moment.utc(reviewTime) */ - reviewTime: Moment; + reviewTime: string | Moment; /** * The time at which this scheduled event was created. + * + * Note: Stored as ISO string for PouchDB serialization compatibility, + * but can be consumed as Moment objects via moment.utc(scheduledAt) */ - scheduledAt: Moment; + scheduledAt: string | Moment; /** * Classifying whether this card is scheduled on behalf of a diff --git a/packages/db/src/impl/common/userDBHelpers.ts b/packages/db/src/impl/common/userDBHelpers.ts index ecb76ad8e..55a6687fb 100644 --- a/packages/db/src/impl/common/userDBHelpers.ts +++ b/packages/db/src/impl/common/userDBHelpers.ts @@ -125,9 +125,9 @@ export function scheduleCardReviewLocal( void userDB.put({ _id: DocTypePrefixes[DocType.SCHEDULED_CARD] + review.time.format(REVIEW_TIME_FORMAT), cardId: review.card_id, - reviewTime: review.time, + reviewTime: review.time.toISOString(), courseId: review.course_id, - scheduledAt: now, + scheduledAt: now.toISOString(), scheduledFor: review.scheduledFor, schedulingAgentId: review.schedulingAgentId, }); diff --git a/packages/db/src/impl/couch/index.ts b/packages/db/src/impl/couch/index.ts index 793a2f65a..2477425e5 100644 --- a/packages/db/src/impl/couch/index.ts +++ b/packages/db/src/impl/couch/index.ts @@ -198,9 +198,9 @@ export function scheduleCardReview(review: { void getCouchUserDB(review.user).put({ _id: DocTypePrefixes[DocType.SCHEDULED_CARD] + review.time.format(REVIEW_TIME_FORMAT), cardId: review.card_id, - reviewTime: review.time, + reviewTime: review.time.toISOString(), courseId: review.course_id, - scheduledAt: now, + scheduledAt: now.toISOString(), scheduledFor: review.scheduledFor, schedulingAgentId: review.schedulingAgentId, }); From a6ebde14b48a3ac63f5cc2bc4a878b99fb1d2556 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Tue, 8 Jul 2025 11:15:49 -0300 Subject: [PATCH 3/6] all writes to writeDB --- packages/db/src/impl/common/BaseUserDB.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/db/src/impl/common/BaseUserDB.ts b/packages/db/src/impl/common/BaseUserDB.ts index 133361fcf..16ca73f84 100644 --- a/packages/db/src/impl/common/BaseUserDB.ts +++ b/packages/db/src/impl/common/BaseUserDB.ts @@ -964,10 +964,10 @@ Currently logged-in as ${this._username}.` scheduledFor: ScheduledCard['scheduledFor']; schedulingAgentId: ScheduledCard['schedulingAgentId']; }) { - return scheduleCardReviewLocal(this.remoteDB, review); + return scheduleCardReviewLocal(this.writeDB, review); } public async removeScheduledCardReview(reviewId: string): Promise { - return removeScheduledCardReviewLocal(this.remoteDB, reviewId); + return removeScheduledCardReviewLocal(this.writeDB, reviewId); } public async registerForClassroom( From b2021377c3f8d22ac2773efc79d3b9a785931ac4 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Tue, 8 Jul 2025 11:47:22 -0300 Subject: [PATCH 4/6] fix regDoc lookiup --- packages/standalone-ui/src/views/UserStatsView.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/standalone-ui/src/views/UserStatsView.vue b/packages/standalone-ui/src/views/UserStatsView.vue index f0d216cea..a41d9e1eb 100644 --- a/packages/standalone-ui/src/views/UserStatsView.vue +++ b/packages/standalone-ui/src/views/UserStatsView.vue @@ -57,8 +57,8 @@ onMounted(async () => { const courseDB = dataLayer.getCourseDB(courseId); // Try to get user's ELO profile for this course - const userRegistrations = await dataLayer.getUserDB(user.getUsername()).getCourseRegistrations(); - const courseReg = userRegistrations.find(reg => reg.courseID === courseId); + const userDB = dataLayer.getUserDB(); + const courseReg = await userDB.getCourseRegDoc(courseId); if (courseReg && courseReg.elo) { userElo.value = courseReg.elo; From 18451e572771500353d62ede31c599b5dab80401 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Tue, 8 Jul 2025 12:00:15 -0300 Subject: [PATCH 5/6] make source-course display conditional --- packages/common-ui/src/components/StudySession.vue | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/common-ui/src/components/StudySession.vue b/packages/common-ui/src/components/StudySession.vue index 8ebec2184..e48f42a65 100644 --- a/packages/common-ui/src/components/StudySession.vue +++ b/packages/common-ui/src/components/StudySession.vue @@ -1,13 +1,9 @@