musora-content-services 2.104.4 → 2.104.7
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/.claude/settings.local.json +3 -10
- package/.coderabbit.yaml +0 -0
- package/.editorconfig +0 -0
- package/.github/pull_request_template.md +0 -0
- package/.github/workflows/conventional-commits.yaml +0 -0
- package/.github/workflows/docs.js.yml +0 -0
- package/.github/workflows/node.js.yml +0 -0
- package/.prettierignore +0 -0
- package/.prettierrc +0 -0
- package/CHANGELOG.md +17 -0
- package/CLAUDE.md +0 -0
- package/README.md +0 -0
- package/babel.config.cjs +0 -0
- package/jest.config.js +0 -0
- package/jsdoc.json +0 -0
- package/package.json +1 -1
- package/src/constants/award-assets.js +0 -0
- package/src/contentMetaData.js +0 -0
- package/src/filterBuilder.js +0 -0
- package/src/infrastructure/http/HttpClient.ts +0 -0
- package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
- package/src/infrastructure/http/index.ts +0 -0
- package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
- package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
- package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
- package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
- package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
- package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
- package/src/lib/ads/monoid.ts +0 -0
- package/src/lib/ads/semigroup.ts +0 -0
- package/src/lib/brands.ts +0 -0
- package/src/lib/httpHelper.js +0 -0
- package/src/lib/lastUpdated.js +0 -0
- package/src/lib/sanity/filter.ts +13 -0
- package/src/lib/sanity/query.ts +0 -0
- package/src/services/api/types.js +0 -0
- package/src/services/api/types.ts +0 -0
- package/src/services/awards/award-callbacks.js +0 -0
- package/src/services/awards/internal/.indexignore +0 -0
- package/src/services/awards/internal/award-definitions.js +0 -0
- package/src/services/awards/internal/award-events.js +0 -0
- package/src/services/awards/internal/certificate-builder.js +0 -0
- package/src/services/awards/internal/completion-data-generator.js +0 -0
- package/src/services/awards/internal/content-progress-observer.js +0 -0
- package/src/services/awards/internal/image-utils.js +0 -0
- package/src/services/awards/internal/message-generator.js +0 -0
- package/src/services/awards/internal/types.js +0 -0
- package/src/services/awards/types.d.ts +0 -0
- package/src/services/awards/types.js +0 -0
- package/src/services/config.js +0 -0
- package/src/services/content/artist.ts +17 -25
- package/src/services/content/content.ts +0 -0
- package/src/services/content/genre.ts +17 -25
- package/src/services/content/instructor.ts +15 -23
- package/src/services/content-org/content-org.js +0 -0
- package/src/services/content-org/guided-courses.ts +0 -0
- package/src/services/content-org/learning-paths.ts +87 -37
- package/src/services/content-org/playlists-types.js +0 -0
- package/src/services/contentAggregator.js +0 -0
- package/src/services/contentLikes.js +0 -0
- package/src/services/contentProgress.js +0 -0
- package/src/services/dataContext.js +0 -0
- package/src/services/dateUtils.js +0 -0
- package/src/services/eventsAPI.js +0 -0
- package/src/services/forums/categories.ts +0 -0
- package/src/services/forums/forums.ts +0 -0
- package/src/services/forums/posts.ts +0 -0
- package/src/services/forums/threads.ts +0 -0
- package/src/services/forums/types.ts +0 -0
- package/src/services/gamification/awards.ts +0 -0
- package/src/services/gamification/gamification.js +0 -0
- package/src/services/imageSRCBuilder.js +0 -0
- package/src/services/imageSRCVerify.js +0 -0
- package/src/services/liveTesting.ts +0 -0
- package/src/services/permissions/PermissionsAdapter.ts +0 -0
- package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
- package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
- package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
- package/src/services/permissions/README.md +0 -0
- package/src/services/permissions/index.ts +0 -0
- package/src/services/progress-events.js +0 -0
- package/src/services/progress-row/method-card.js +38 -24
- package/src/services/recommendations.js +0 -0
- package/src/services/reporting/README.md +0 -0
- package/src/services/reporting/types.ts +0 -0
- package/src/services/sanity.js +8 -4
- package/src/services/sentry/.indexignore +0 -0
- package/src/services/sentry/index.ts +0 -0
- package/src/services/sync/.indexignore +0 -0
- package/src/services/sync/adapters/factory.ts +0 -0
- package/src/services/sync/adapters/lokijs.ts +0 -0
- package/src/services/sync/adapters/sqlite.ts +0 -0
- package/src/services/sync/concurrency-safety.ts +0 -0
- package/src/services/sync/context/index.ts +0 -0
- package/src/services/sync/context/providers/base.ts +0 -0
- package/src/services/sync/context/providers/connectivity.ts +0 -0
- package/src/services/sync/context/providers/durability.ts +0 -0
- package/src/services/sync/context/providers/index.ts +0 -0
- package/src/services/sync/context/providers/session.ts +0 -0
- package/src/services/sync/context/providers/tabs.ts +0 -0
- package/src/services/sync/context/providers/visibility.ts +0 -0
- package/src/services/sync/database/factory.ts +0 -0
- package/src/services/sync/errors/boundary.ts +0 -0
- package/src/services/sync/errors/index.ts +0 -0
- package/src/services/sync/fetch.ts +0 -0
- package/src/services/sync/index.ts +0 -0
- package/src/services/sync/manager.ts +0 -0
- package/src/services/sync/models/Base.ts +0 -0
- package/src/services/sync/models/ContentLike.ts +0 -0
- package/src/services/sync/models/ContentProgress.ts +0 -0
- package/src/services/sync/models/Practice.ts +0 -0
- package/src/services/sync/models/PracticeDayNote.ts +0 -0
- package/src/services/sync/models/UserAwardProgress.ts +0 -0
- package/src/services/sync/models/index.ts +0 -0
- package/src/services/sync/repositories/base.ts +0 -0
- package/src/services/sync/repositories/content-likes.ts +0 -0
- package/src/services/sync/repositories/content-progress.ts +0 -0
- package/src/services/sync/repositories/index.ts +0 -0
- package/src/services/sync/repositories/practice-day-notes.ts +0 -0
- package/src/services/sync/repositories/practices.ts +0 -0
- package/src/services/sync/repository-proxy.ts +0 -0
- package/src/services/sync/resolver.ts +0 -0
- package/src/services/sync/retry.ts +0 -0
- package/src/services/sync/run-scope.ts +0 -0
- package/src/services/sync/schema/index.ts +0 -0
- package/src/services/sync/serializers/index.ts +0 -0
- package/src/services/sync/serializers/model.ts +0 -0
- package/src/services/sync/serializers/raw.ts +0 -0
- package/src/services/sync/store/index.ts +0 -0
- package/src/services/sync/store/push-coalescer.ts +0 -0
- package/src/services/sync/store-configs.ts +0 -0
- package/src/services/sync/strategies/base.ts +0 -0
- package/src/services/sync/strategies/index.ts +0 -0
- package/src/services/sync/strategies/initial.ts +0 -0
- package/src/services/sync/strategies/polling.ts +0 -0
- package/src/services/sync/telemetry/index.ts +0 -0
- package/src/services/sync/telemetry/sampling.ts +0 -0
- package/src/services/sync/utils/event-emitter.ts +0 -0
- package/src/services/sync/utils/index.ts +0 -0
- package/src/services/sync/utils/throttle.ts +0 -0
- package/src/services/sync/utils/timers.ts +0 -0
- package/src/services/types.js +0 -0
- package/src/services/user/account.ts +0 -0
- package/src/services/user/chat.js +0 -0
- package/src/services/user/interests.js +0 -0
- package/src/services/user/management.js +0 -0
- package/src/services/user/memberships.ts +0 -0
- package/src/services/user/notifications.js +0 -0
- package/src/services/user/onboarding.ts +0 -0
- package/src/services/user/payments.ts +0 -0
- package/src/services/user/permissions.js +0 -0
- package/src/services/user/profile.js +0 -0
- package/src/services/user/sessions.js +0 -0
- package/src/services/user/types.d.ts +0 -0
- package/src/services/user/types.js +0 -0
- package/src/services/user/user-management-system.js +0 -0
- package/src/services/userActivity.js +0 -0
- package/test/HttpClient.test.js +0 -0
- package/test/awards/award-alacarte-observer.test.js +0 -0
- package/test/awards/award-auto-refresh.test.js +0 -0
- package/test/awards/award-calculations.test.js +0 -0
- package/test/awards/award-certificate-display.test.js +0 -0
- package/test/awards/award-collection-edge-cases.test.js +0 -0
- package/test/awards/award-collection-filtering.test.js +0 -0
- package/test/awards/award-exclusion-handling.test.js +0 -0
- package/test/awards/award-multi-lesson.test.js +0 -0
- package/test/awards/award-observer-integration.test.js +0 -0
- package/test/awards/award-query-messages.test.js +0 -0
- package/test/awards/award-user-collection.test.js +0 -0
- package/test/awards/duplicate-prevention.test.js +0 -0
- package/test/awards/helpers/completion-mock.js +0 -0
- package/test/awards/helpers/index.js +0 -0
- package/test/awards/helpers/mock-setup.js +0 -0
- package/test/awards/helpers/progress-emitter.js +0 -0
- package/test/awards/message-generator.test.js +0 -0
- package/test/content.test.js +0 -0
- package/test/contentLikes.test.js +0 -0
- package/test/contentProgress.test.js +0 -0
- package/test/dataContext.test.js +0 -0
- package/test/forum.test.js +0 -0
- package/test/imageSRCBuilder.test.js +0 -0
- package/test/imageSRCVerify.test.js +0 -0
- package/test/initializeTests.js +0 -0
- package/test/learningPaths.test.js +0 -0
- package/test/lib/__snapshots__/filter.test.ts.snap +0 -0
- package/test/lib/filter.test.ts +0 -0
- package/test/lib/lastUpdated.test.js +0 -0
- package/test/lib/query.test.ts +0 -0
- package/test/live/contentProgressLive.test.js +0 -0
- package/test/live/railcontentLive.test.js +0 -0
- package/test/localStorageMock.js +0 -0
- package/test/log.js +0 -0
- package/test/mockData/award-definitions.js +0 -0
- package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
- package/test/mockData/mockData_progress_content.json +0 -0
- package/test/mockData/mockData_sanity_progress_content.json +0 -0
- package/test/mockData/mockData_user_practices.json +0 -0
- package/test/notifications.test.js +0 -0
- package/test/progressRows.test.js +0 -0
- package/test/sanityQueryService.test.js +0 -0
- package/test/streakMessage.test.js +0 -0
- package/test/sync/adapter.ts +0 -0
- package/test/sync/initialize-sync-manager.js +0 -0
- package/test/sync/models/award-database-integration.test.js +0 -0
- package/test/user/permissions.test.js +0 -0
- package/test/userActivity.test.js +0 -0
- package/tools/generate-index.cjs +0 -0
- package/.yarnrc.yml +0 -1
- package/check_content.js +0 -30
- package/check_content.mjs +0 -32
- package/test/reporting.test.js +0 -132
- package/test_owned_navigate.js +0 -74
|
@@ -72,7 +72,7 @@ export async function getDailySession(brand: string, userDate: Date) {
|
|
|
72
72
|
export async function updateDailySession(
|
|
73
73
|
brand: string,
|
|
74
74
|
userDate: Date,
|
|
75
|
-
keepFirstLearningPath: boolean
|
|
75
|
+
keepFirstLearningPath: boolean = false
|
|
76
76
|
) {
|
|
77
77
|
const stringDate = userDate.toISOString().split('T')[0]
|
|
78
78
|
const url: string = `${LEARNING_PATHS_PATH}/daily-session/create`
|
|
@@ -194,6 +194,23 @@ export function mapContentToParent(lessons, parentContentType, parentContentId)
|
|
|
194
194
|
})
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
interface fetchLearningPathLessonsResponse {
|
|
198
|
+
id: number
|
|
199
|
+
thumbnail?: string
|
|
200
|
+
title: string
|
|
201
|
+
children: any[]
|
|
202
|
+
is_active_learning_path: boolean
|
|
203
|
+
active_learning_path_id?: number
|
|
204
|
+
active_learning_path_created_at?: string
|
|
205
|
+
upcoming_lessons?: any[]
|
|
206
|
+
completed_lessons?: any[]
|
|
207
|
+
learning_path_dailies?: any[]
|
|
208
|
+
next_learning_path_dailies?: any[]
|
|
209
|
+
next_learning_path_id?: number
|
|
210
|
+
previous_learning_path_dailies?: any[]
|
|
211
|
+
previous_learning_path_id?: number
|
|
212
|
+
}
|
|
213
|
+
|
|
197
214
|
/** Fetches and organizes learning path lessons.
|
|
198
215
|
*
|
|
199
216
|
* @param {number} learningPathId - The learning path ID.
|
|
@@ -203,13 +220,17 @@ export function mapContentToParent(lessons, parentContentType, parentContentId)
|
|
|
203
220
|
* @returns {number} result.id - The learning path ID.
|
|
204
221
|
* @returns {string} result.thumbnail - Optional thumbnail URL for the learning path.
|
|
205
222
|
* @returns {string} result.title - The title of the learning path.
|
|
206
|
-
* @returns {boolean} result.is_active_learning_path - Whether the learning path is currently active.
|
|
207
223
|
* @returns {Array} result.children - Array of all lessons.
|
|
208
|
-
* @returns {
|
|
209
|
-
* @returns {
|
|
210
|
-
* @returns {
|
|
211
|
-
* @returns {Array} result.
|
|
212
|
-
* @returns {Array} result.
|
|
224
|
+
* @returns {boolean} result.is_active_learning_path - Whether the learning path is currently active.
|
|
225
|
+
* @returns {number} result.active_learning_path_id - The active learning path ID from daily session.
|
|
226
|
+
* @returns {string} result.active_learning_path_created_at - The datetime the learning path was set as active.
|
|
227
|
+
* @returns {Array} result.upcoming_lessons - Array of upcoming lessons.
|
|
228
|
+
* @returns {Array} result.learning_path_dailies - Array of today's dailies in this learning path.
|
|
229
|
+
* @returns {Array} result.next_learning_path_dailies - Array of today's dailies in the next learning path.
|
|
230
|
+
* @returns {number} result.next_learning_path_id - the next learning path (after the active path).
|
|
231
|
+
* @returns {Array} result.completed_lessons - Array of completed lessons in this learning path.
|
|
232
|
+
* @returns {Array} result.previous_learning_path_dailies - Array of today's dailies in the previous learning path.
|
|
233
|
+
* @returns {number} result.previous_learning_path_id - the previous learning path (before the active path)
|
|
213
234
|
*/
|
|
214
235
|
export async function fetchLearningPathLessons(
|
|
215
236
|
learningPathId: number,
|
|
@@ -217,9 +238,9 @@ export async function fetchLearningPathLessons(
|
|
|
217
238
|
userDate: Date
|
|
218
239
|
) {
|
|
219
240
|
const learningPath = await getEnrichedLearningPath(learningPathId)
|
|
220
|
-
let dailySession = await getDailySession(brand, userDate)
|
|
241
|
+
let dailySession = await getDailySession(brand, userDate) as DailySessionResponse // what if the call just fails, and a DS does exist?
|
|
221
242
|
if (!dailySession) {
|
|
222
|
-
dailySession = await updateDailySession(brand, userDate, false)
|
|
243
|
+
dailySession = await updateDailySession(brand, userDate, false) as DailySessionResponse
|
|
223
244
|
}
|
|
224
245
|
|
|
225
246
|
const isActiveLearningPath = (dailySession?.active_learning_path_id || 0) == learningPathId
|
|
@@ -227,48 +248,64 @@ export async function fetchLearningPathLessons(
|
|
|
227
248
|
return {
|
|
228
249
|
...learningPath,
|
|
229
250
|
is_active_learning_path: isActiveLearningPath,
|
|
230
|
-
}
|
|
251
|
+
} as fetchLearningPathLessonsResponse
|
|
231
252
|
}
|
|
232
|
-
// this assumes that the first entry is active_path, based on user flows
|
|
233
|
-
const todayContentIds = dailySession.daily_session[0]?.content_ids || []
|
|
234
|
-
const todayLearningPathId = dailySession.daily_session[0]?.learning_path_id
|
|
235
253
|
|
|
236
|
-
|
|
237
|
-
|
|
254
|
+
let todayContentIds = []
|
|
255
|
+
let todayLearningPathId = null
|
|
256
|
+
let nextContentIds = []
|
|
257
|
+
let nextLearningPathId = null
|
|
258
|
+
let previousContentIds = []
|
|
259
|
+
let previousLearningPathId = null
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
for (const session of dailySession.daily_session) {
|
|
264
|
+
if (session.learning_path_id === learningPathId) {
|
|
265
|
+
todayContentIds = session.content_ids || []
|
|
266
|
+
todayLearningPathId = session.learning_path_id
|
|
267
|
+
} else {
|
|
268
|
+
if (!todayLearningPathId) {
|
|
269
|
+
previousContentIds = session.content_ids || []
|
|
270
|
+
previousLearningPathId = session.learning_path_id
|
|
271
|
+
} else if (!nextLearningPathId) {
|
|
272
|
+
nextContentIds = session.content_ids || []
|
|
273
|
+
nextLearningPathId = session.learning_path_id
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
238
277
|
|
|
239
278
|
const completedLessons = []
|
|
240
279
|
let thisLPDailies = []
|
|
241
280
|
let nextLPDailies = []
|
|
242
|
-
let
|
|
281
|
+
let previousLPDailies = []
|
|
243
282
|
const upcomingLessons = []
|
|
244
283
|
|
|
284
|
+
//previous/next never within LP
|
|
245
285
|
learningPath.children.forEach((lesson: any) => {
|
|
246
286
|
if (todayContentIds.includes(lesson.id)) {
|
|
247
287
|
thisLPDailies.push(lesson)
|
|
248
|
-
} else if (lesson.progressStatus ===
|
|
288
|
+
} else if (lesson.progressStatus === STATE.COMPLETED) {
|
|
249
289
|
completedLessons.push(lesson)
|
|
250
290
|
} else {
|
|
251
291
|
upcomingLessons.push(lesson)
|
|
252
292
|
}
|
|
253
293
|
})
|
|
254
294
|
|
|
255
|
-
if (
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
todayContentIds,
|
|
260
|
-
todayLearningPathId
|
|
295
|
+
if (previousContentIds.length !== 0) {
|
|
296
|
+
previousLPDailies = await getLearningPathLessonsByIds(
|
|
297
|
+
previousContentIds,
|
|
298
|
+
previousLearningPathId
|
|
261
299
|
)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
nextLPDailies = lessons.map(lesson => ({
|
|
300
|
+
}
|
|
301
|
+
if (nextContentIds.length !== 0) {
|
|
302
|
+
nextLPDailies = await getLearningPathLessonsByIds(
|
|
303
|
+
nextContentIds,
|
|
304
|
+
nextLearningPathId
|
|
305
|
+
).then(lessons => lessons.map(lesson => ({
|
|
269
306
|
...lesson,
|
|
270
|
-
in_next_learning_path:
|
|
271
|
-
}))
|
|
307
|
+
in_next_learning_path: learningPath.progressStatus === STATE.COMPLETED
|
|
308
|
+
})))
|
|
272
309
|
}
|
|
273
310
|
|
|
274
311
|
return {
|
|
@@ -277,11 +314,12 @@ export async function fetchLearningPathLessons(
|
|
|
277
314
|
active_learning_path_id: dailySession?.active_learning_path_id,
|
|
278
315
|
active_learning_path_created_at: dailySession?.active_learning_path_created_at,
|
|
279
316
|
upcoming_lessons: upcomingLessons,
|
|
280
|
-
todays_lessons: thisLPDailies,
|
|
281
|
-
next_learning_path_lessons: nextLPDailies,
|
|
282
|
-
next_learning_path_id: nextLearningPathId,
|
|
283
317
|
completed_lessons: completedLessons,
|
|
284
|
-
|
|
318
|
+
learning_path_dailies: thisLPDailies,
|
|
319
|
+
next_learning_path_dailies: nextLPDailies,
|
|
320
|
+
next_learning_path_id: nextLearningPathId,
|
|
321
|
+
previous_learning_path_dailies: previousLPDailies,
|
|
322
|
+
previous_learning_path_id: previousLearningPathId,
|
|
285
323
|
}
|
|
286
324
|
}
|
|
287
325
|
|
|
@@ -341,12 +379,14 @@ interface completeLearningPathIntroVideo {
|
|
|
341
379
|
intro_video_response: SyncWriteDTO<ContentProgress, any> | null
|
|
342
380
|
learning_path_reset_response: SyncWriteDTO<ContentProgress, any> | null
|
|
343
381
|
lesson_import_response: SyncWriteDTO<ContentProgress, any> | null
|
|
382
|
+
update_dailies_response: DailySessionResponse | null
|
|
344
383
|
}
|
|
345
384
|
/**
|
|
346
385
|
* Handles completion of learning path intro video and other related actions.
|
|
347
386
|
* @param introVideoId - The learning path intro video content ID.
|
|
348
387
|
* @param learningPathId - The content_id of the learning path that this learning path intro video belongs to.
|
|
349
388
|
* @param lessonsToImport - content ids for all lessons with progress found during intro video progress check. empty if user chose not to keep learning path progress.
|
|
389
|
+
* @param brand
|
|
350
390
|
* @returns {Promise<Array>} response - The response object.
|
|
351
391
|
* @returns {Promise<Object|null>} response.intro_video_response - The intro video completion response or null if already completed.
|
|
352
392
|
* @returns {Promise<void>} response.learning_path_reset_response - The reset learning path response.
|
|
@@ -355,7 +395,8 @@ interface completeLearningPathIntroVideo {
|
|
|
355
395
|
export async function completeLearningPathIntroVideo(
|
|
356
396
|
introVideoId: number,
|
|
357
397
|
learningPathId: number,
|
|
358
|
-
lessonsToImport: number[] | null
|
|
398
|
+
lessonsToImport: number[] | null,
|
|
399
|
+
brand: string | null
|
|
359
400
|
) {
|
|
360
401
|
let response = {} as completeLearningPathIntroVideo
|
|
361
402
|
|
|
@@ -368,6 +409,15 @@ export async function completeLearningPathIntroVideo(
|
|
|
368
409
|
|
|
369
410
|
} else {
|
|
370
411
|
response.lesson_import_response = await contentStatusCompletedMany(lessonsToImport, collection)
|
|
412
|
+
|
|
413
|
+
const activePath = await getActivePath(brand)
|
|
414
|
+
if (activePath.active_learning_path_id === learningPathId) {
|
|
415
|
+
response.update_dailies_response = await updateDailySession(
|
|
416
|
+
brand,
|
|
417
|
+
getToday(),
|
|
418
|
+
true
|
|
419
|
+
)
|
|
420
|
+
}
|
|
371
421
|
}
|
|
372
422
|
|
|
373
423
|
return response
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -6,7 +6,7 @@ import { getActivePath, fetchLearningPathLessons } from '../content-org/learning
|
|
|
6
6
|
import { getToday } from '../dateUtils.js'
|
|
7
7
|
import { fetchMethodV2IntroVideo } from '../sanity'
|
|
8
8
|
import { getProgressState } from '../contentProgress'
|
|
9
|
-
import {
|
|
9
|
+
import {COLLECTION_TYPE, STATE} from '../sync/models/ContentProgress'
|
|
10
10
|
|
|
11
11
|
export async function getMethodCard(brand) {
|
|
12
12
|
const introVideo = await fetchMethodV2IntroVideo(brand)
|
|
@@ -19,7 +19,7 @@ export async function getMethodCard(brand) {
|
|
|
19
19
|
|
|
20
20
|
const activeLearningPath = await getActivePath(brand)
|
|
21
21
|
|
|
22
|
-
if (introVideoProgressState !==
|
|
22
|
+
if (introVideoProgressState !== STATE.COMPLETED || !activeLearningPath) {
|
|
23
23
|
//startLearningPath('drumeo', 422533)
|
|
24
24
|
const timestamp = Math.floor(Date.now() / 1000)
|
|
25
25
|
const instructorText =
|
|
@@ -43,43 +43,57 @@ export async function getMethodCard(brand) {
|
|
|
43
43
|
progressTimestamp: timestamp,
|
|
44
44
|
}
|
|
45
45
|
} else {
|
|
46
|
-
//TODO: Optimize loading of dailySessions/Path, should not need multiple requests
|
|
47
46
|
const learningPath = await fetchLearningPathLessons(
|
|
48
47
|
activeLearningPath.active_learning_path_id,
|
|
49
48
|
brand,
|
|
50
49
|
getToday()
|
|
51
50
|
)
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const anyCompleted = learningPath?.todays_lessons.some(
|
|
58
|
-
(lesson) => lesson.progressStatus === 'completed'
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
const noneCompleted = learningPath?.todays_lessons.every(
|
|
62
|
-
(lesson) => lesson.progressStatus !== 'completed'
|
|
63
|
-
)
|
|
52
|
+
if (!learningPath) {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
64
55
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
// need to calculate based on all dailies
|
|
57
|
+
const allDailies = [
|
|
58
|
+
...learningPath.previous_learning_path_dailies,
|
|
59
|
+
...learningPath.learning_path_dailies,
|
|
60
|
+
...learningPath.next_learning_path_dailies
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
let allDailiesCompleted = true;
|
|
64
|
+
let anyDailiesCompleted = false;
|
|
65
|
+
let noDailiesCompleted = true;
|
|
66
|
+
let nextIncompleteDaily = null;
|
|
67
|
+
|
|
68
|
+
for (const lesson of allDailies) {
|
|
69
|
+
if (lesson.progressStatus === STATE.COMPLETED) {
|
|
70
|
+
anyDailiesCompleted = true;
|
|
71
|
+
noDailiesCompleted = false;
|
|
72
|
+
} else {
|
|
73
|
+
allDailiesCompleted = false;
|
|
74
|
+
if (!nextIncompleteDaily) {
|
|
75
|
+
nextIncompleteDaily = lesson;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!allDailiesCompleted && anyDailiesCompleted && nextIncompleteDaily) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
68
82
|
|
|
69
83
|
// get the first incomplete lesson from upcoming and next learning path lessons
|
|
70
84
|
const nextLesson = [
|
|
71
85
|
...learningPath?.upcoming_lessons,
|
|
72
|
-
...learningPath?.
|
|
73
|
-
]?.find((lesson) => lesson.progressStatus !==
|
|
86
|
+
...learningPath?.next_learning_path_dailies,
|
|
87
|
+
]?.find((lesson) => lesson.progressStatus !== STATE.COMPLETED)
|
|
74
88
|
|
|
75
89
|
let ctaText, action
|
|
76
|
-
if (
|
|
90
|
+
if (noDailiesCompleted) {
|
|
77
91
|
ctaText = 'Start Session'
|
|
78
|
-
action = getMethodActionCTA(
|
|
79
|
-
} else if (
|
|
92
|
+
action = getMethodActionCTA(nextIncompleteDaily)
|
|
93
|
+
} else if (anyDailiesCompleted && !allDailiesCompleted) {
|
|
80
94
|
ctaText = 'Continue Session'
|
|
81
|
-
action = getMethodActionCTA(
|
|
82
|
-
} else if (
|
|
95
|
+
action = getMethodActionCTA(nextIncompleteDaily)
|
|
96
|
+
} else if (allDailiesCompleted) {
|
|
83
97
|
ctaText = nextLesson ? 'Start Next Lesson' : 'Browse Lessons'
|
|
84
98
|
action = nextLesson
|
|
85
99
|
? getMethodActionCTA(nextLesson)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/services/sanity.js
CHANGED
|
@@ -1306,7 +1306,7 @@ export async function fetchByReference(
|
|
|
1306
1306
|
* @returns {Promise<int|null>}
|
|
1307
1307
|
*/
|
|
1308
1308
|
export async function fetchTopLevelParentId(railcontentId) {
|
|
1309
|
-
const parentFilter =
|
|
1309
|
+
const parentFilter = 'railcontent_id in [...(^.parent_content_data[].id)]'
|
|
1310
1310
|
const statusFilter = "&& status in ['scheduled', 'published', 'archived', 'unlisted']"
|
|
1311
1311
|
|
|
1312
1312
|
const query = `*[railcontent_id == ${railcontentId}]{
|
|
@@ -1379,7 +1379,7 @@ export async function fetchHierarchy(railcontentId) {
|
|
|
1379
1379
|
}
|
|
1380
1380
|
|
|
1381
1381
|
function populateHierarchyLookups(currentLevel, data, parentId) {
|
|
1382
|
-
const railcontentIdField = currentLevel.railcontent_id ?
|
|
1382
|
+
const railcontentIdField = currentLevel.railcontent_id ? 'railcontent_id' : 'id'
|
|
1383
1383
|
|
|
1384
1384
|
let contentId = currentLevel[railcontentIdField]
|
|
1385
1385
|
let children = currentLevel['children']
|
|
@@ -1534,6 +1534,10 @@ function contentResultsDecorator(results, fieldName, callback) {
|
|
|
1534
1534
|
results.related_lessons.forEach((result) => {
|
|
1535
1535
|
result[fieldName] = callback(result)
|
|
1536
1536
|
})
|
|
1537
|
+
} else if (results.data && Array.isArray(results.data)) {
|
|
1538
|
+
results.data.forEach((result) => {
|
|
1539
|
+
result[fieldName] = callback(result)
|
|
1540
|
+
})
|
|
1537
1541
|
} else {
|
|
1538
1542
|
results[fieldName] = callback(results)
|
|
1539
1543
|
}
|
|
@@ -2017,7 +2021,7 @@ export async function fetchMethodV2Structure(brand) {
|
|
|
2017
2021
|
* @returns {Promise<*|null>}
|
|
2018
2022
|
*/
|
|
2019
2023
|
export async function fetchMethodV2StructureFromId(contentId) {
|
|
2020
|
-
const _type =
|
|
2024
|
+
const _type = 'method-v2'
|
|
2021
2025
|
const query = `*[_type == '${_type}' && brand == *[railcontent_id == ${contentId}][0].brand][0...1]{
|
|
2022
2026
|
'sanity_id': _id,
|
|
2023
2027
|
brand,
|
|
@@ -2028,7 +2032,7 @@ export async function fetchMethodV2StructureFromId(contentId) {
|
|
|
2028
2032
|
'children': child[]->railcontent_id
|
|
2029
2033
|
}
|
|
2030
2034
|
}`
|
|
2031
|
-
return await fetchSanity(query, false)
|
|
2035
|
+
return await fetchSanity(query, false)
|
|
2032
2036
|
}
|
|
2033
2037
|
|
|
2034
2038
|
/**
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/services/types.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/test/HttpClient.test.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|