musora-content-services 2.79.0 → 2.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.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 +14 -0
- package/README.md +0 -0
- package/babel.config.cjs +0 -0
- package/docs/Content.html +269 -0
- package/docs/ContentOrganization.html +2 -2
- package/docs/Forums.html +2 -2
- package/docs/Gamification.html +2 -2
- package/docs/TestUser.html +2 -2
- package/docs/UserManagementSystem.html +2 -2
- package/docs/api_types.js.html +2 -2
- package/docs/config.js.html +2 -2
- package/docs/content-org_content-org.js.html +2 -2
- package/docs/content-org_guided-courses.ts.html +2 -2
- package/docs/content-org_learning-paths.ts.html +124 -24
- package/docs/content-org_playlists-types.js.html +2 -2
- package/docs/content-org_playlists.js.html +2 -2
- package/docs/content.js.html +2 -2
- package/docs/content_artist.ts.html +212 -0
- package/docs/content_content.ts.html +77 -0
- package/docs/content_genre.ts.html +211 -0
- package/docs/content_instructor.ts.html +203 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/forums_categories.ts.html +3 -3
- package/docs/forums_discussions.js.html +0 -0
- package/docs/forums_forum.js.html +0 -0
- package/docs/forums_forums.ts.html +2 -2
- package/docs/forums_posts.ts.html +22 -3
- package/docs/forums_threads.ts.html +16 -3
- package/docs/gamification_awards.js.html +0 -0
- package/docs/gamification_awards.ts.html +2 -2
- package/docs/gamification_gamification.js.html +2 -2
- package/docs/gamification_types.js.html +0 -0
- package/docs/global.html +2 -2
- package/docs/index.html +2 -2
- package/docs/liveTesting.ts.html +2 -2
- package/docs/module-Accounts.html +10 -10
- package/docs/module-Artist.html +991 -0
- package/docs/module-Awards.html +2 -2
- package/docs/module-Categories.html +0 -0
- package/docs/module-Config.html +2 -2
- package/docs/module-Content-Services-V2.html +2 -2
- package/docs/module-ForumCategories.html +0 -0
- package/docs/module-ForumDiscussions.html +0 -0
- package/docs/module-Forums.html +731 -89
- package/docs/module-Genre.html +981 -0
- package/docs/module-GuidedCourses.html +2 -2
- package/docs/module-Instructor.html +929 -0
- package/docs/module-Interests.html +2 -2
- package/docs/module-LearningPaths.html +640 -12
- package/docs/module-Onboarding.html +2 -2
- package/docs/module-Payments.html +2 -2
- package/docs/module-Permissions.html +2 -2
- package/docs/module-Playlists.html +2 -2
- package/docs/module-ProgressRow.html +2 -2
- package/docs/module-Railcontent-Services.html +2 -2
- package/docs/module-Sanity-Services.html +327 -1855
- package/docs/module-Sessions.html +2 -2
- package/docs/module-Threads.html +0 -0
- package/docs/module-UserActivity.html +2 -2
- package/docs/module-UserChat.html +2 -2
- package/docs/module-UserManagement.html +2 -2
- package/docs/module-UserMemberships.html +2 -2
- package/docs/module-UserNotifications.html +2 -2
- package/docs/module-UserProfile.html +2 -2
- package/docs/progress-row_method-card.js.html +8 -7
- package/docs/railcontent.js.html +2 -2
- package/docs/sanity.js.html +109 -268
- package/docs/scripts/collapse.js +0 -0
- package/docs/scripts/commonNav.js +0 -0
- package/docs/scripts/linenumber.js +0 -0
- package/docs/scripts/nav.js +0 -0
- package/docs/scripts/polyfill.js +0 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
- package/docs/scripts/prettify/lang-css.js +0 -0
- package/docs/scripts/prettify/prettify.js +0 -0
- package/docs/scripts/search.js +0 -0
- package/docs/styles/jsdoc.css +0 -0
- package/docs/styles/prettify.css +0 -0
- package/docs/userActivity.js.html +2 -2
- package/docs/user_account.ts.html +5 -11
- package/docs/user_chat.js.html +2 -2
- package/docs/user_interests.js.html +2 -2
- package/docs/user_management.js.html +2 -2
- package/docs/user_memberships.js.html +0 -0
- package/docs/user_memberships.ts.html +2 -2
- package/docs/user_notifications.js.html +2 -2
- package/docs/user_onboarding.ts.html +2 -2
- package/docs/user_payments.ts.html +2 -2
- package/docs/user_permissions.js.html +2 -2
- package/docs/user_profile.js.html +2 -2
- package/docs/user_sessions.js.html +2 -2
- package/docs/user_types.js.html +2 -2
- package/docs/user_user-management-system.js.html +2 -2
- package/jest.config.js +0 -0
- package/jsdoc.json +1 -0
- package/package.json +1 -1
- package/src/contentMetaData.js +0 -0
- package/src/contentTypeConfig.js +2 -2
- package/src/filterBuilder.js +0 -0
- package/src/index.d.ts +28 -5
- package/src/index.js +28 -5
- 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/httpHelper.js +0 -0
- package/src/lib/lastUpdated.js +0 -0
- package/src/services/api/types.js +0 -0
- package/src/services/api/types.ts +0 -0
- package/src/services/config.js +0 -0
- package/src/services/content/artist.ts +139 -0
- package/src/services/content/content.ts +38 -0
- package/src/services/content/genre.ts +139 -0
- package/src/services/content/instructor.ts +131 -0
- 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 +35 -21
- package/src/services/content-org/playlists-types.js +0 -0
- package/src/services/content-org/playlists.js +0 -0
- package/src/services/content.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/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/progress-row/method-card.js +0 -0
- package/src/services/railcontent.js +0 -0
- package/src/services/recommendations.js +0 -0
- package/src/services/sanity.js +105 -266
- package/src/services/types.js +0 -0
- package/src/services/user/account.ts +3 -9
- 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.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/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/lastUpdated.test.js +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/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/user/permissions.test.js +0 -0
- package/test/userActivity.test.js +0 -0
- package/tools/generate-index.cjs +0 -0
- package/.claude/settings.local.json +0 -14
- package/.yarnrc.yml +0 -1
package/package.json
CHANGED
package/src/contentMetaData.js
CHANGED
|
File without changes
|
package/src/contentTypeConfig.js
CHANGED
|
@@ -81,8 +81,8 @@ export const playAlongMp3sField = `{
|
|
|
81
81
|
`
|
|
82
82
|
|
|
83
83
|
export const instructorField = `instructor[]->{
|
|
84
|
-
"id": railcontent_id,
|
|
85
84
|
name,
|
|
85
|
+
slug,
|
|
86
86
|
short_bio,
|
|
87
87
|
"biography": short_bio[0].children[0].text,
|
|
88
88
|
"coach_card_image": coach_card_image.asset->url,
|
|
@@ -278,7 +278,7 @@ export const getNextLessonLessonParentTypes = [
|
|
|
278
278
|
'pack-bundle',
|
|
279
279
|
'song-tutorial',
|
|
280
280
|
'learning-path-v2',
|
|
281
|
-
'skill-pack'
|
|
281
|
+
'skill-pack',
|
|
282
282
|
]
|
|
283
283
|
|
|
284
284
|
export const progressTypesMapping = {
|
package/src/filterBuilder.js
CHANGED
|
File without changes
|
package/src/index.d.ts
CHANGED
|
@@ -5,6 +5,24 @@ import {
|
|
|
5
5
|
initializeService
|
|
6
6
|
} from './services/config.js';
|
|
7
7
|
|
|
8
|
+
import {
|
|
9
|
+
fetchArtistBySlug,
|
|
10
|
+
fetchArtistLessons,
|
|
11
|
+
fetchArtists
|
|
12
|
+
} from './services/content/artist.ts';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
fetchGenreBySlug,
|
|
16
|
+
fetchGenreLessons,
|
|
17
|
+
fetchGenres
|
|
18
|
+
} from './services/content/genre.ts';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
fetchInstructorBySlug,
|
|
22
|
+
fetchInstructorLessons,
|
|
23
|
+
fetchInstructors
|
|
24
|
+
} from './services/content/instructor.ts';
|
|
25
|
+
|
|
8
26
|
import {
|
|
9
27
|
enrollUserInGuidedCourse,
|
|
10
28
|
fetchEnrollmentPageMetadata,
|
|
@@ -225,21 +243,18 @@ import {
|
|
|
225
243
|
} from './services/recommendations.js';
|
|
226
244
|
|
|
227
245
|
import {
|
|
246
|
+
buildEntityAndTotalQuery,
|
|
228
247
|
fetchAll,
|
|
229
248
|
fetchAllFilterOptions,
|
|
230
249
|
fetchAllPacks,
|
|
231
|
-
fetchArtistLessons,
|
|
232
|
-
fetchArtists,
|
|
233
250
|
fetchByRailContentId,
|
|
234
251
|
fetchByRailContentIds,
|
|
235
252
|
fetchByReference,
|
|
236
253
|
fetchChatAndLiveEnvent,
|
|
237
|
-
fetchCoachLessons,
|
|
238
254
|
fetchComingSoon,
|
|
239
255
|
fetchCommentModContentData,
|
|
240
256
|
fetchContentRows,
|
|
241
257
|
fetchFoundation,
|
|
242
|
-
fetchGenreLessons,
|
|
243
258
|
fetchHierarchy,
|
|
244
259
|
fetchLeaving,
|
|
245
260
|
fetchLessonContent,
|
|
@@ -274,6 +289,7 @@ import {
|
|
|
274
289
|
fetchTabData,
|
|
275
290
|
fetchTopLevelParentId,
|
|
276
291
|
fetchUpcomingEvents,
|
|
292
|
+
getSanityDate,
|
|
277
293
|
getSortOrder,
|
|
278
294
|
jumpToContinueContent
|
|
279
295
|
} from './services/sanity.js';
|
|
@@ -406,6 +422,7 @@ declare module 'musora-content-services' {
|
|
|
406
422
|
assignModeratorToComment,
|
|
407
423
|
blockUser,
|
|
408
424
|
blockedUsers,
|
|
425
|
+
buildEntityAndTotalQuery,
|
|
409
426
|
buildImageSRC,
|
|
410
427
|
calculateLongestStreaks,
|
|
411
428
|
closeComment,
|
|
@@ -442,6 +459,7 @@ declare module 'musora-content-services' {
|
|
|
442
459
|
fetchAllCompletedStates,
|
|
443
460
|
fetchAllFilterOptions,
|
|
444
461
|
fetchAllPacks,
|
|
462
|
+
fetchArtistBySlug,
|
|
445
463
|
fetchArtistLessons,
|
|
446
464
|
fetchArtists,
|
|
447
465
|
fetchAwardsForUser,
|
|
@@ -452,7 +470,6 @@ declare module 'musora-content-services' {
|
|
|
452
470
|
fetchCertificate,
|
|
453
471
|
fetchChatAndLiveEnvent,
|
|
454
472
|
fetchChatSettings,
|
|
455
|
-
fetchCoachLessons,
|
|
456
473
|
fetchComingSoon,
|
|
457
474
|
fetchComment,
|
|
458
475
|
fetchCommentModContentData,
|
|
@@ -470,9 +487,14 @@ declare module 'musora-content-services' {
|
|
|
470
487
|
fetchFollowedThreads,
|
|
471
488
|
fetchForumCategories,
|
|
472
489
|
fetchFoundation,
|
|
490
|
+
fetchGenreBySlug,
|
|
473
491
|
fetchGenreLessons,
|
|
492
|
+
fetchGenres,
|
|
474
493
|
fetchHandler,
|
|
475
494
|
fetchHierarchy,
|
|
495
|
+
fetchInstructorBySlug,
|
|
496
|
+
fetchInstructorLessons,
|
|
497
|
+
fetchInstructors,
|
|
476
498
|
fetchInterests,
|
|
477
499
|
fetchLastInteractedChild,
|
|
478
500
|
fetchLatestThreads,
|
|
@@ -572,6 +594,7 @@ declare module 'musora-content-services' {
|
|
|
572
594
|
getRecommendedForYou,
|
|
573
595
|
getResumeTimeSeconds,
|
|
574
596
|
getResumeTimeSecondsByIds,
|
|
597
|
+
getSanityDate,
|
|
575
598
|
getScheduleContentRows,
|
|
576
599
|
getSortOrder,
|
|
577
600
|
getStartedOrCompletedProgressOnly,
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,24 @@ import {
|
|
|
5
5
|
initializeService
|
|
6
6
|
} from './services/config.js';
|
|
7
7
|
|
|
8
|
+
import {
|
|
9
|
+
fetchArtistBySlug,
|
|
10
|
+
fetchArtistLessons,
|
|
11
|
+
fetchArtists
|
|
12
|
+
} from './services/content/artist.ts';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
fetchGenreBySlug,
|
|
16
|
+
fetchGenreLessons,
|
|
17
|
+
fetchGenres
|
|
18
|
+
} from './services/content/genre.ts';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
fetchInstructorBySlug,
|
|
22
|
+
fetchInstructorLessons,
|
|
23
|
+
fetchInstructors
|
|
24
|
+
} from './services/content/instructor.ts';
|
|
25
|
+
|
|
8
26
|
import {
|
|
9
27
|
enrollUserInGuidedCourse,
|
|
10
28
|
fetchEnrollmentPageMetadata,
|
|
@@ -225,21 +243,18 @@ import {
|
|
|
225
243
|
} from './services/recommendations.js';
|
|
226
244
|
|
|
227
245
|
import {
|
|
246
|
+
buildEntityAndTotalQuery,
|
|
228
247
|
fetchAll,
|
|
229
248
|
fetchAllFilterOptions,
|
|
230
249
|
fetchAllPacks,
|
|
231
|
-
fetchArtistLessons,
|
|
232
|
-
fetchArtists,
|
|
233
250
|
fetchByRailContentId,
|
|
234
251
|
fetchByRailContentIds,
|
|
235
252
|
fetchByReference,
|
|
236
253
|
fetchChatAndLiveEnvent,
|
|
237
|
-
fetchCoachLessons,
|
|
238
254
|
fetchComingSoon,
|
|
239
255
|
fetchCommentModContentData,
|
|
240
256
|
fetchContentRows,
|
|
241
257
|
fetchFoundation,
|
|
242
|
-
fetchGenreLessons,
|
|
243
258
|
fetchHierarchy,
|
|
244
259
|
fetchLeaving,
|
|
245
260
|
fetchLessonContent,
|
|
@@ -274,6 +289,7 @@ import {
|
|
|
274
289
|
fetchTabData,
|
|
275
290
|
fetchTopLevelParentId,
|
|
276
291
|
fetchUpcomingEvents,
|
|
292
|
+
getSanityDate,
|
|
277
293
|
getSortOrder,
|
|
278
294
|
jumpToContinueContent
|
|
279
295
|
} from './services/sanity.js';
|
|
@@ -405,6 +421,7 @@ export {
|
|
|
405
421
|
assignModeratorToComment,
|
|
406
422
|
blockUser,
|
|
407
423
|
blockedUsers,
|
|
424
|
+
buildEntityAndTotalQuery,
|
|
408
425
|
buildImageSRC,
|
|
409
426
|
calculateLongestStreaks,
|
|
410
427
|
closeComment,
|
|
@@ -441,6 +458,7 @@ export {
|
|
|
441
458
|
fetchAllCompletedStates,
|
|
442
459
|
fetchAllFilterOptions,
|
|
443
460
|
fetchAllPacks,
|
|
461
|
+
fetchArtistBySlug,
|
|
444
462
|
fetchArtistLessons,
|
|
445
463
|
fetchArtists,
|
|
446
464
|
fetchAwardsForUser,
|
|
@@ -451,7 +469,6 @@ export {
|
|
|
451
469
|
fetchCertificate,
|
|
452
470
|
fetchChatAndLiveEnvent,
|
|
453
471
|
fetchChatSettings,
|
|
454
|
-
fetchCoachLessons,
|
|
455
472
|
fetchComingSoon,
|
|
456
473
|
fetchComment,
|
|
457
474
|
fetchCommentModContentData,
|
|
@@ -469,9 +486,14 @@ export {
|
|
|
469
486
|
fetchFollowedThreads,
|
|
470
487
|
fetchForumCategories,
|
|
471
488
|
fetchFoundation,
|
|
489
|
+
fetchGenreBySlug,
|
|
472
490
|
fetchGenreLessons,
|
|
491
|
+
fetchGenres,
|
|
473
492
|
fetchHandler,
|
|
474
493
|
fetchHierarchy,
|
|
494
|
+
fetchInstructorBySlug,
|
|
495
|
+
fetchInstructorLessons,
|
|
496
|
+
fetchInstructors,
|
|
475
497
|
fetchInterests,
|
|
476
498
|
fetchLastInteractedChild,
|
|
477
499
|
fetchLatestThreads,
|
|
@@ -571,6 +593,7 @@ export {
|
|
|
571
593
|
getRecommendedForYou,
|
|
572
594
|
getResumeTimeSeconds,
|
|
573
595
|
getResumeTimeSecondsByIds,
|
|
596
|
+
getSanityDate,
|
|
574
597
|
getScheduleContentRows,
|
|
575
598
|
getSortOrder,
|
|
576
599
|
getStartedOrCompletedProgressOnly,
|
|
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/lib/httpHelper.js
CHANGED
|
File without changes
|
package/src/lib/lastUpdated.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/services/config.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Artist
|
|
3
|
+
*/
|
|
4
|
+
import { DEFAULT_FIELDS, filtersToGroq } from '../../contentTypeConfig.js'
|
|
5
|
+
import { FilterBuilder } from '../../filterBuilder.js'
|
|
6
|
+
import { fetchSanity, getSanityDate, getSortOrder } from '../sanity.js'
|
|
7
|
+
import { Lesson } from './content'
|
|
8
|
+
|
|
9
|
+
export interface Artist {
|
|
10
|
+
slug: string
|
|
11
|
+
name: string
|
|
12
|
+
lessons?: Lesson[]
|
|
13
|
+
lessonsCount: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Fetch all artists with lessons available for a specific brand.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} brand - The brand for which to fetch artists.
|
|
20
|
+
* @returns {Promise<Artist[]|null>} - A promise that resolves to an array of artist objects or null if not found.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* fetchArtists('drumeo')
|
|
24
|
+
* .then(artists => console.log(artists))
|
|
25
|
+
* .catch(error => console.error(error));
|
|
26
|
+
*/
|
|
27
|
+
export async function fetchArtists(brand: string): Promise<Artist[] | null> {
|
|
28
|
+
const filter = await new FilterBuilder(
|
|
29
|
+
`_type == "song" && brand == "${brand}" && references(^._id)`,
|
|
30
|
+
{ bypassPermissions: true }
|
|
31
|
+
).buildFilter()
|
|
32
|
+
const query = `
|
|
33
|
+
*[_type == "artist"]{
|
|
34
|
+
name,
|
|
35
|
+
"slug": slug.current,
|
|
36
|
+
"lessonsCount": count(*[${filter}])
|
|
37
|
+
}[lessonsCount > 0] |order(lower(name)) `
|
|
38
|
+
return fetchSanity(query, true, { processNeedAccess: false, processPageType: false })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Fetch a single artist by their Sanity ID.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} slug - The name of the artist to fetch.
|
|
45
|
+
* @param {string} [brand] - The brand for which to fetch the artist.
|
|
46
|
+
* @returns {Promise<Artist|null>} - A promise that resolves to an artist objects or null if not found.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* fetchArtists('drumeo')
|
|
50
|
+
* .then(artists => console.log(artists))
|
|
51
|
+
* .catch(error => console.error(error));
|
|
52
|
+
*/
|
|
53
|
+
export async function fetchArtistBySlug(slug: string, brand?: string): Promise<Artist | null> {
|
|
54
|
+
const brandFilter = brand ? `brand == "${brand}" && ` : ''
|
|
55
|
+
const filter = await new FilterBuilder(`${brandFilter} _type == "song" && references(^._id)`, {
|
|
56
|
+
bypassPermissions: true,
|
|
57
|
+
}).buildFilter()
|
|
58
|
+
const query = `
|
|
59
|
+
*[_type == "artist" && slug.current == '${slug}']{
|
|
60
|
+
name,
|
|
61
|
+
"slug": slug.current,
|
|
62
|
+
"lessonsCount": count(*[${filter}])
|
|
63
|
+
}[lessonsCount > 0] |order(lower(name)) `
|
|
64
|
+
return fetchSanity(query, true, { processNeedAccess: false, processPageType: false })
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ArtistLessonOptions {
|
|
68
|
+
sort?: string
|
|
69
|
+
searchTerm?: string
|
|
70
|
+
page?: number
|
|
71
|
+
limit?: number
|
|
72
|
+
includedFields?: Array<string>
|
|
73
|
+
progressIds?: Array<number>
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface LessonsByArtistResponse {
|
|
77
|
+
entity: Artist[]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Fetch the artist's lessons.
|
|
82
|
+
* @param {string} brand - The brand for which to fetch lessons.
|
|
83
|
+
* @param {string} slug - The slug of the artist
|
|
84
|
+
* @param {string} contentType - The type of the lessons we need to get from the artist. If not defined, groq will get lessons from all content types
|
|
85
|
+
* @param {Object} params - Parameters for sorting, searching, pagination and filtering.
|
|
86
|
+
* @param {string} [params.sort="-published_on"] - The field to sort the lessons by.
|
|
87
|
+
* @param {string} [params.searchTerm=""] - The search term to filter the lessons.
|
|
88
|
+
* @param {number} [params.page=1] - The page number for pagination.
|
|
89
|
+
* @param {number} [params.limit=10] - The number of items per page.
|
|
90
|
+
* @param {Array<string>} [params.includedFields=[]] - Additional filters to apply to the query in the format of a key,value array. eg. ['difficulty,Intermediate', 'genre,rock'].
|
|
91
|
+
* @param {Array<number>} [params.progressIds] - The ids of the lessons that are in progress or completed
|
|
92
|
+
* @returns {Promise<LessonsByArtistResponse|null>} - The lessons for the artist and some details about the artist (name and thumbnail).
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* fetchArtistLessons('drumeo', '10 Years', 'song', {'-published_on', '', 1, 10, ["difficulty,Intermediate"], [232168, 232824, 303375, 232194, 393125]})
|
|
96
|
+
* .then(lessons => console.log(lessons))
|
|
97
|
+
* .catch(error => console.error(error));
|
|
98
|
+
*/
|
|
99
|
+
export async function fetchArtistLessons(
|
|
100
|
+
brand: string,
|
|
101
|
+
slug: string,
|
|
102
|
+
contentType: string,
|
|
103
|
+
{
|
|
104
|
+
sort = '-published_on',
|
|
105
|
+
searchTerm = '',
|
|
106
|
+
page = 1,
|
|
107
|
+
limit = 10,
|
|
108
|
+
includedFields = [],
|
|
109
|
+
progressIds = undefined,
|
|
110
|
+
}: ArtistLessonOptions = {}
|
|
111
|
+
): Promise<LessonsByArtistResponse | null> {
|
|
112
|
+
const fieldsString = DEFAULT_FIELDS.join(',')
|
|
113
|
+
const start = (page - 1) * limit
|
|
114
|
+
const end = start + limit
|
|
115
|
+
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"` : ''
|
|
116
|
+
const sortOrder = getSortOrder(sort, brand)
|
|
117
|
+
const addType =
|
|
118
|
+
contentType && Array.isArray(contentType)
|
|
119
|
+
? `_type in ['${contentType.join("', '")}'] &&`
|
|
120
|
+
: contentType
|
|
121
|
+
? `_type == '${contentType}' && `
|
|
122
|
+
: ''
|
|
123
|
+
const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
|
|
124
|
+
|
|
125
|
+
// limits the results to supplied progressIds for started & completed filters
|
|
126
|
+
const progressFilter =
|
|
127
|
+
progressIds !== undefined ? `&& railcontent_id in [${progressIds.join(',')}]` : ''
|
|
128
|
+
const now = getSanityDate(new Date())
|
|
129
|
+
const query = `{
|
|
130
|
+
"entity":
|
|
131
|
+
*[_type == 'artist' && slug.current == '${slug}']
|
|
132
|
+
{'type': _type, name, 'thumbnail':thumbnail_url.asset->url,
|
|
133
|
+
'lessons_count': count(*[${addType} brand == '${brand}' && references(^._id)]),
|
|
134
|
+
'lessons': *[${addType} brand == '${brand}' && references(^._id) && (status in ['published'] || (status == 'scheduled' && defined(published_on) && published_on >= '${now}')) ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{${fieldsString}}
|
|
135
|
+
[${start}...${end}]}
|
|
136
|
+
|order(${sortOrder})
|
|
137
|
+
}`
|
|
138
|
+
return fetchSanity(query, true)
|
|
139
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace Content
|
|
3
|
+
* @property {module:Instructor} Instructor
|
|
4
|
+
* @property {module:Genre} Genre
|
|
5
|
+
* @property {module:Artist} Artist
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type LessonType = 'workout' | 'challenge-part' | 'song' | string
|
|
9
|
+
export type LessonPageType = 'lesson' | 'song' | string
|
|
10
|
+
|
|
11
|
+
export interface ArtistObject {
|
|
12
|
+
name: string
|
|
13
|
+
thumbnail: string | null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Lesson {
|
|
17
|
+
artist: ArtistObject | string | null
|
|
18
|
+
artist_name: string
|
|
19
|
+
brand: string
|
|
20
|
+
child_count: number | null
|
|
21
|
+
difficulty: number | null
|
|
22
|
+
difficulty_string: string | null
|
|
23
|
+
genre: string[] | string | null
|
|
24
|
+
id: number
|
|
25
|
+
image: string
|
|
26
|
+
length_in_seconds: number
|
|
27
|
+
parent_id: number | null
|
|
28
|
+
permission_id: number[]
|
|
29
|
+
published_on: string
|
|
30
|
+
sanity_id: string
|
|
31
|
+
slug: string
|
|
32
|
+
status: string
|
|
33
|
+
thumbnail: string
|
|
34
|
+
title: string
|
|
35
|
+
type: LessonType
|
|
36
|
+
need_access: boolean
|
|
37
|
+
page_type: LessonPageType
|
|
38
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Genre
|
|
3
|
+
*/
|
|
4
|
+
import { DEFAULT_FIELDS, filtersToGroq } from '../../contentTypeConfig.js'
|
|
5
|
+
import { fetchSanity, getSanityDate, getSortOrder } from '../sanity.js'
|
|
6
|
+
import { FilterBuilder } from '../../filterBuilder.js'
|
|
7
|
+
import { Lesson } from './content'
|
|
8
|
+
|
|
9
|
+
export interface Genre {
|
|
10
|
+
lessons?: Lesson[]
|
|
11
|
+
lessons_count: number
|
|
12
|
+
name: string
|
|
13
|
+
slug: string
|
|
14
|
+
thumbnail: string
|
|
15
|
+
type: 'genre'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Fetch all genres with lessons available for a specific brand.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} [brand] - The brand for which to fetch the genre for. Lesson count will be filtered by this brand if provided.
|
|
22
|
+
* @returns {Promise<Genre[]>} - A promise that resolves to an genre object or null if not found.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* fetchGenres('drumeo')
|
|
26
|
+
* .then(genres => console.log(genres))
|
|
27
|
+
* .catch(error => console.error(error));
|
|
28
|
+
*/
|
|
29
|
+
export async function fetchGenres(brand: string): Promise<Genre[]> {
|
|
30
|
+
const filter = await new FilterBuilder(`brand == "${brand}" && references(^._id)`, {
|
|
31
|
+
bypassPermissions: true,
|
|
32
|
+
}).buildFilter()
|
|
33
|
+
|
|
34
|
+
const query = `
|
|
35
|
+
*[_type == 'genre'] {
|
|
36
|
+
'type': _type,
|
|
37
|
+
name,
|
|
38
|
+
"slug": slug.current,
|
|
39
|
+
'thumbnail': thumbnail_url.asset->url,
|
|
40
|
+
"lessons_count": count(*[${filter}])
|
|
41
|
+
} |order(lower(name)) `
|
|
42
|
+
return fetchSanity(query, true, { processNeedAccess: false, processPageType: false})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Fetch a single genre by their slug and brand
|
|
47
|
+
*
|
|
48
|
+
* @param {string} slug - The slug of the genre to fetch.
|
|
49
|
+
* @param {string} [brand] - The brand for which to fetch the genre. Lesson count will be filtered by this brand if provided.
|
|
50
|
+
* @returns {Promise<Genre[]|null>} - A promise that resolves to an genre object or null if not found.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* fetchGenreBySlug('drumeo')
|
|
54
|
+
* .then(genres => console.log(genres))
|
|
55
|
+
* .catch(error => console.error(error));
|
|
56
|
+
*/
|
|
57
|
+
export async function fetchGenreBySlug(slug: string, brand?: string): Promise<Genre | null> {
|
|
58
|
+
const brandFilter = brand ? `brand == "${brand}" && ` : ''
|
|
59
|
+
const filter = await new FilterBuilder(`${brandFilter} references(^._id)`, {
|
|
60
|
+
bypassPermissions: true,
|
|
61
|
+
}).buildFilter()
|
|
62
|
+
|
|
63
|
+
const query = `
|
|
64
|
+
*[_type == 'genre' && slug.current == '${slug}'] {
|
|
65
|
+
'type': _type, name,
|
|
66
|
+
name,
|
|
67
|
+
"slug": slug.current,
|
|
68
|
+
'thumbnail':thumbnail_url.asset->url,
|
|
69
|
+
"lessonsCount": count(*[${filter}])
|
|
70
|
+
}`
|
|
71
|
+
return fetchSanity(query, true, { processNeedAccess: false, processPageType: false})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface FetchGenreLessonsOptions {
|
|
75
|
+
sort?: string
|
|
76
|
+
searchTerm?: string
|
|
77
|
+
page?: number
|
|
78
|
+
limit?: number
|
|
79
|
+
includedFields?: Array<string>
|
|
80
|
+
progressIds?: Array<number>
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface LessonsByGenreResponse {
|
|
84
|
+
entity: Genre[]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Fetch the genre's lessons.
|
|
89
|
+
* @param {string} brand - The brand for which to fetch lessons.
|
|
90
|
+
* @param {string} slug - The slug of the genre
|
|
91
|
+
* @param {Object} params - Parameters for sorting, searching, pagination and filtering.
|
|
92
|
+
* @param {string} [params.sort="-published_on"] - The field to sort the lessons by.
|
|
93
|
+
* @param {string} [params.searchTerm=""] - The search term to filter the lessons.
|
|
94
|
+
* @param {number} [params.page=1] - The page number for pagination.
|
|
95
|
+
* @param {number} [params.limit=10] - The number of items per page.
|
|
96
|
+
* @param {Array<string>} [params.includedFields=[]] - Additional filters to apply to the query in the format of a key,value array. eg. ['difficulty,Intermediate', 'genre,rock'].
|
|
97
|
+
* @param {Array<number>} [params.progressIds=[]] - The ids of the lessons that are in progress or completed
|
|
98
|
+
* @returns {Promise<LessonsByGenreResponse>} - The lessons for the artist and some details about the artist (name and thumbnail).
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* fetchGenreLessons('drumeo', 'Blues', 'song', {'-published_on', '', 1, 10, ["difficulty,Intermediate"], [232168, 232824, 303375, 232194, 393125]})
|
|
102
|
+
* .then(lessons => console.log(lessons))
|
|
103
|
+
* .catch(error => console.error(error));
|
|
104
|
+
*/
|
|
105
|
+
export async function fetchGenreLessons(
|
|
106
|
+
brand: string,
|
|
107
|
+
slug: string,
|
|
108
|
+
contentType: string,
|
|
109
|
+
{
|
|
110
|
+
sort = '-published_on',
|
|
111
|
+
searchTerm = '',
|
|
112
|
+
page = 1,
|
|
113
|
+
limit = 10,
|
|
114
|
+
includedFields = [],
|
|
115
|
+
progressIds = [],
|
|
116
|
+
}: FetchGenreLessonsOptions = {}
|
|
117
|
+
): Promise<LessonsByGenreResponse> {
|
|
118
|
+
const fieldsString = DEFAULT_FIELDS.join(',')
|
|
119
|
+
const start = (page - 1) * limit
|
|
120
|
+
const end = start + limit
|
|
121
|
+
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"` : ''
|
|
122
|
+
const sortOrder = getSortOrder(sort, brand)
|
|
123
|
+
const addType = contentType ? `_type == '${contentType}' && ` : ''
|
|
124
|
+
const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
|
|
125
|
+
// limits the results to supplied progressIds for started & completed filters
|
|
126
|
+
const progressFilter =
|
|
127
|
+
progressIds !== undefined ? `&& railcontent_id in [${progressIds.join(',')}]` : ''
|
|
128
|
+
const now = getSanityDate(new Date())
|
|
129
|
+
const query = `{
|
|
130
|
+
"entity":
|
|
131
|
+
*[_type == 'genre' && slug.current == '${slug}']
|
|
132
|
+
{'type': _type, name, 'thumbnail':thumbnail_url.asset->url,
|
|
133
|
+
'lessons_count': count(*[${addType} brand == '${brand}' && references(^._id)]),
|
|
134
|
+
'lessons': *[${addType} brand == '${brand}' && references(^._id) && (status in ['published'] || (status == 'scheduled' && defined(published_on) && published_on >= '${now}')) ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{${fieldsString}}
|
|
135
|
+
[${start}...${end}]}
|
|
136
|
+
|order(${sortOrder})
|
|
137
|
+
}`
|
|
138
|
+
return fetchSanity(query, true)
|
|
139
|
+
}
|