musora-content-services 1.3.10 → 1.3.11

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.
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.countAssignmentsAndLessons">countAssignmentsAndLessons</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deletePlaylistItem">deletePlaylistItem</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deletePlaylistLike">deletePlaylistLike</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeIndexMetadata">fetchChallengeIndexMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeLessonData">fetchChallengeLessonData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeMetadata">fetchChallengeMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeUserActiveChallenges">fetchChallengeUserActiveChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedChallenges">fetchCompletedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchOwnedChallenges">fetchOwnedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPinnedPlaylists">fetchPinnedPlaylists</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPlaylistItem">fetchPlaylistItem</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserChallengeProgress">fetchUserChallengeProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.pinPlaylist">pinPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCommunityNotification">postChallengesCommunityNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCompleteLesson">postChallengesCompleteLesson</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnroll">postChallengesEnroll</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnrollmentNotification">postChallengesEnrollmentNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesHideCompletedBanner">postChallengesHideCompletedBanner</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesLeave">postChallengesLeave</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSetStartDate">postChallengesSetStartDate</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSoloNotification">postChallengesSoloNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unpinPlaylist">unpinPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.updatePlaylistItem">updatePlaylistItem</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchParentForDownload">fetchParentForDownload</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~handleCustomFetchAll">handleCustomFetchAll</a></li></ul></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.countAssignmentsAndLessons">countAssignmentsAndLessons</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deletePlaylistItem">deletePlaylistItem</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deletePlaylistLike">deletePlaylistLike</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeIndexMetadata">fetchChallengeIndexMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeLessonData">fetchChallengeLessonData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeMetadata">fetchChallengeMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeUserActiveChallenges">fetchChallengeUserActiveChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedChallenges">fetchCompletedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchOwnedChallenges">fetchOwnedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPinnedPlaylists">fetchPinnedPlaylists</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPlaylistItem">fetchPlaylistItem</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserChallengeProgress">fetchUserChallengeProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.pinPlaylist">pinPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCommunityNotification">postChallengesCommunityNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCompleteLesson">postChallengesCompleteLesson</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnroll">postChallengesEnroll</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnrollmentNotification">postChallengesEnrollmentNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesHideCompletedBanner">postChallengesHideCompletedBanner</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesLeave">postChallengesLeave</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSetStartDate">postChallengesSetStartDate</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSoloNotification">postChallengesSoloNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unpinPlaylist">unpinPlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.updatePlaylistItem">updatePlaylistItem</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchParentForDownload">fetchParentForDownload</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getNextAndPreviousQuarterDates">getNextAndPreviousQuarterDates</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li><li data-type='method'><a href="module-Sanity-Services.html#~handleCustomFetchAll">handleCustomFetchAll</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -49,45 +49,43 @@
49
49
  * @module Sanity-Services
50
50
  */
51
51
  import {
52
- artistOrInstructorName,
53
- artistOrInstructorNameAsArray,
54
- assignmentsField,
55
- descriptionField,
56
- resourcesField,
57
- contentTypeConfig,
58
- DEFAULT_FIELDS,
59
- getFieldsForContentType,
60
- filtersToGroq,
61
- getUpcomingEventsTypes,
62
- showsTypes,
63
- getNewReleasesTypes,
64
- coachLessonsTypes
65
- } from "../contentTypeConfig.js";
52
+ artistOrInstructorName,
53
+ artistOrInstructorNameAsArray,
54
+ assignmentsField,
55
+ descriptionField,
56
+ resourcesField,
57
+ contentTypeConfig,
58
+ DEFAULT_FIELDS,
59
+ getFieldsForContentType,
60
+ filtersToGroq,
61
+ getUpcomingEventsTypes,
62
+ showsTypes,
63
+ getNewReleasesTypes,
64
+ coachLessonsTypes,
65
+ getChildFieldsForContentType,
66
+ } from '../contentTypeConfig.js'
67
+
68
+ import { processMetadata, typeWithSortOrder } from '../contentMetaData.js'
69
+
70
+ import { globalConfig } from './config.js'
66
71
 
67
72
  import {
68
- processMetadata,
69
- typeWithSortOrder
70
- } from "../contentMetaData.js";
71
-
72
- import {globalConfig} from "./config.js";
73
-
74
- import {
75
- fetchAllCompletedStates,
76
- fetchCompletedChallenges,
77
- fetchOwnedChallenges,
78
- fetchNextContentDataForParent,
79
- fetchHandler,
80
- } from './railcontent.js';
81
- import {arrayToStringRepresentation, FilterBuilder} from "../filterBuilder.js";
82
- import {fetchUserPermissions} from "./userPermissions.js";
83
- import {getAllCompleted, getAllStarted, getAllStartedOrCompleted} from "./contentProgress.js";
73
+ fetchAllCompletedStates,
74
+ fetchCompletedChallenges,
75
+ fetchOwnedChallenges,
76
+ fetchNextContentDataForParent,
77
+ fetchHandler,
78
+ } from './railcontent.js'
79
+ import { arrayToStringRepresentation, FilterBuilder } from '../filterBuilder.js'
80
+ import { fetchUserPermissions } from './userPermissions.js'
81
+ import { getAllCompleted, getAllStarted, getAllStartedOrCompleted } from './contentProgress.js'
84
82
 
85
83
  /**
86
84
  * Exported functions that are excluded from index generation.
87
85
  *
88
86
  * @type {string[]}
89
87
  */
90
- const excludeFromGeneratedIndex = ['handleCustomFetchAll'];
88
+ const excludeFromGeneratedIndex = ['handleCustomFetchAll']
91
89
 
92
90
  /**
93
91
  * Fetch a song by its document ID from Sanity.
@@ -101,16 +99,123 @@ const excludeFromGeneratedIndex = ['handleCustomFetchAll'];
101
99
  * .catch(error => console.error(error));
102
100
  */
103
101
  export async function fetchSongById(documentId) {
104
- const fields = getFieldsForContentType('song');
105
- const filterParams = {};
106
- const query = await buildQuery(
107
- `_type == "song" &amp;&amp; railcontent_id == ${documentId}`,
108
- filterParams,
109
- fields,
110
- {
111
- isSingle: true,
112
- });
113
- return fetchSanity(query, false);
102
+ const fields = getFieldsForContentType('song')
103
+ const filterParams = {}
104
+ const query = await buildQuery(
105
+ `_type == "song" &amp;&amp; railcontent_id == ${documentId}`,
106
+ filterParams,
107
+ fields,
108
+ {
109
+ isSingle: true,
110
+ }
111
+ )
112
+ return fetchSanity(query, false)
113
+ }
114
+
115
+ /**
116
+ * fetches from Sanity all content marked for removal next quarter
117
+ *
118
+ * @string brand
119
+ * @number pageNumber
120
+ * @number contentPerPage
121
+ * @returns {Promise&lt;Object|null>}
122
+ */
123
+ export async function fetchLeaving(
124
+ brand,
125
+ { pageNumber = 1, contentPerPage = 20 } = {}) {
126
+ const nextQuarter = getNextAndPreviousQuarterDates()['next'];
127
+ const filterString = `brand == '${brand}' &amp;&amp; quarter_removed == '${nextQuarter}'`
128
+ const startEndOrder = getQueryFromPage(pageNumber, contentPerPage);
129
+ const sortOrder = {sortOrder: "published_on desc, id desc", start: startEndOrder['start'], end: startEndOrder['end']};
130
+ const query = await buildQuery(filterString, {pullFutureContent: false, availableContentStatuses: ["published"]}, getFieldsForContentType(), sortOrder);
131
+ return fetchSanity(query, true);
132
+ }
133
+
134
+ /**
135
+ * fetches from Sanity all content marked for return next quarter
136
+ *
137
+ * @string brand
138
+ * @number pageNumber
139
+ * @number contentPerPage
140
+ * @returns {Promise&lt;Object|null>}
141
+ */
142
+ export async function fetchReturning(
143
+ brand,
144
+ { pageNumber = 1, contentPerPage = 20 } = {}) {
145
+ const nextQuarter = getNextAndPreviousQuarterDates()['next'];
146
+ const filterString = `brand == '${brand}' &amp;&amp; quarter_published == '${nextQuarter}'`;
147
+ const startEndOrder = getQueryFromPage(pageNumber, contentPerPage);
148
+ const sortOrder = {sortOrder: "published_on desc, id desc", start: startEndOrder['start'], end: startEndOrder['end']};
149
+ const query = await buildQuery(filterString, {pullFutureContent: true, availableContentStatuses: ["draft"]}, getFieldsForContentType(), sortOrder);
150
+
151
+ return fetchSanity(query, true);
152
+ }
153
+
154
+ /**
155
+ * fetches from Sanity all songs coming soon (new) next quarter
156
+ *
157
+ * @string brand
158
+ * @number pageNumber
159
+ * @number contentPerPage
160
+ * @returns {Promise&lt;Object|null>}
161
+ */
162
+ export async function fetchComingSoon(
163
+ brand,
164
+ { pageNumber = 1, contentPerPage = 20 } = {}) {
165
+ const filterString = `brand == '${brand}' &amp;&amp; _type == 'song'`;
166
+ const startEndOrder = getQueryFromPage(pageNumber, contentPerPage);
167
+ const sortOrder = {sortOrder: "published_on desc, id desc", start: startEndOrder['start'], end: startEndOrder['end']};
168
+ const query = await buildQuery(filterString, {getFutureContentOnly: true}, getFieldsForContentType(), sortOrder);
169
+ return fetchSanity(query, true);
170
+ }
171
+
172
+ /**
173
+ *
174
+ * @number page
175
+ * @returns {number[]}
176
+ */
177
+ function getQueryFromPage(pageNumber, contentPerPage) {
178
+ const start = contentPerPage*(pageNumber-1);
179
+ const end = contentPerPage*pageNumber;
180
+ let result = [];
181
+ result['start'] = start;
182
+ result['end'] = end;
183
+ return result;
184
+ }
185
+
186
+ /**
187
+ * returns array of next and previous quarter dates as strings
188
+ *
189
+ * @returns {*[]}
190
+ */
191
+ function getNextAndPreviousQuarterDates() {
192
+ const january = 1;
193
+ const april = 4;
194
+ const july = 7;
195
+ const october = 10;
196
+ const month = new Date().getMonth();
197
+ let year = new Date().getFullYear();
198
+ let nextQuarter = '';
199
+ let prevQuarter = '';
200
+ if (month &lt; april) {
201
+ nextQuarter = `${year}-0${april}-01`;
202
+ prevQuarter = `${year}-0${january}-01`;
203
+ } else if (month &lt; july) {
204
+ nextQuarter = `${year}-0${july}-01`;
205
+ prevQuarter = `${year}-0${april}-01`;
206
+ } else if (month &lt; october) {
207
+ nextQuarter = `${year}-${october}-01`;
208
+ prevQuarter = `${year}-0${july}-01`;
209
+ } else {
210
+ prevQuarter = `${year}-${october}-01`;
211
+ year++;
212
+ nextQuarter = `${year}-0${january}-01`;
213
+ }
214
+
215
+ let result = [];
216
+ result['next'] = nextQuarter;
217
+ result['previous'] = prevQuarter;
218
+ return result;
114
219
  }
115
220
 
116
221
  /**
@@ -125,13 +230,16 @@ export async function fetchSongById(documentId) {
125
230
  * .catch(error => console.error(error));
126
231
  */
127
232
  export async function fetchArtists(brand) {
128
- const filter = await new FilterBuilder(`_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)`, {bypassPermissions: true}).buildFilter();
129
- const query = `
233
+ const filter = await new FilterBuilder(
234
+ `_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)`,
235
+ { bypassPermissions: true }
236
+ ).buildFilter()
237
+ const query = `
130
238
  *[_type == "artist"]{
131
239
  name,
132
240
  "lessonsCount": count(*[${filter}])
133
- }[lessonsCount > 0]`;
134
- return fetchSanity(query, true, {processNeedAccess: false});
241
+ }[lessonsCount > 0] |order(lower(name)) `
242
+ return fetchSanity(query, true, { processNeedAccess: false })
135
243
  }
136
244
 
137
245
  /**
@@ -140,13 +248,33 @@ export async function fetchArtists(brand) {
140
248
  * @returns {Promise&lt;int|null>} - The fetched count of artists.
141
249
  */
142
250
  export async function fetchSongArtistCount(brand) {
143
- const query = `count(*[_type == 'artist']{'lessonsCount': count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; references(^._id)]._id)}[lessonsCount > 0])`;
144
- return fetchSanity(query, true, {processNeedAccess: false});
251
+ const filter = await new FilterBuilder(
252
+ `_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)`,
253
+ { bypassPermissions: true }
254
+ ).buildFilter()
255
+ const query = `
256
+ count(*[_type == "artist"]{
257
+ name,
258
+ "lessonsCount": count(*[${filter}])
259
+ }[lessonsCount > 0])`
260
+ return fetchSanity(query, true, { processNeedAccess: false })
145
261
  }
146
262
 
147
- export async function fetchPlayAlongsCount(brand) {
148
- const query = `count(*[brand == '${brand}' &amp;&amp; _type == "play-along"]) `
149
- return fetchSanity(query, true, {processNeedAccess: false});
263
+ export async function fetchPlayAlongsCount(brand, {
264
+ searchTerm,
265
+ includedFields,
266
+ progressIds,
267
+ progress,
268
+ }) {
269
+ const searchFilter = searchTerm ? `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")` :'';
270
+
271
+ // Construct the included fields filter, replacing 'difficulty' with 'difficulty_string'
272
+ const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
273
+
274
+ // limits the results to supplied progressIds for started &amp; completed filters
275
+ const progressFilter = await getProgressFilter(progress, progressIds)
276
+ const query = `count(*[brand == '${brand}' &amp;&amp; _type == "play-along" ${searchFilter} ${includedFieldsFilter} ${progressFilter} ]) `
277
+ return fetchSanity(query, true, { processNeedAccess: false })
150
278
  }
151
279
 
152
280
  /**
@@ -162,8 +290,8 @@ export async function fetchPlayAlongsCount(brand) {
162
290
  * .catch(error => console.error(error));
163
291
  */
164
292
  export async function fetchRelatedSongs(brand, songId) {
165
- const now = getSanityDate(new Date());
166
- const query = `
293
+ const now = getSanityDate(new Date())
294
+ const query = `
167
295
  *[_type == "song" &amp;&amp; railcontent_id == ${songId}]{
168
296
  "entity": array::unique([
169
297
  ...(*[_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; railcontent_id != ${songId} &amp;&amp; references(^.artist->_id)
@@ -224,10 +352,10 @@ export async function fetchRelatedSongs(brand, songId) {
224
352
  }]
225
353
  }[0...10])
226
354
  ])[0...10]
227
- }`;
355
+ }`
228
356
 
229
- // Fetch the related songs data
230
- return fetchSanity(query, false);
357
+ // Fetch the related songs data
358
+ return fetchSanity(query, false)
231
359
  }
232
360
 
233
361
  /**
@@ -235,14 +363,17 @@ export async function fetchRelatedSongs(brand, songId) {
235
363
  * @param {string} brand - The brand for which to fetch new releases.
236
364
  * @returns {Promise&lt;Object|null>} - The fetched new releases data or null if not found.
237
365
  */
238
- export async function fetchNewReleases(brand, {page = 1, limit = 20, sort = "-published_on"} = {}) {
239
- const newTypes = getNewReleasesTypes(brand);
240
- const typesString = arrayToStringRepresentation(newTypes);
241
- const start = (page - 1) * limit;
242
- const end = start + limit;
243
- const sortOrder = getSortOrder(sort, brand);
244
- const filter = `_type in ${typesString} &amp;&amp; brand == '${brand}' &amp;&amp; show_in_new_feed == true`;
245
- const fields = `
366
+ export async function fetchNewReleases(
367
+ brand,
368
+ { page = 1, limit = 20, sort = '-published_on' } = {}
369
+ ) {
370
+ const newTypes = getNewReleasesTypes(brand)
371
+ const typesString = arrayToStringRepresentation(newTypes)
372
+ const start = (page - 1) * limit
373
+ const end = start + limit
374
+ const sortOrder = getSortOrder(sort, brand)
375
+ const filter = `_type in ${typesString} &amp;&amp; brand == '${brand}' &amp;&amp; show_in_new_feed == true`
376
+ const fields = `
246
377
  "id": railcontent_id,
247
378
  title,
248
379
  "image": thumbnail.asset->url,
@@ -255,21 +386,16 @@ export async function fetchNewReleases(brand, {page = 1, limit = 20, sort = "-pu
255
386
  "type": _type,
256
387
  web_url_path,
257
388
  "permission_id": permission[]->railcontent_id,
258
- `;
259
- const filterParams = {allowsPullSongsContent: false};
260
- const query = await buildQuery(
261
- filter,
262
- filterParams,
263
- fields,
264
- {
265
- sortOrder: sortOrder,
266
- start,
267
- end: end,
268
- });
269
- return fetchSanity(query, true);
389
+ `
390
+ const filterParams = { allowsPullSongsContent: false }
391
+ const query = await buildQuery(filter, filterParams, fields, {
392
+ sortOrder: sortOrder,
393
+ start,
394
+ end: end,
395
+ })
396
+ return fetchSanity(query, true)
270
397
  }
271
398
 
272
-
273
399
  /**
274
400
  * Fetch upcoming events for a specific brand.
275
401
  *
@@ -284,13 +410,13 @@ export async function fetchNewReleases(brand, {page = 1, limit = 20, sort = "-pu
284
410
  * .then(events => console.log(events))
285
411
  * .catch(error => console.error(error));
286
412
  */
287
- export async function fetchUpcomingEvents(brand, {page = 1, limit = 10} = {}) {
288
- const liveTypes = getUpcomingEventsTypes(brand);
289
- const typesString = arrayToStringRepresentation(liveTypes);
290
- const now = getSanityDate(new Date());
291
- const start = (page - 1) * limit;
292
- const end = start + limit;
293
- const fields = `
413
+ export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {}) {
414
+ const liveTypes = getUpcomingEventsTypes(brand)
415
+ const typesString = arrayToStringRepresentation(liveTypes)
416
+ const now = getSanityDate(new Date())
417
+ const start = (page - 1) * limit
418
+ const end = start + limit
419
+ const fields = `
294
420
  "id": railcontent_id,
295
421
  title,
296
422
  "image": thumbnail.asset->url,
@@ -302,17 +428,17 @@ export async function fetchUpcomingEvents(brand, {page = 1, limit = 10} = {}) {
302
428
  published_on,
303
429
  "type": _type,
304
430
  web_url_path,
305
- "permission_id": permission[]->railcontent_id,`;
306
- const query = buildRawQuery(
307
- `_type in ${typesString} &amp;&amp; brand == '${brand}' &amp;&amp; published_on > '${now}' &amp;&amp; status == 'scheduled'`,
308
- fields,
309
- {
310
- sortOrder: 'published_on asc',
311
- start: start,
312
- end: end,
313
- },
314
- );
315
- return fetchSanity(query, true);
431
+ "permission_id": permission[]->railcontent_id,`
432
+ const query = buildRawQuery(
433
+ `_type in ${typesString} &amp;&amp; brand == '${brand}' &amp;&amp; published_on > '${now}' &amp;&amp; status == 'scheduled'`,
434
+ fields,
435
+ {
436
+ sortOrder: 'published_on asc',
437
+ start: start,
438
+ end: end,
439
+ }
440
+ )
441
+ return fetchSanity(query, true)
316
442
  }
317
443
 
318
444
  /**
@@ -329,16 +455,16 @@ export async function fetchUpcomingEvents(brand, {page = 1, limit = 10} = {}) {
329
455
  * .then(content => console.log(content))
330
456
  * .catch(error => console.error(error));
331
457
  */
332
- export async function fetchScheduledReleases(brand, {page = 1, limit = 10}) {
333
- const upcomingTypes = getUpcomingEventsTypes(brand);
334
- const newTypes = getNewReleasesTypes(brand);
335
-
336
- const scheduledTypes = merge(upcomingTypes, newTypes)
337
- const typesString = arrayJoinWithQuotes(scheduledTypes);
338
- const now = getSanityDate(new Date());
339
- const start = (page - 1) * limit;
340
- const end = start + limit;
341
- const query = `*[_type in [${typesString}] &amp;&amp; brand == '${brand}' &amp;&amp; status in ['published','scheduled'] &amp;&amp; published_on > '${now}']{
458
+ export async function fetchScheduledReleases(brand, { page = 1, limit = 10 }) {
459
+ const upcomingTypes = getUpcomingEventsTypes(brand)
460
+ const newTypes = getNewReleasesTypes(brand)
461
+
462
+ const scheduledTypes = merge(upcomingTypes, newTypes)
463
+ const typesString = arrayJoinWithQuotes(scheduledTypes)
464
+ const now = getSanityDate(new Date())
465
+ const start = (page - 1) * limit
466
+ const end = start + limit
467
+ const query = `*[_type in [${typesString}] &amp;&amp; brand == '${brand}' &amp;&amp; status in ['published','scheduled'] &amp;&amp; published_on > '${now}']{
342
468
  "id": railcontent_id,
343
469
  title,
344
470
  "image": thumbnail.asset->url,
@@ -351,8 +477,8 @@ export async function fetchScheduledReleases(brand, {page = 1, limit = 10}) {
351
477
  "type": _type,
352
478
  web_url_path,
353
479
  "permission_id": permission[]->railcontent_id,
354
- } | order(published_on asc)[${start}...${end}]`;
355
- return fetchSanity(query, true);
480
+ } | order(published_on asc)[${start}...${end}]`
481
+ return fetchSanity(query, true)
356
482
  }
357
483
 
358
484
  /**
@@ -368,17 +494,12 @@ export async function fetchScheduledReleases(brand, {page = 1, limit = 10}) {
368
494
  * .catch(error => console.error(error));
369
495
  */
370
496
  export async function fetchByRailContentId(id, contentType) {
371
- const fields = getFieldsForContentType(contentType);
372
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
373
- const entityFieldsString = ` ${fields}
497
+ const fields = getFieldsForContentType(contentType)
498
+ const childFields = getChildFieldsForContentType(contentType)
499
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
500
+ const entityFieldsString = ` ${fields}
374
501
  'child_count': coalesce(count(child[${childrenFilter}]->), 0) ,
375
- "lessons": child[${childrenFilter}]->{
376
- "id": railcontent_id,
377
- title,
378
- "image": thumbnail.asset->url,
379
- "instructors": instructor[]->name,
380
- length_in_seconds,
381
- },
502
+ "lessons": child[${childrenFilter}]->{${childFields}},
382
503
  'length_in_seconds': coalesce(
383
504
  math::sum(
384
505
  select(
@@ -386,17 +507,17 @@ export async function fetchByRailContentId(id, contentType) {
386
507
  )
387
508
  ),
388
509
  length_in_seconds
389
- ),`;
510
+ ),`
390
511
 
391
- const query = buildRawQuery(
392
- `railcontent_id == ${id} &amp;&amp; _type == '${contentType}'`,
393
- entityFieldsString,
394
- {
395
- isSingle: true,
396
- },
397
- );
512
+ const query = buildRawQuery(
513
+ `railcontent_id == ${id} &amp;&amp; _type == '${contentType}'`,
514
+ entityFieldsString,
515
+ {
516
+ isSingle: true,
517
+ }
518
+ )
398
519
 
399
- return fetchSanity(query, false);
520
+ return fetchSanity(query, false)
400
521
  }
401
522
 
402
523
  /**
@@ -412,25 +533,28 @@ export async function fetchByRailContentId(id, contentType) {
412
533
  * .catch(error => console.error(error));
413
534
  */
414
535
  export async function fetchByRailContentIds(ids, contentType = undefined) {
415
- const idsString = ids.join(',');
536
+ if (!ids) {
537
+ return [];
538
+ }
539
+ const idsString = ids.join(',')
416
540
 
417
- const query = `*[railcontent_id in [${idsString}]]{
541
+ const query = `*[railcontent_id in [${idsString}]]{
418
542
  ${getFieldsForContentType(contentType)}
419
543
  }`
420
- const results = await fetchSanity(query, true);
421
-
422
- const sortFuction = function compare(a,b){
423
- const indexA = ids.indexOf(a['id']);
424
- const indexB = ids.indexOf(b['id'])
425
- if(indexA === indexB) return 0;
426
- if(indexA > indexB) return 1;
427
- return -1;
428
- }
544
+ const results = await fetchSanity(query, true)
545
+
546
+ const sortFuction = function compare(a, b) {
547
+ const indexA = ids.indexOf(a['id'])
548
+ const indexB = ids.indexOf(b['id'])
549
+ if (indexA === indexB) return 0
550
+ if (indexA > indexB) return 1
551
+ return -1
552
+ }
429
553
 
430
- // Sort results to match the order of the input IDs
431
- const sortedResults = results.sort(sortFuction);
554
+ // Sort results to match the order of the input IDs
555
+ const sortedResults = results.sort(sortFuction)
432
556
 
433
- return sortedResults;
557
+ return sortedResults
434
558
  }
435
559
 
436
560
  /**
@@ -465,88 +589,96 @@ export async function fetchByRailContentIds(ids, contentType = undefined) {
465
589
  * .then(content => console.log(content))
466
590
  * .catch(error => console.error(error));
467
591
  */
468
- export async function fetchAll(brand, type, {
592
+ export async function fetchAll(
593
+ brand,
594
+ type,
595
+ {
469
596
  page = 1,
470
597
  limit = 10,
471
- searchTerm = "",
472
- sort = "-published_on",
598
+ searchTerm = '',
599
+ sort = '-published_on',
473
600
  includedFields = [],
474
- groupBy = "",
601
+ groupBy = '',
475
602
  progressIds = undefined,
476
603
  useDefaultFields = true,
477
604
  customFields = [],
478
- progress = "all"
479
- } = {}) {
480
- let customResults = await handleCustomFetchAll(brand, type, {
481
- page,
482
- limit,
483
- searchTerm,
484
- sort,
485
- includedFields,
486
- groupBy,
487
- progressIds,
488
- useDefaultFields,
489
- customFields,
490
- progress
491
- });
492
- if (customResults) {
493
- return customResults;
494
- }
495
- console.log('rox fetch all ');
496
- let config = contentTypeConfig[type] ?? {};
497
- let additionalFields = config?.fields ?? [];
498
- let isGroupByOneToOne = (groupBy ? config?.relationships?.[groupBy]?.isOneToOne : false) ?? false;
499
- let webUrlPathType = config?.slug ?? type;
500
- const start = (page - 1) * limit;
501
- const end = start + limit;
502
- let bypassStatusAndPublishedValidation = (type == 'instructor' || groupBy == 'artist' || groupBy == 'genre' || groupBy == 'instructor');
503
- let bypassPermissions = bypassStatusAndPublishedValidation;
504
- // Construct the type filter
505
- let typeFilter;
506
-
507
- if (type === 'archives') {
508
- typeFilter = `&amp;&amp; status == "archived"`;
509
- bypassStatusAndPublishedValidation = true;
510
- } else if(type === 'pack'){
511
- typeFilter = `&amp;&amp; (_type == 'pack' || _type == 'semester-pack')`;
512
- } else {
513
- typeFilter = type ? `&amp;&amp; _type == '${type}'` : "";
514
- }
515
-
516
- // Construct the search filter
517
- const searchFilter = searchTerm
518
- ? groupBy !== "" ?
519
- `&amp;&amp; (^.name match "${searchTerm}*" || title match "${searchTerm}*")`
520
- : `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")`
521
- : "";
522
-
523
- // Construct the included fields filter, replacing 'difficulty' with 'difficulty_string'
524
- const includedFieldsFilter = includedFields.length > 0
525
- ? filtersToGroq(includedFields)
526
- : "";
527
-
528
- // limits the results to supplied progressIds for started &amp; completed filters
529
- const progressFilter = await getProgressFilter(progress, progressIds);
530
-
531
- // Determine the sort order
532
- const sortOrder = getSortOrder(sort, brand, groupBy);
533
-
534
- let fields = useDefaultFields ? customFields.concat(DEFAULT_FIELDS, additionalFields) : customFields;
535
- let fieldsString = fields.join(',');
536
-
537
- let customFilter = '';
538
- if (type == 'instructor') {
539
- customFilter = '&amp;&amp; coach_card_image != null'
540
- }
541
- // Determine the group by clause
542
- let query = "";
543
- let entityFieldsString = "";
544
- let filter = "";
545
- if (groupBy !== "" &amp;&amp; isGroupByOneToOne) {
546
- const webUrlPath = 'artists';
547
- const lessonsFilter = `_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter} ${customFilter}`;
548
- const lessonsFilterWithRestrictions = await new FilterBuilder(lessonsFilter).buildFilter();
549
- entityFieldsString = `
605
+ progress = 'all',
606
+ } = {}
607
+ ) {
608
+ let customResults = await handleCustomFetchAll(brand, type, {
609
+ page,
610
+ limit,
611
+ searchTerm,
612
+ sort,
613
+ includedFields,
614
+ groupBy,
615
+ progressIds,
616
+ useDefaultFields,
617
+ customFields,
618
+ progress,
619
+ })
620
+ if (customResults) {
621
+ return customResults
622
+ }
623
+ let config = contentTypeConfig[type] ?? {}
624
+ let additionalFields = config?.fields ?? []
625
+ let isGroupByOneToOne = (groupBy ? config?.relationships?.[groupBy]?.isOneToOne : false) ?? false
626
+ let webUrlPathType = config?.slug ?? type
627
+ const start = (page - 1) * limit
628
+ const end = start + limit
629
+ let bypassStatusAndPublishedValidation =
630
+ type == 'instructor' || groupBy == 'artist' || groupBy == 'genre' || groupBy == 'instructor'
631
+ let bypassPermissions = bypassStatusAndPublishedValidation
632
+ // Construct the type filter
633
+ let typeFilter
634
+
635
+ if (type === 'archives') {
636
+ typeFilter = `&amp;&amp; status == "archived"`
637
+ bypassStatusAndPublishedValidation = true
638
+ } else if (type === 'pack') {
639
+ typeFilter = `&amp;&amp; (_type == 'pack' || _type == 'semester-pack')`
640
+ } else {
641
+ typeFilter = type
642
+ ? `&amp;&amp; _type == '${type}'`
643
+ : progress === 'in progress' || progress === 'completed'
644
+ ? " &amp;&amp; (_type != 'challenge-part' &amp;&amp; _type != 'challenge')"
645
+ : ''
646
+ }
647
+
648
+ // Construct the search filter
649
+ const searchFilter = searchTerm
650
+ ? groupBy !== ''
651
+ ? `&amp;&amp; (^.name match "${searchTerm}*" || title match "${searchTerm}*")`
652
+ : `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")`
653
+ : ''
654
+
655
+ // Construct the included fields filter, replacing 'difficulty' with 'difficulty_string'
656
+ const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
657
+
658
+ // limits the results to supplied progressIds for started &amp; completed filters
659
+ const progressFilter = await getProgressFilter(progress, progressIds)
660
+
661
+ // Determine the sort order
662
+ const sortOrder = getSortOrder(sort, brand, groupBy)
663
+
664
+ let fields = useDefaultFields
665
+ ? customFields.concat(DEFAULT_FIELDS, additionalFields)
666
+ : customFields
667
+ let fieldsString = fields.join(',')
668
+
669
+ let customFilter = ''
670
+ if (type == 'instructor') {
671
+ customFilter = '&amp;&amp; coach_card_image != null'
672
+ }
673
+ // Determine the group by clause
674
+ let query = ''
675
+ let entityFieldsString = ''
676
+ let filter = ''
677
+ if (groupBy !== '' &amp;&amp; isGroupByOneToOne) {
678
+ const webUrlPath = 'artists'
679
+ const lessonsFilter = `_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter} ${customFilter}`
680
+ const lessonsFilterWithRestrictions = await new FilterBuilder(lessonsFilter).buildFilter()
681
+ entityFieldsString = `
550
682
  'id': railcontent_id,
551
683
  'type': _type,
552
684
  name,
@@ -557,16 +689,16 @@ console.log('rox fetch all ');
557
689
  ${fieldsString},
558
690
  ${groupBy}
559
691
  }[0...20]
560
- `;
561
- filter = `_type == '${groupBy}' &amp;&amp; count(*[${lessonsFilterWithRestrictions}]._id) > 0`;
562
- } else if (groupBy !== "") {
563
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
692
+ `
693
+ filter = `_type == '${groupBy}' &amp;&amp; count(*[${lessonsFilterWithRestrictions}]._id) > 0`
694
+ } else if (groupBy !== '') {
695
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
564
696
 
565
- const webUrlPath = (groupBy == 'genre') ? '/genres' : '';
566
- const lessonsFilter = `brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter} ${customFilter}`;
567
- const lessonsFilterWithRestrictions = await new FilterBuilder(lessonsFilter).buildFilter();
697
+ const webUrlPath = groupBy == 'genre' ? '/genres' : ''
698
+ const lessonsFilter = `brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter} ${customFilter}`
699
+ const lessonsFilterWithRestrictions = await new FilterBuilder(lessonsFilter).buildFilter()
568
700
 
569
- entityFieldsString = `
701
+ entityFieldsString = `
570
702
  'id': railcontent_id,
571
703
  'type': _type,
572
704
  name,
@@ -577,12 +709,12 @@ console.log('rox fetch all ');
577
709
  ${fieldsString},
578
710
  'lesson_count': coalesce(count(child[${childrenFilter}]->), 0) ,
579
711
  ${groupBy}
580
- }[0...20]`;
581
- filter = `_type == '${groupBy}' &amp;&amp; count(*[${lessonsFilterWithRestrictions}]._id) > 0`;
582
- } else {
583
- filter = `brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter} ${customFilter}`
584
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
585
- entityFieldsString = ` ${fieldsString},
712
+ }[0...20]`
713
+ filter = `_type == '${groupBy}' &amp;&amp; count(*[${lessonsFilterWithRestrictions}]._id) > 0`
714
+ } else {
715
+ filter = `brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter} ${customFilter}`
716
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
717
+ entityFieldsString = ` ${fieldsString},
586
718
  'lesson_count': coalesce(count(child[${childrenFilter}]->), 0) ,
587
719
  'length_in_seconds': coalesce(
588
720
  math::sum(
@@ -591,24 +723,21 @@ console.log('rox fetch all ');
591
723
  )
592
724
  ),
593
725
  length_in_seconds
594
- ),`;
595
- }
596
-
597
- const filterWithRestrictions = await new FilterBuilder(filter, {
598
- bypassStatuses: bypassStatusAndPublishedValidation,
599
- bypassPermissions: bypassPermissions,
600
- bypassPublishedDateRestriction: bypassStatusAndPublishedValidation
601
- }).buildFilter();
602
- query = buildEntityAndTotalQuery(
603
- filterWithRestrictions,
604
- entityFieldsString,
605
- {
606
- sortOrder: sortOrder,
607
- start: start,
608
- end: end,
609
- });
610
-
611
- return fetchSanity(query, true);
726
+ ),`
727
+ }
728
+
729
+ const filterWithRestrictions = await new FilterBuilder(filter, {
730
+ bypassStatuses: bypassStatusAndPublishedValidation,
731
+ bypassPermissions: bypassPermissions,
732
+ bypassPublishedDateRestriction: bypassStatusAndPublishedValidation,
733
+ }).buildFilter()
734
+ query = buildEntityAndTotalQuery(filterWithRestrictions, entityFieldsString, {
735
+ sortOrder: sortOrder,
736
+ start: start,
737
+ end: end,
738
+ })
739
+
740
+ return fetchSanity(query, true)
612
741
  }
613
742
 
614
743
  /**
@@ -628,83 +757,110 @@ console.log('rox fetch all ');
628
757
  * @param {string} [params.progress="all"] - An string representing which progress filter to use ("all", "in progress", "complete", "not started").
629
758
  * @returns {Promise&lt;Object|null>} - The fetched content data or null if not found.
630
759
  */
631
- async function handleCustomFetchAll(brand, type, {
760
+ async function handleCustomFetchAll(
761
+ brand,
762
+ type,
763
+ {
632
764
  page = 1,
633
765
  limit = 10,
634
- searchTerm = "",
635
- sort = "-published_on",
766
+ searchTerm = '',
767
+ sort = '-published_on',
636
768
  includedFields = [],
637
- groupBy = "",
769
+ groupBy = '',
638
770
  progressIds = undefined,
639
771
  useDefaultFields = true,
640
772
  customFields = [],
641
- progress = "all"
642
- } = {}) {
643
- if (type === 'challenge') {
644
- if (groupBy === 'completed') {
645
- const completedIds = await fetchCompletedChallenges(brand, page, limit);
646
- return fetchAll(brand, type,
647
- {
648
- page,
649
- limit,
650
- searchTerm,
651
- sort,
652
- includedFields,
653
- groupBy: '',
654
- progressIds: completedIds,
655
- useDefaultFields,
656
- customFields,
657
- progress
658
- });
659
- } else if (groupBy === 'owned') {
660
- const ownedIds = await fetchOwnedChallenges(brand, page, limit);
661
- return fetchAll(brand, type,
662
- {
663
- page,
664
- limit,
665
- searchTerm,
666
- sort,
667
- includedFields,
668
- groupBy: '',
669
- progressIds: ownedIds,
670
- useDefaultFields,
671
- customFields,
672
- progress
673
- });
674
- } else if (groupBy === 'difficulty_string') {
675
- return fetchChallengesByDifficulty(brand, type, page, limit, searchTerm, sort, includedFields, groupBy, progressIds, useDefaultFields, customFields, progress);
676
- }
773
+ progress = 'all',
774
+ } = {}
775
+ ) {
776
+ if (type === 'challenge') {
777
+ if (groupBy === 'completed') {
778
+ const completedIds = await fetchCompletedChallenges(brand, page, limit)
779
+ return fetchAll(brand, type, {
780
+ page,
781
+ limit,
782
+ searchTerm,
783
+ sort,
784
+ includedFields,
785
+ groupBy: '',
786
+ progressIds: completedIds,
787
+ useDefaultFields,
788
+ customFields,
789
+ progress,
790
+ })
791
+ } else if (groupBy === 'owned') {
792
+ const ownedIds = await fetchOwnedChallenges(brand, page, limit)
793
+ return fetchAll(brand, type, {
794
+ page,
795
+ limit,
796
+ searchTerm,
797
+ sort,
798
+ includedFields,
799
+ groupBy: '',
800
+ progressIds: ownedIds,
801
+ useDefaultFields,
802
+ customFields,
803
+ progress,
804
+ })
805
+ } else if (groupBy === 'difficulty_string') {
806
+ return fetchChallengesByDifficulty(
807
+ brand,
808
+ type,
809
+ page,
810
+ limit,
811
+ searchTerm,
812
+ sort,
813
+ includedFields,
814
+ groupBy,
815
+ progressIds,
816
+ useDefaultFields,
817
+ customFields,
818
+ progress
819
+ )
677
820
  }
678
- return null;
821
+ }
822
+ return null
679
823
  }
680
824
 
681
- async function fetchChallengesByDifficulty(brand, type, page, limit, searchTerm, sort, includedFields, groupBy, progressIds, useDefaultFields, customFields, progress) {
682
- let config = contentTypeConfig['challenge'] ?? {};
683
- let additionalFields = config?.fields ?? [];
684
-
685
- // Construct the search filter
686
- const searchFilter = searchTerm
687
- ? groupBy !== "" ?
688
- `&amp;&amp; (^.name match "${searchTerm}*" || title match "${searchTerm}*")`
689
- : `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")`
690
- : "";
825
+ async function fetchChallengesByDifficulty(
826
+ brand,
827
+ type,
828
+ page,
829
+ limit,
830
+ searchTerm,
831
+ sort,
832
+ includedFields,
833
+ groupBy,
834
+ progressIds,
835
+ useDefaultFields,
836
+ customFields,
837
+ progress
838
+ ) {
839
+ let config = contentTypeConfig['challenge'] ?? {}
840
+ let additionalFields = config?.fields ?? []
691
841
 
692
- // Construct the included fields filter, replacing 'difficulty' with 'difficulty_string'
693
- const includedFieldsFilter = includedFields.length > 0
694
- ? filtersToGroq(includedFields)
695
- : "";
842
+ // Construct the search filter
843
+ const searchFilter = searchTerm
844
+ ? groupBy !== ''
845
+ ? `&amp;&amp; (^.name match "${searchTerm}*" || title match "${searchTerm}*")`
846
+ : `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")`
847
+ : ''
696
848
 
697
- // limits the results to supplied progressIds for started &amp; completed filters
698
- const progressFilter = await getProgressFilter(progress, progressIds);
849
+ // Construct the included fields filter, replacing 'difficulty' with 'difficulty_string'
850
+ const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
699
851
 
700
- let fields = useDefaultFields ? customFields.concat(DEFAULT_FIELDS, additionalFields) : customFields;
701
- let fieldsString = fields.join(',');
852
+ // limits the results to supplied progressIds for started &amp; completed filters
853
+ const progressFilter = await getProgressFilter(progress, progressIds)
702
854
 
855
+ let fields = useDefaultFields
856
+ ? customFields.concat(DEFAULT_FIELDS, additionalFields)
857
+ : customFields
858
+ let fieldsString = fields.join(',')
703
859
 
704
- const lessonsFilter = `_type == 'challenge' &amp;&amp; brand == '${brand}' &amp;&amp; ^.name == difficulty_string ${searchFilter} ${includedFieldsFilter} ${progressFilter}`;
705
- const lessonsFilterWithRestrictions = await new FilterBuilder(lessonsFilter).buildFilter();
860
+ const lessonsFilter = `_type == 'challenge' &amp;&amp; brand == '${brand}' &amp;&amp; ^.name == difficulty_string ${searchFilter} ${includedFieldsFilter} ${progressFilter}`
861
+ const lessonsFilterWithRestrictions = await new FilterBuilder(lessonsFilter).buildFilter()
706
862
 
707
- const query = `{
863
+ const query = `{
708
864
  "entity": [
709
865
  {"name": "All"},
710
866
  {"name": "Novice"},
@@ -722,62 +878,61 @@ async function fetchChallengesByDifficulty(brand, type, page, limit, searchTerm,
722
878
  }[0...20]
723
879
  },
724
880
  "total": 0
725
- }`;
726
- let data = await fetchSanity(query, true);
727
- data.entity = data.entity.filter(function (difficulty) {
728
- return difficulty.lessons.length > 0;
729
- });
730
- return data;
881
+ }`
882
+ let data = await fetchSanity(query, true)
883
+ data.entity = data.entity.filter(function (difficulty) {
884
+ return difficulty.lessons.length > 0
885
+ })
886
+ return data
731
887
  }
732
888
 
733
889
  async function getProgressFilter(progress, progressIds) {
734
- switch (progress) {
735
- case "all":
736
- return progressIds !== undefined ?
737
- `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
738
- case "in progress": {
739
- const ids = await getAllStarted();
740
- return `&amp;&amp; railcontent_id in [${ids.join(',')}]`;
741
- }
742
- case "completed": {
743
- const ids = await getAllCompleted();
744
- return `&amp;&amp; railcontent_id in [${ids.join(',')}]`;
745
- }
746
- case "not started": {
747
- const ids = await getAllStartedOrCompleted();
748
- return `&amp;&amp; !(railcontent_id in [${ids.join(',')}])`;
749
- }
750
- default:
751
- throw new Error(`'${progress}' progress option not implemented`);
890
+ switch (progress) {
891
+ case 'all':
892
+ return progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
893
+ case 'in progress': {
894
+ const ids = await getAllStarted()
895
+ return `&amp;&amp; railcontent_id in [${ids.join(',')}]`
896
+ }
897
+ case 'completed': {
898
+ const ids = await getAllCompleted()
899
+ return `&amp;&amp; railcontent_id in [${ids.join(',')}]`
752
900
  }
901
+ case 'not started': {
902
+ const ids = await getAllStartedOrCompleted()
903
+ return `&amp;&amp; !(railcontent_id in [${ids.join(',')}])`
904
+ }
905
+ default:
906
+ throw new Error(`'${progress}' progress option not implemented`)
907
+ }
753
908
  }
754
909
 
755
910
  export function getSortOrder(sort = '-published_on', brand, groupBy) {
756
- // Determine the sort order
757
- let sortOrder = '';
758
- const isDesc = sort.startsWith('-');
759
- sort = isDesc ? sort.substring(1) : sort;
760
- switch (sort) {
761
- case "slug":
762
- sortOrder = groupBy ? 'name' : "title";
763
- break;
764
- case "name":
765
- sortOrder = sort;
766
- break;
767
- case "popularity":
768
- if (groupBy == "artist" || groupBy == "genre") {
769
- sortOrder = isDesc ? `coalesce(popularity.${brand}, -1)` : "popularity";
770
- } else {
771
- sortOrder = isDesc ? "coalesce(popularity, -1)" : "popularity";
772
- }
773
- break;
774
- case "published_on":
775
- default:
776
- sortOrder = "published_on";
777
- break;
778
- }
779
- sortOrder += isDesc ? ' desc' : ' asc';
780
- return sortOrder;
911
+ // Determine the sort order
912
+ let sortOrder = ''
913
+ const isDesc = sort.startsWith('-')
914
+ sort = isDesc ? sort.substring(1) : sort
915
+ switch (sort) {
916
+ case 'slug':
917
+ sortOrder = groupBy ? 'name' : 'title'
918
+ break
919
+ case 'name':
920
+ sortOrder = sort
921
+ break
922
+ case 'popularity':
923
+ if (groupBy == 'artist' || groupBy == 'genre') {
924
+ sortOrder = isDesc ? `coalesce(popularity.${brand}, -1)` : 'popularity'
925
+ } else {
926
+ sortOrder = isDesc ? 'coalesce(popularity, -1)' : 'popularity'
927
+ }
928
+ break
929
+ case 'published_on':
930
+ default:
931
+ sortOrder = 'published_on'
932
+ break
933
+ }
934
+ sortOrder += isDesc ? ' desc' : ' asc'
935
+ return sortOrder
781
936
  }
782
937
 
783
938
  /**
@@ -812,42 +967,48 @@ export function getSortOrder(sort = '-published_on', brand, groupBy) {
812
967
  * .catch(error => console.error(error));
813
968
  */
814
969
  export async function fetchAllFilterOptions(
815
- brand,
816
- filters = [],
817
- style,
818
- artist,
819
- contentType,
820
- term,
821
- progressIds,
822
- coachId,
823
- includeTabs = false,
970
+ brand,
971
+ filters = [],
972
+ style,
973
+ artist,
974
+ contentType,
975
+ term,
976
+ progressIds,
977
+ coachId,
978
+ includeTabs = false
824
979
  ) {
825
- if (coachId &amp;&amp; contentType !== 'coach-lessons') {
826
- throw new Error(`Invalid contentType: '${contentType}' for coachId. It must be 'coach-lessons'.`);
827
- }
828
-
829
- const includedFieldsFilter = filters?.length ? filtersToGroq(filters) : undefined;
830
- const progressFilter = progressIds ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
831
- const isAdmin = (await fetchUserPermissions()).isAdmin;
832
-
833
- const constructCommonFilter = (excludeFilter) => {
834
- const filterWithoutOption = excludeFilter ? filtersToGroq(filters, excludeFilter) : includedFieldsFilter;
835
- const statusFilter = ' &amp;&amp; status == "published"';
836
- const includeStatusFilter = !isAdmin &amp;&amp; !['instructor', 'artist', 'genre'].includes(contentType);
837
-
838
- return coachId
839
- ? `brand == '${brand}' &amp;&amp; status == "published" &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${coachId}]._id) ${filterWithoutOption || ''} ${term ? ` &amp;&amp; (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}`
840
- : `_type == '${contentType}' &amp;&amp; brand == "${brand}"${includeStatusFilter ? statusFilter : ''}${style &amp;&amp; excludeFilter !== "style" ? ` &amp;&amp; '${style}' in genre[]->name` : ''}${artist &amp;&amp; excludeFilter !== "artist" ? ` &amp;&amp; artist->name == '${artist}'` : ''} ${progressFilter} ${filterWithoutOption || ''} ${term ? ` &amp;&amp; (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}`;
841
- };
842
-
843
- const metaData = processMetadata(brand, contentType, true);
844
- const allowableFilters = metaData?.allowableFilters || [];
845
- const tabs = metaData?.tabs || [];
846
- const catalogName = metaData?.shortname || metaData?.name;
847
-
848
- const dynamicFilterOptions = allowableFilters.map(filter => getFilterOptions(filter, constructCommonFilter(filter), contentType, brand)).join(' ');
849
-
850
- const query = `
980
+ if (coachId &amp;&amp; contentType !== 'coach-lessons') {
981
+ throw new Error(
982
+ `Invalid contentType: '${contentType}' for coachId. It must be 'coach-lessons'.`
983
+ )
984
+ }
985
+
986
+ const includedFieldsFilter = filters?.length ? filtersToGroq(filters) : undefined
987
+ const progressFilter = progressIds ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
988
+ const isAdmin = (await fetchUserPermissions()).isAdmin
989
+
990
+ const constructCommonFilter = (excludeFilter) => {
991
+ const filterWithoutOption = excludeFilter
992
+ ? filtersToGroq(filters, excludeFilter)
993
+ : includedFieldsFilter
994
+ const statusFilter = ' &amp;&amp; status == "published"'
995
+ const includeStatusFilter = !isAdmin &amp;&amp; !['instructor', 'artist', 'genre'].includes(contentType)
996
+
997
+ return coachId
998
+ ? `brand == '${brand}' &amp;&amp; status == "published" &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${coachId}]._id) ${filterWithoutOption || ''} ${term ? ` &amp;&amp; (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}`
999
+ : `_type == '${contentType}' &amp;&amp; brand == "${brand}"${includeStatusFilter ? statusFilter : ''}${style &amp;&amp; excludeFilter !== 'style' ? ` &amp;&amp; '${style}' in genre[]->name` : ''}${artist &amp;&amp; excludeFilter !== 'artist' ? ` &amp;&amp; artist->name == '${artist}'` : ''} ${progressFilter} ${filterWithoutOption || ''} ${term ? ` &amp;&amp; (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}`
1000
+ }
1001
+
1002
+ const metaData = processMetadata(brand, contentType, true)
1003
+ const allowableFilters = metaData?.allowableFilters || []
1004
+ const tabs = metaData?.tabs || []
1005
+ const catalogName = metaData?.shortname || metaData?.name
1006
+
1007
+ const dynamicFilterOptions = allowableFilters
1008
+ .map((filter) => getFilterOptions(filter, constructCommonFilter(filter), contentType, brand))
1009
+ .join(' ')
1010
+
1011
+ const query = `
851
1012
  {
852
1013
  "meta": {
853
1014
  "totalResults": count(*[${constructCommonFilter()}
@@ -856,11 +1017,11 @@ export async function fetchAllFilterOptions(
856
1017
  ${dynamicFilterOptions}
857
1018
  }
858
1019
  }
859
- }`;
1020
+ }`
860
1021
 
861
- const results = await fetchSanity(query, true, {processNeedAccess: false});
1022
+ const results = await fetchSanity(query, true, { processNeedAccess: false })
862
1023
 
863
- return includeTabs ? {...results, tabs, catalogName} : results;
1024
+ return includeTabs ? { ...results, tabs, catalogName } : results
864
1025
  }
865
1026
 
866
1027
  /**
@@ -869,17 +1030,17 @@ export async function fetchAllFilterOptions(
869
1030
  * @returns {Promise&lt;Object|null>} - The fetched foundation data or null if not found.
870
1031
  */
871
1032
  export async function fetchFoundation(slug) {
872
- const filterParams = {};
873
- const query = await buildQuery(
874
- `_type == 'foundation' &amp;&amp; slug.current == "${slug}"`,
875
- filterParams,
876
- getFieldsForContentType('foundation'),
877
- {
878
- sortOrder: 'published_on asc',
879
- isSingle: true,
880
- }
881
- );
882
- return fetchSanity(query, false);
1033
+ const filterParams = {}
1034
+ const query = await buildQuery(
1035
+ `_type == 'foundation' &amp;&amp; slug.current == "${slug}"`,
1036
+ filterParams,
1037
+ getFieldsForContentType('foundation'),
1038
+ {
1039
+ sortOrder: 'published_on asc',
1040
+ isSingle: true,
1041
+ }
1042
+ )
1043
+ return fetchSanity(query, false)
883
1044
  }
884
1045
 
885
1046
  /**
@@ -889,9 +1050,9 @@ export async function fetchFoundation(slug) {
889
1050
  * @returns {Promise&lt;Object|null>} - The fetched methods data or null if not found.
890
1051
  */
891
1052
  export async function fetchMethod(brand, slug) {
892
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
1053
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
893
1054
 
894
- const query = `*[_type == 'learning-path' &amp;&amp; brand == "${brand}" &amp;&amp; slug.current == "${slug}"] {
1055
+ const query = `*[_type == 'learning-path' &amp;&amp; brand == "${brand}" &amp;&amp; slug.current == "${slug}"] {
895
1056
  "description": ${descriptionField},
896
1057
  "instructors":instructor[]->name,
897
1058
  published_on,
@@ -928,7 +1089,7 @@ export async function fetchMethod(brand, slug) {
928
1089
  total_xp
929
1090
  }
930
1091
  } | order(published_on asc)`
931
- return fetchSanity(query, false);
1092
+ return fetchSanity(query, false)
932
1093
  }
933
1094
 
934
1095
  /**
@@ -937,9 +1098,9 @@ export async function fetchMethod(brand, slug) {
937
1098
  * @returns {Promise&lt;Object|null>} - The fetched next lesson data or null if not found.
938
1099
  */
939
1100
  export async function fetchMethodChildren(railcontentId) {
940
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
1101
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
941
1102
 
942
- const query = `*[railcontent_id == ${railcontentId}]{
1103
+ const query = `*[railcontent_id == ${railcontentId}]{
943
1104
  "child_count":coalesce(count(child[${childrenFilter}]->), 0),
944
1105
  "id": railcontent_id,
945
1106
  "description": ${descriptionField},
@@ -957,8 +1118,8 @@ export async function fetchMethodChildren(railcontentId) {
957
1118
  'children': child[(${childrenFilter})]->{
958
1119
  ${getFieldsForContentType('method')}
959
1120
  },
960
- }[0..1]`;
961
- return fetchSanity(query, true);
1121
+ }[0..1]`
1122
+ return fetchSanity(query, true)
962
1123
  }
963
1124
 
964
1125
  /**
@@ -972,21 +1133,21 @@ export async function fetchMethodChildren(railcontentId) {
972
1133
  * .catch(error => console.error(error));
973
1134
  */
974
1135
  export async function fetchMethodPreviousNextLesson(railcontentId, methodId) {
975
- const sortedChildren = await fetchMethodChildrenIds(methodId);
976
- const index = sortedChildren.indexOf(Number(railcontentId));
977
- let nextId = sortedChildren[index + 1];
978
- let previousId = sortedChildren[index - 1];
979
- let ids = [];
980
- if (nextId) ids.push(nextId);
981
- if (previousId) ids.push(previousId);
982
- let nextPrev = await fetchByRailContentIds(ids);
983
- const nextLesson = nextPrev.find((elem) => {
984
- return elem['id'] === nextId
985
- });
986
- const prevLesson = nextPrev.find((elem) => {
987
- return elem['id'] === previousId
988
- });
989
- return {nextLesson, prevLesson};
1136
+ const sortedChildren = await fetchMethodChildrenIds(methodId)
1137
+ const index = sortedChildren.indexOf(Number(railcontentId))
1138
+ let nextId = sortedChildren[index + 1]
1139
+ let previousId = sortedChildren[index - 1]
1140
+ let ids = []
1141
+ if (nextId) ids.push(nextId)
1142
+ if (previousId) ids.push(previousId)
1143
+ let nextPrev = await fetchByRailContentIds(ids)
1144
+ const nextLesson = nextPrev.find((elem) => {
1145
+ return elem['id'] === nextId
1146
+ })
1147
+ const prevLesson = nextPrev.find((elem) => {
1148
+ return elem['id'] === previousId
1149
+ })
1150
+ return { nextLesson, prevLesson }
990
1151
  }
991
1152
 
992
1153
  /**
@@ -995,9 +1156,9 @@ export async function fetchMethodPreviousNextLesson(railcontentId, methodId) {
995
1156
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children data or null if not found.
996
1157
  */
997
1158
  export async function fetchMethodChildrenIds(railcontentId) {
998
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
1159
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
999
1160
 
1000
- const query = `*[ railcontent_id == ${railcontentId}]{
1161
+ const query = `*[ railcontent_id == ${railcontentId}]{
1001
1162
  'children': child[${childrenFilter}]-> {
1002
1163
  'id': railcontent_id,
1003
1164
  'type' : _type,
@@ -1010,22 +1171,22 @@ export async function fetchMethodChildrenIds(railcontentId) {
1010
1171
  }
1011
1172
  }
1012
1173
  }
1013
- }`;
1014
- let allChildren = await fetchSanity(query, false);
1015
- return getChildrenToDepth(allChildren, 4);
1174
+ }`
1175
+ let allChildren = await fetchSanity(query, false)
1176
+ return getChildrenToDepth(allChildren, 4)
1016
1177
  }
1017
1178
 
1018
1179
  function getChildrenToDepth(parent, depth = 1) {
1019
- let allChildrenIds = [];
1020
- if (parent &amp;&amp; parent['children'] &amp;&amp; depth > 0) {
1021
- parent['children'].forEach((child) => {
1022
- if (!child['children']) {
1023
- allChildrenIds.push(child['id']);
1024
- }
1025
- allChildrenIds = allChildrenIds.concat(getChildrenToDepth(child, depth - 1));
1026
- })
1027
- }
1028
- return allChildrenIds;
1180
+ let allChildrenIds = []
1181
+ if (parent &amp;&amp; parent['children'] &amp;&amp; depth > 0) {
1182
+ parent['children'].forEach((child) => {
1183
+ if (!child['children']) {
1184
+ allChildrenIds.push(child['id'])
1185
+ }
1186
+ allChildrenIds = allChildrenIds.concat(getChildrenToDepth(child, depth - 1))
1187
+ })
1188
+ }
1189
+ return allChildrenIds
1029
1190
  }
1030
1191
 
1031
1192
  /**
@@ -1034,31 +1195,31 @@ function getChildrenToDepth(parent, depth = 1) {
1034
1195
  * @returns {Promise&lt;Object|null>} - The fetched next and previous lesson data or null if found.
1035
1196
  */
1036
1197
  export async function fetchNextPreviousLesson(railcontentId) {
1037
- const document = await fetchLessonContent(railcontentId);
1038
- if (document.parent_content_data &amp;&amp; document.parent_content_data.length > 0) {
1039
- const lastElement = document.parent_content_data[document.parent_content_data.length - 1];
1040
- const results = await fetchMethodPreviousNextLesson(railcontentId, lastElement.id);
1041
- return results;
1042
- }
1043
- const processedData = processMetadata(document.brand, document.type, true);
1044
- let sortBy = processedData?.sortBy ?? 'published_on';
1045
- const isDesc = sortBy.startsWith('-');
1046
- sortBy = isDesc ? sortBy.substring(1) : sortBy;
1047
- let sortValue = document[sortBy];
1048
- if (sortValue == null) {
1049
- sortBy = 'railcontent_id';
1050
- sortValue = document['railcontent_id'];
1051
- }
1052
- const isNumeric = !isNaN(sortValue);
1053
- let prevComparison = isNumeric ? `${sortBy} &lt;= ${sortValue}` : `${sortBy} &lt;= "${sortValue}"`;
1054
- let nextComparison = isNumeric ? `${sortBy} >= ${sortValue}` : `${sortBy} >= "${sortValue}"`;
1055
- const fields = getFieldsForContentType(document.type);
1056
- const query = `{
1198
+ const document = await fetchLessonContent(railcontentId)
1199
+ if (document.parent_content_data &amp;&amp; document.parent_content_data.length > 0) {
1200
+ const lastElement = document.parent_content_data[document.parent_content_data.length - 1]
1201
+ const results = await fetchMethodPreviousNextLesson(railcontentId, lastElement.id)
1202
+ return results
1203
+ }
1204
+ const processedData = processMetadata(document.brand, document.type, true)
1205
+ let sortBy = processedData?.sortBy ?? 'published_on'
1206
+ const isDesc = sortBy.startsWith('-')
1207
+ sortBy = isDesc ? sortBy.substring(1) : sortBy
1208
+ let sortValue = document[sortBy]
1209
+ if (sortValue == null) {
1210
+ sortBy = 'railcontent_id'
1211
+ sortValue = document['railcontent_id']
1212
+ }
1213
+ const isNumeric = !isNaN(sortValue)
1214
+ let prevComparison = isNumeric ? `${sortBy} &lt;= ${sortValue}` : `${sortBy} &lt;= "${sortValue}"`
1215
+ let nextComparison = isNumeric ? `${sortBy} >= ${sortValue}` : `${sortBy} >= "${sortValue}"`
1216
+ const fields = getFieldsForContentType(document.type)
1217
+ const query = `{
1057
1218
  "prevLesson": *[brand == "${document.brand}" &amp;&amp; status == "${document.status}" &amp;&amp; _type == "${document.type}" &amp;&amp; ${prevComparison} &amp;&amp; railcontent_id != ${railcontentId}] | order(${sortBy} desc){${fields}}[0...1][0],
1058
1219
  "nextLesson": *[brand == "${document.brand}" &amp;&amp; status == "${document.status}" &amp;&amp; _type == "${document.type}" &amp;&amp; ${nextComparison} &amp;&amp; railcontent_id != ${railcontentId}] | order(${sortBy} asc){${fields}}[0...1][0]
1059
- }`;
1220
+ }`
1060
1221
 
1061
- return await fetchSanity(query, true);
1222
+ return await fetchSanity(query, true)
1062
1223
  }
1063
1224
 
1064
1225
  /**
@@ -1071,12 +1232,12 @@ export async function fetchNextPreviousLesson(railcontentId) {
1071
1232
  * .catch(error => console.error(error));
1072
1233
  */
1073
1234
  export async function jumpToContinueContent(railcontentId) {
1074
- const nextContent = await fetchNextContentDataForParent(railcontentId);
1075
- if (!nextContent || !nextContent.id) {
1076
- return null;
1077
- }
1078
- let next = await fetchByRailContentId(nextContent.id, nextContent.type);
1079
- return {next};
1235
+ const nextContent = await fetchNextContentDataForParent(railcontentId)
1236
+ if (!nextContent || !nextContent.id) {
1237
+ return null
1238
+ }
1239
+ let next = await fetchByRailContentId(nextContent.id, nextContent.type)
1240
+ return { next }
1080
1241
  }
1081
1242
 
1082
1243
  /**
@@ -1090,11 +1251,11 @@ export async function jumpToContinueContent(railcontentId) {
1090
1251
  * .catch(error => console.error(error));
1091
1252
  */
1092
1253
  export async function fetchLessonContent(railContentId) {
1093
- const filterParams = {isSingle: true, pullFutureContent: true};
1094
- // Format changes made to the `fields` object may also need to be reflected in Musora-web-platform SanityGateway.php $fields object
1095
- // Currently only for challenges and challenge lessons
1096
- // If you're unsure, message Adrian, or just add them.
1097
- const fields = `title,
1254
+ const filterParams = { isSingle: true, pullFutureContent: true }
1255
+ // Format changes made to the `fields` object may also need to be reflected in Musora-web-platform SanityGateway.php $fields object
1256
+ // Currently only for challenges and challenge lessons
1257
+ // If you're unsure, message Adrian, or just add them.
1258
+ const fields = `title,
1098
1259
  published_on,
1099
1260
  "type":_type,
1100
1261
  "resources": ${resourcesField},
@@ -1142,16 +1303,11 @@ export async function fetchLessonContent(railContentId) {
1142
1303
  "type": *[railcontent_id == ^.id][0]._type,
1143
1304
  },
1144
1305
  sort,
1145
- xp`;
1146
- const query = await buildQuery(
1147
- `railcontent_id == ${railContentId}`,
1148
- filterParams,
1149
- fields,
1150
- {
1151
- isSingle: true,
1152
- }
1153
- );
1154
- return fetchSanity(query, false);
1306
+ xp`
1307
+ const query = await buildQuery(`railcontent_id == ${railContentId}`, filterParams, fields, {
1308
+ isSingle: true,
1309
+ })
1310
+ return fetchSanity(query, false)
1155
1311
  }
1156
1312
 
1157
1313
  /**
@@ -1161,14 +1317,22 @@ export async function fetchLessonContent(railContentId) {
1161
1317
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons data or null if not found.
1162
1318
  */
1163
1319
  export async function fetchRelatedLessons(railContentId, brand) {
1164
- const filterSameTypeAndSortOrder = await new FilterBuilder(`_type==^._type &amp;&amp; _type in ${JSON.stringify(typeWithSortOrder)} &amp;&amp; brand == "${brand}" &amp;&amp; railcontent_id !=${railContentId}`).buildFilter();
1165
- const filterSameType = await new FilterBuilder(`_type==^._type &amp;&amp; !(_type in ${JSON.stringify(typeWithSortOrder)}) &amp;&amp; !(defined(parent_type)) &amp;&amp; brand == "${brand}" &amp;&amp; railcontent_id !=${railContentId}`).buildFilter();
1166
- const filterSongSameArtist = await new FilterBuilder(`_type=="song" &amp;&amp; _type==^._type &amp;&amp; brand == "${brand}" &amp;&amp; references(^.artist->_id) &amp;&amp; railcontent_id !=${railContentId}`).buildFilter();
1167
- const filterSongSameGenre = await new FilterBuilder(`_type=="song" &amp;&amp; _type==^._type &amp;&amp; brand == "${brand}" &amp;&amp; references(^.genre[]->_id) &amp;&amp; railcontent_id !=${railContentId}`).buildFilter();
1168
- const filterNeighbouringSiblings = await new FilterBuilder(`references(^._id)`).buildFilter();
1169
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
1170
-
1171
- const query = `*[railcontent_id == ${railContentId} &amp;&amp; brand == "${brand}" &amp;&amp; (!defined(permission) || references(*[_type=='permission']._id))]{
1320
+ const filterSameTypeAndSortOrder = await new FilterBuilder(
1321
+ `_type==^._type &amp;&amp; _type in ${JSON.stringify(typeWithSortOrder)} &amp;&amp; brand == "${brand}" &amp;&amp; railcontent_id !=${railContentId}`
1322
+ ).buildFilter()
1323
+ const filterSameType = await new FilterBuilder(
1324
+ `_type==^._type &amp;&amp; !(_type in ${JSON.stringify(typeWithSortOrder)}) &amp;&amp; !(defined(parent_type)) &amp;&amp; brand == "${brand}" &amp;&amp; railcontent_id !=${railContentId}`
1325
+ ).buildFilter()
1326
+ const filterSongSameArtist = await new FilterBuilder(
1327
+ `_type=="song" &amp;&amp; _type==^._type &amp;&amp; brand == "${brand}" &amp;&amp; references(^.artist->_id) &amp;&amp; railcontent_id !=${railContentId}`
1328
+ ).buildFilter()
1329
+ const filterSongSameGenre = await new FilterBuilder(
1330
+ `_type=="song" &amp;&amp; _type==^._type &amp;&amp; brand == "${brand}" &amp;&amp; references(^.genre[]->_id) &amp;&amp; railcontent_id !=${railContentId}`
1331
+ ).buildFilter()
1332
+ const filterNeighbouringSiblings = await new FilterBuilder(`references(^._id)`).buildFilter()
1333
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
1334
+
1335
+ const query = `*[railcontent_id == ${railContentId} &amp;&amp; brand == "${brand}" &amp;&amp; (!defined(permission) || references(*[_type=='permission']._id))]{
1172
1336
  _type, parent_type, railcontent_id,
1173
1337
  "related_lessons" : array::unique([
1174
1338
  ...(*[${filterNeighbouringSiblings}][0].child[${childrenFilter}]->{_id, "id":railcontent_id, published_on, "instructor": instructor[0]->name, title, "thumbnail_url":thumbnail.asset->url, length_in_seconds, web_url_path, "type": _type, difficulty, difficulty_string, railcontent_id, artist->,"permission_id": permission[]->railcontent_id,_type}),
@@ -1177,8 +1341,8 @@ export async function fetchRelatedLessons(railContentId, brand) {
1177
1341
  ...(*[${filterSameTypeAndSortOrder}]{_id, "id":railcontent_id, published_on, "instructor": instructor[0]->name, title, "thumbnail_url":thumbnail.asset->url, length_in_seconds, web_url_path, "type": _type, difficulty, difficulty_string, railcontent_id, artist->,"permission_id": permission[]->railcontent_id,_type, sort}|order(sort asc, title asc)[0...10]),
1178
1342
  ...(*[${filterSameType}]{_id, "id":railcontent_id, published_on, "instructor": instructor[0]->name, title, "thumbnail_url":thumbnail.asset->url, length_in_seconds, web_url_path, "type": _type, difficulty, difficulty_string, railcontent_id, artist->,"permission_id": permission[]->railcontent_id,_type}|order(published_on desc, title asc)[0...10])
1179
1343
  ,
1180
- ])[0...10]}`;
1181
- return fetchSanity(query, false);
1344
+ ])[0...10]}`
1345
+ return fetchSanity(query, false)
1182
1346
  }
1183
1347
 
1184
1348
  /**
@@ -1190,26 +1354,27 @@ export async function fetchRelatedLessons(railContentId, brand) {
1190
1354
  * @param {number} [params.limit=10] - The number of items per page.
1191
1355
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
1192
1356
  */
1193
- export async function fetchAllPacks(brand, sort = "-published_on", searchTerm = "", page = 1, limit = 10) {
1194
- const sortOrder = getSortOrder(sort, brand);
1195
- const filter = `(_type == 'pack' || _type == 'semester-pack') &amp;&amp; brand == '${brand}' &amp;&amp; title match "${searchTerm}*"`
1196
- const filterParams = {};
1197
- const fields = getFieldsForContentType('pack');
1198
- const start = (page - 1) * limit;
1199
- const end = start + limit;
1200
-
1201
- const query = await buildQuery(
1202
- filter,
1203
- filterParams,
1204
- getFieldsForContentType('pack'),
1205
- {
1206
- logo_image_url: 'logo_image_url.asset->url',
1207
- sortOrder: sortOrder,
1208
- start,
1209
- end
1210
- }
1211
- );
1212
- return fetchSanity(query, true);
1357
+ export async function fetchAllPacks(
1358
+ brand,
1359
+ sort = '-published_on',
1360
+ searchTerm = '',
1361
+ page = 1,
1362
+ limit = 10
1363
+ ) {
1364
+ const sortOrder = getSortOrder(sort, brand)
1365
+ const filter = `(_type == 'pack' || _type == 'semester-pack') &amp;&amp; brand == '${brand}' &amp;&amp; title match "${searchTerm}*"`
1366
+ const filterParams = {}
1367
+ const fields = getFieldsForContentType('pack')
1368
+ const start = (page - 1) * limit
1369
+ const end = start + limit
1370
+
1371
+ const query = await buildQuery(filter, filterParams, getFieldsForContentType('pack'), {
1372
+ logo_image_url: 'logo_image_url.asset->url',
1373
+ sortOrder: sortOrder,
1374
+ start,
1375
+ end,
1376
+ })
1377
+ return fetchSanity(query, true)
1213
1378
  }
1214
1379
 
1215
1380
  /**
@@ -1218,38 +1383,38 @@ export async function fetchAllPacks(brand, sort = "-published_on", searchTerm =
1218
1383
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
1219
1384
  */
1220
1385
  export async function fetchPackAll(railcontentId, type = 'pack') {
1221
- return fetchByRailContentId(railcontentId, type);
1386
+ return fetchByRailContentId(railcontentId, type)
1222
1387
  }
1223
1388
 
1224
1389
  export async function fetchLiveEvent(brand) {
1225
- //calendarIDs taken from addevent.php
1226
- // TODO import instructor calendars to Sanity
1227
- let defaultCalendarID = '';
1228
- switch (brand) {
1229
- case ('drumeo'):
1230
- defaultCalendarID = 'GP142387';
1231
- break;
1232
- case ('pianote'):
1233
- defaultCalendarID = 'be142408';
1234
- break;
1235
- case ('guitareo'):
1236
- defaultCalendarID = 'IJ142407';
1237
- break;
1238
- case ('singeo'):
1239
- defaultCalendarID = 'bk354284';
1240
- break;
1241
- default:
1242
- break;
1243
- }
1244
- let startDateTemp = new Date();
1245
- let endDateTemp = new Date();
1246
- startDateTemp= new Date (startDateTemp.setMinutes(startDateTemp.getMinutes() + 15));
1247
- endDateTemp = new Date(endDateTemp.setMinutes(endDateTemp.getMinutes() - 15));
1248
-
1249
- // See LiveStreamEventService.getCurrentOrNextLiveEvent for some nice complicated logic which I don't think is actually importart
1250
- // this has some +- on times
1251
- // But this query just finds the first scheduled event (sorted by start_time) that ends after now()
1252
- const query = `*[status == 'scheduled' &amp;&amp; brand == '${brand}' &amp;&amp; defined(live_event_start_time) &amp;&amp; live_event_start_time &lt;= '${getSanityDate(startDateTemp, false)}' &amp;&amp; live_event_end_time >= '${getSanityDate(endDateTemp, false)}']{
1390
+ //calendarIDs taken from addevent.php
1391
+ // TODO import instructor calendars to Sanity
1392
+ let defaultCalendarID = ''
1393
+ switch (brand) {
1394
+ case 'drumeo':
1395
+ defaultCalendarID = 'GP142387'
1396
+ break
1397
+ case 'pianote':
1398
+ defaultCalendarID = 'be142408'
1399
+ break
1400
+ case 'guitareo':
1401
+ defaultCalendarID = 'IJ142407'
1402
+ break
1403
+ case 'singeo':
1404
+ defaultCalendarID = 'bk354284'
1405
+ break
1406
+ default:
1407
+ break
1408
+ }
1409
+ let startDateTemp = new Date()
1410
+ let endDateTemp = new Date()
1411
+ startDateTemp = new Date(startDateTemp.setMinutes(startDateTemp.getMinutes() + 15))
1412
+ endDateTemp = new Date(endDateTemp.setMinutes(endDateTemp.getMinutes() - 15))
1413
+
1414
+ // See LiveStreamEventService.getCurrentOrNextLiveEvent for some nice complicated logic which I don't think is actually importart
1415
+ // this has some +- on times
1416
+ // But this query just finds the first scheduled event (sorted by start_time) that ends after now()
1417
+ const query = `*[status == 'scheduled' &amp;&amp; brand == '${brand}' &amp;&amp; defined(live_event_start_time) &amp;&amp; live_event_start_time &lt;= '${getSanityDate(startDateTemp, false)}' &amp;&amp; live_event_end_time >= '${getSanityDate(endDateTemp, false)}']{
1253
1418
  'slug': slug.current,
1254
1419
  'id': railcontent_id,
1255
1420
  live_event_start_time,
@@ -1266,8 +1431,8 @@ export async function fetchLiveEvent(brand) {
1266
1431
  web_url_path,
1267
1432
  },
1268
1433
  'videoId': coalesce(live_event_youtube_id, video.external_id),
1269
- } | order(live_event_start_time)[0...1]`;
1270
- return await fetchSanity(query, false, {processNeedAccess: false});
1434
+ } | order(live_event_start_time)[0...1]`
1435
+ return await fetchSanity(query, false, { processNeedAccess: false })
1271
1436
  }
1272
1437
 
1273
1438
  /**
@@ -1281,10 +1446,10 @@ export async function fetchLiveEvent(brand) {
1281
1446
  * .catch(error => console.error(error));
1282
1447
  */
1283
1448
  export async function fetchPackData(id) {
1284
- const query = `*[railcontent_id == ${id}]{
1285
- ${getFieldsForContentType("pack")}
1286
- } [0...1]`;
1287
- return fetchSanity(query, false);
1449
+ const query = `*[railcontent_id == ${id}]{
1450
+ ${getFieldsForContentType('pack')}
1451
+ } [0...1]`
1452
+ return fetchSanity(query, false)
1288
1453
  }
1289
1454
 
1290
1455
  /**
@@ -1304,34 +1469,26 @@ export async function fetchPackData(id) {
1304
1469
  * .then(lessons => console.log(lessons))
1305
1470
  * .catch(error => console.error(error));
1306
1471
  */
1307
- export async function fetchCoachLessons(brand, id, {
1308
- sortOrder = '-published_on',
1309
- searchTerm = '',
1310
- page = 1,
1311
- limit = 20,
1312
- includedFields = [],
1313
- } = {}) {
1314
- const fieldsString = getFieldsForContentType();
1315
- const start = (page - 1) * limit;
1316
- const end = start + limit;
1317
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1318
- const includedFieldsFilter = includedFields.length > 0
1319
- ? filtersToGroq(includedFields)
1320
- : "";
1321
- const filter = `brand == '${brand}' ${searchFilter} ${includedFieldsFilter} &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${id}]._id)`;
1322
- const filterWithRestrictions = await new FilterBuilder(filter).buildFilter();
1323
-
1324
- sortOrder = getSortOrder(sortOrder, brand);
1325
- const query = buildEntityAndTotalQuery(
1326
- filterWithRestrictions,
1327
- fieldsString,
1328
- {
1329
- sortOrder: sortOrder,
1330
- start: start,
1331
- end: end,
1332
- },
1333
- );
1334
- return fetchSanity(query, true);
1472
+ export async function fetchCoachLessons(
1473
+ brand,
1474
+ id,
1475
+ { sortOrder = '-published_on', searchTerm = '', page = 1, limit = 20, includedFields = [] } = {}
1476
+ ) {
1477
+ const fieldsString = getFieldsForContentType()
1478
+ const start = (page - 1) * limit
1479
+ const end = start + limit
1480
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1481
+ const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
1482
+ const filter = `brand == '${brand}' ${searchFilter} ${includedFieldsFilter} &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${id}]._id)`
1483
+ const filterWithRestrictions = await new FilterBuilder(filter).buildFilter()
1484
+
1485
+ sortOrder = getSortOrder(sortOrder, brand)
1486
+ const query = buildEntityAndTotalQuery(filterWithRestrictions, fieldsString, {
1487
+ sortOrder: sortOrder,
1488
+ start: start,
1489
+ end: end,
1490
+ })
1491
+ return fetchSanity(query, true)
1335
1492
  }
1336
1493
 
1337
1494
  /**
@@ -1345,15 +1502,15 @@ export async function fetchCoachLessons(brand, id, {
1345
1502
  * .catch(error => console.error(error));
1346
1503
  */
1347
1504
  export async function fetchParentForDownload(id) {
1348
- const query = buildRawQuery(
1349
- `railcontent_id == ${id}`,
1350
- getFieldsForContentType('parent-download'),
1351
- {
1352
- isSingle: true,
1353
- },
1354
- );
1355
-
1356
- return fetchSanity(query, false);
1505
+ const query = buildRawQuery(
1506
+ `railcontent_id == ${id}`,
1507
+ getFieldsForContentType('parent-download'),
1508
+ {
1509
+ isSingle: true,
1510
+ }
1511
+ )
1512
+
1513
+ return fetchSanity(query, false)
1357
1514
  }
1358
1515
 
1359
1516
  /**
@@ -1367,33 +1524,24 @@ export async function fetchParentForDownload(id) {
1367
1524
  * .then(lessons => console.log(lessons))
1368
1525
  * .catch(error => console.error(error));
1369
1526
  */
1370
- export async function fetchByReference(brand, {
1371
- sortOrder = '-published_on',
1372
- searchTerm = '',
1373
- page = 1,
1374
- limit = 20,
1375
- includedFields = [],
1376
- } = {}) {
1377
- const fieldsString = getFieldsForContentType();
1378
- const start = (page - 1) * limit;
1379
- const end = start + limit;
1380
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : '';
1381
- const includedFieldsFilter = includedFields.length > 0
1382
- ? includedFields.join(' &amp;&amp; ')
1383
- : "";
1384
-
1385
- const filter = `brand == '${brand}' ${searchFilter} &amp;&amp; references(*[${includedFieldsFilter}]._id)`;
1386
- const filterWithRestrictions = await new FilterBuilder(filter).buildFilter();
1387
- const query = buildEntityAndTotalQuery(
1388
- filterWithRestrictions,
1389
- fieldsString,
1390
- {
1391
- sortOrder: getSortOrder(sortOrder, brand),
1392
- start: start,
1393
- end: end,
1394
- },
1395
- );
1396
- return fetchSanity(query, true);
1527
+ export async function fetchByReference(
1528
+ brand,
1529
+ { sortOrder = '-published_on', searchTerm = '', page = 1, limit = 20, includedFields = [] } = {}
1530
+ ) {
1531
+ const fieldsString = getFieldsForContentType()
1532
+ const start = (page - 1) * limit
1533
+ const end = start + limit
1534
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1535
+ const includedFieldsFilter = includedFields.length > 0 ? includedFields.join(' &amp;&amp; ') : ''
1536
+
1537
+ const filter = `brand == '${brand}' ${searchFilter} &amp;&amp; references(*[${includedFieldsFilter}]._id)`
1538
+ const filterWithRestrictions = await new FilterBuilder(filter).buildFilter()
1539
+ const query = buildEntityAndTotalQuery(filterWithRestrictions, fieldsString, {
1540
+ sortOrder: getSortOrder(sortOrder, brand),
1541
+ start: start,
1542
+ end: end,
1543
+ })
1544
+ return fetchSanity(query, true)
1397
1545
  }
1398
1546
 
1399
1547
  /**
@@ -1415,29 +1563,37 @@ export async function fetchByReference(brand, {
1415
1563
  * .then(lessons => console.log(lessons))
1416
1564
  * .catch(error => console.error(error));
1417
1565
  */
1418
- export async function fetchArtistLessons(brand, name, contentType, {
1566
+ export async function fetchArtistLessons(
1567
+ brand,
1568
+ name,
1569
+ contentType,
1570
+ {
1419
1571
  sort = '-published_on',
1420
1572
  searchTerm = '',
1421
1573
  page = 1,
1422
1574
  limit = 10,
1423
1575
  includedFields = [],
1424
1576
  progressIds = undefined,
1425
- } = {}) {
1426
-
1427
- const fieldsString = DEFAULT_FIELDS.join(',');
1428
- const start = (page - 1) * limit;
1429
- const end = start + limit;
1430
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1431
- const sortOrder = getSortOrder(sort, brand);
1432
- const addType = contentType &amp;&amp; Array.isArray(contentType) ? `_type in ['${contentType.join("', '")}'] &amp;&amp;` : contentType ? `_type == '${contentType}' &amp;&amp; ` : ''
1433
- const includedFieldsFilter = includedFields.length > 0
1434
- ? filtersToGroq(includedFields)
1435
- : "";
1436
-
1437
- // limits the results to supplied progressIds for started &amp; completed filters
1438
- const progressFilter = progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
1439
- const now = getSanityDate(new Date());
1440
- const query = `{
1577
+ } = {}
1578
+ ) {
1579
+ const fieldsString = DEFAULT_FIELDS.join(',')
1580
+ const start = (page - 1) * limit
1581
+ const end = start + limit
1582
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1583
+ const sortOrder = getSortOrder(sort, brand)
1584
+ const addType =
1585
+ contentType &amp;&amp; Array.isArray(contentType)
1586
+ ? `_type in ['${contentType.join("', '")}'] &amp;&amp;`
1587
+ : contentType
1588
+ ? `_type == '${contentType}' &amp;&amp; `
1589
+ : ''
1590
+ const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
1591
+
1592
+ // limits the results to supplied progressIds for started &amp; completed filters
1593
+ const progressFilter =
1594
+ progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
1595
+ const now = getSanityDate(new Date())
1596
+ const query = `{
1441
1597
  "entity":
1442
1598
  *[_type == 'artist' &amp;&amp; name == '${name}']
1443
1599
  {'type': _type, name, 'thumbnail_url':thumbnail_url.asset->url,
@@ -1445,8 +1601,8 @@ export async function fetchArtistLessons(brand, name, contentType, {
1445
1601
  'lessons': *[${addType} brand == '${brand}' &amp;&amp; references(^._id) &amp;&amp; (status in ['published'] || (status == 'scheduled' &amp;&amp; defined(published_on) &amp;&amp; published_on >= '${now}')) ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{${fieldsString}}
1446
1602
  [${start}...${end}]}
1447
1603
  |order(${sortOrder})
1448
- }`;
1449
- return fetchSanity(query, true);
1604
+ }`
1605
+ return fetchSanity(query, true)
1450
1606
  }
1451
1607
 
1452
1608
  /**
@@ -1467,27 +1623,31 @@ export async function fetchArtistLessons(brand, name, contentType, {
1467
1623
  * .then(lessons => console.log(lessons))
1468
1624
  * .catch(error => console.error(error));
1469
1625
  */
1470
- export async function fetchGenreLessons(brand, name, contentType, {
1626
+ export async function fetchGenreLessons(
1627
+ brand,
1628
+ name,
1629
+ contentType,
1630
+ {
1471
1631
  sort = '-published_on',
1472
1632
  searchTerm = '',
1473
1633
  page = 1,
1474
1634
  limit = 10,
1475
1635
  includedFields = [],
1476
1636
  progressIds = undefined,
1477
- } = {}) {
1478
- const fieldsString = DEFAULT_FIELDS.join(',');
1479
- const start = (page - 1) * limit;
1480
- const end = start + limit;
1481
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1482
- const sortOrder = getSortOrder(sort, brand);
1483
- const addType = contentType ? `_type == '${contentType}' &amp;&amp; ` : ''
1484
- const includedFieldsFilter = includedFields.length > 0
1485
- ? filtersToGroq(includedFields)
1486
- : "";
1487
- // limits the results to supplied progressIds for started &amp; completed filters
1488
- const progressFilter = progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
1489
- const now = getSanityDate(new Date());
1490
- const query = `{
1637
+ } = {}
1638
+ ) {
1639
+ const fieldsString = DEFAULT_FIELDS.join(',')
1640
+ const start = (page - 1) * limit
1641
+ const end = start + limit
1642
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1643
+ const sortOrder = getSortOrder(sort, brand)
1644
+ const addType = contentType ? `_type == '${contentType}' &amp;&amp; ` : ''
1645
+ const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
1646
+ // limits the results to supplied progressIds for started &amp; completed filters
1647
+ const progressFilter =
1648
+ progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
1649
+ const now = getSanityDate(new Date())
1650
+ const query = `{
1491
1651
  "entity":
1492
1652
  *[_type == 'genre' &amp;&amp; name == '${name}']
1493
1653
  {'type': _type, name, 'thumbnail_url':thumbnail_url.asset->url,
@@ -1495,14 +1655,14 @@ export async function fetchGenreLessons(brand, name, contentType, {
1495
1655
  'lessons': *[${addType} brand == '${brand}' &amp;&amp; references(^._id) &amp;&amp; (status in ['published'] || (status == 'scheduled' &amp;&amp; defined(published_on) &amp;&amp; published_on >= '${now}')) ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{${fieldsString}}
1496
1656
  [${start}...${end}]}
1497
1657
  |order(${sortOrder})
1498
- }`;
1499
- return fetchSanity(query, true);
1658
+ }`
1659
+ return fetchSanity(query, true)
1500
1660
  }
1501
1661
 
1502
1662
  export async function fetchTopLevelParentId(railcontentId) {
1503
- const statusFilter = "&amp;&amp; status in ['scheduled', 'published', 'archived', 'unlisted']";
1663
+ const statusFilter = "&amp;&amp; status in ['scheduled', 'published', 'archived', 'unlisted']"
1504
1664
 
1505
- const query = `*[railcontent_id == ${railcontentId}]{
1665
+ const query = `*[railcontent_id == ${railcontentId}]{
1506
1666
  railcontent_id,
1507
1667
  'parents': *[^._id in child[]._ref ${statusFilter}]{
1508
1668
  railcontent_id,
@@ -1516,24 +1676,24 @@ export async function fetchTopLevelParentId(railcontentId) {
1516
1676
  }
1517
1677
  }
1518
1678
  }
1519
- }`;
1520
- let response = await fetchSanity(query, false, {processNeedAccess: false});
1521
- if (!response) return null;
1522
- let currentLevel = response;
1523
- for (let i = 0; i &lt; 4; i++) {
1524
- if (currentLevel['parents'].length > 0) {
1525
- currentLevel = currentLevel['parents'][0];
1526
- } else {
1527
- return currentLevel['railcontent_id'];
1528
- }
1679
+ }`
1680
+ let response = await fetchSanity(query, false, { processNeedAccess: false })
1681
+ if (!response) return null
1682
+ let currentLevel = response
1683
+ for (let i = 0; i &lt; 4; i++) {
1684
+ if (currentLevel['parents'].length > 0) {
1685
+ currentLevel = currentLevel['parents'][0]
1686
+ } else {
1687
+ return currentLevel['railcontent_id']
1529
1688
  }
1530
- return null;
1689
+ }
1690
+ return null
1531
1691
  }
1532
1692
 
1533
1693
  export async function fetchHierarchy(railcontentId) {
1534
- let topLevelId = await fetchTopLevelParentId(railcontentId);
1535
- const childrenFilter = await new FilterBuilder(``, {isChildrenFilter: true} ).buildFilter();
1536
- const query = `*[railcontent_id == ${topLevelId}]{
1694
+ let topLevelId = await fetchTopLevelParentId(railcontentId)
1695
+ const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
1696
+ const query = `*[railcontent_id == ${topLevelId}]{
1537
1697
  railcontent_id,
1538
1698
  'assignments': assignment[]{railcontent_id},
1539
1699
  'children': child[${childrenFilter}]->{
@@ -1551,42 +1711,40 @@ export async function fetchHierarchy(railcontentId) {
1551
1711
  }
1552
1712
  }
1553
1713
  },
1554
- }`;
1555
- let response = await fetchSanity(query, false, {processNeedAccess: false});
1556
- if (!response) return null;
1557
- let data = {
1558
- topLevelId: topLevelId,
1559
- parents: {},
1560
- children: {}
1561
- };
1562
- populateHierarchyLookups(response, data, null);
1563
- return data;
1714
+ }`
1715
+ let response = await fetchSanity(query, false, { processNeedAccess: false })
1716
+ if (!response) return null
1717
+ let data = {
1718
+ topLevelId: topLevelId,
1719
+ parents: {},
1720
+ children: {},
1721
+ }
1722
+ populateHierarchyLookups(response, data, null)
1723
+ return data
1564
1724
  }
1565
1725
 
1566
-
1567
1726
  function populateHierarchyLookups(currentLevel, data, parentId) {
1568
- let contentId = currentLevel['railcontent_id'];
1569
- let children = currentLevel['children'];
1570
-
1571
- data.parents[contentId] = parentId;
1572
- if (children) {
1573
- data.children[contentId] = children.map(child => child['railcontent_id']);
1574
- for (let i = 0; i &lt; children.length; i++) {
1575
- populateHierarchyLookups(children[i], data, contentId);
1576
- }
1577
- } else {
1578
- data.children[contentId] = [];
1727
+ let contentId = currentLevel['railcontent_id']
1728
+ let children = currentLevel['children']
1729
+
1730
+ data.parents[contentId] = parentId
1731
+ if (children) {
1732
+ data.children[contentId] = children.map((child) => child['railcontent_id'])
1733
+ for (let i = 0; i &lt; children.length; i++) {
1734
+ populateHierarchyLookups(children[i], data, contentId)
1579
1735
  }
1580
-
1581
- let assignments = currentLevel['assignments'];
1582
- if (assignments) {
1583
- let assignmentIds = assignments.map(assignment => assignment['railcontent_id']);
1584
- data.children[contentId] = (data.children[contentId] ?? []).concat(assignmentIds);
1585
- assignmentIds.forEach(assignmentId => {
1586
- data.parents[assignmentId] = contentId;
1587
- });
1588
- }
1589
-
1736
+ } else {
1737
+ data.children[contentId] = []
1738
+ }
1739
+
1740
+ let assignments = currentLevel['assignments']
1741
+ if (assignments) {
1742
+ let assignmentIds = assignments.map((assignment) => assignment['railcontent_id'])
1743
+ data.children[contentId] = (data.children[contentId] ?? []).concat(assignmentIds)
1744
+ assignmentIds.forEach((assignmentId) => {
1745
+ data.parents[assignmentId] = contentId
1746
+ })
1747
+ }
1590
1748
  }
1591
1749
 
1592
1750
  /**
@@ -1596,27 +1754,28 @@ function populateHierarchyLookups(currentLevel, data, parentId) {
1596
1754
  * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing the data
1597
1755
  */
1598
1756
  export async function fetchCommentModContentData(ids) {
1599
- const idsString = ids.join(',');
1600
- const fields = `"id": railcontent_id, "type": _type, title, "url": web_url_path, "parent": *[^._id in child[]._ref]{"id": railcontent_id, title}`;
1601
- const query = await buildQuery(`railcontent_id in [${idsString}]`,
1602
- {bypassPermissions: true},
1603
- fields,
1604
- {end: 50});
1605
- let data = await fetchSanity(query, true);
1606
- let mapped = {};
1607
- data.forEach(function (content) {
1608
- mapped[content.id] = {
1609
- "id": content.id,
1610
- "type": content.type,
1611
- "title": content.title,
1612
- "url": content.url,
1613
- "parentTitle": content.parent[0]?.title ?? null
1614
- };
1615
- });
1616
- return mapped;
1757
+ const idsString = ids.join(',')
1758
+ const fields = `"id": railcontent_id, "type": _type, title, "url": web_url_path, "parent": *[^._id in child[]._ref]{"id": railcontent_id, title}`
1759
+ const query = await buildQuery(
1760
+ `railcontent_id in [${idsString}]`,
1761
+ { bypassPermissions: true },
1762
+ fields,
1763
+ { end: 50 }
1764
+ )
1765
+ let data = await fetchSanity(query, true)
1766
+ let mapped = {}
1767
+ data.forEach(function (content) {
1768
+ mapped[content.id] = {
1769
+ id: content.id,
1770
+ type: content.type,
1771
+ title: content.title,
1772
+ url: content.url,
1773
+ parentTitle: content.parent[0]?.title ?? null,
1774
+ }
1775
+ })
1776
+ return mapped
1617
1777
  }
1618
1778
 
1619
-
1620
1779
  /**
1621
1780
  *
1622
1781
  * @param {string} query - The GROQ query to execute against the Sanity API.
@@ -1632,110 +1791,110 @@ export async function fetchCommentModContentData(ids) {
1632
1791
  * .catch(error => console.error(error));
1633
1792
  */
1634
1793
 
1635
- export async function fetchSanity(query,
1636
- isList,
1637
- {
1638
- customPostProcess = null,
1639
- processNeedAccess = true,
1640
- } = {}
1794
+ export async function fetchSanity(
1795
+ query,
1796
+ isList,
1797
+ { customPostProcess = null, processNeedAccess = true } = {}
1641
1798
  ) {
1642
- // Check the config object before proceeding
1643
- if (!checkSanityConfig(globalConfig)) {
1644
- return null;
1799
+ // Check the config object before proceeding
1800
+ if (!checkSanityConfig(globalConfig)) {
1801
+ return null
1802
+ }
1803
+
1804
+ if (globalConfig.sanityConfig.debug) {
1805
+ console.log('fetchSanity Query:', query)
1806
+ }
1807
+ const perspective = globalConfig.sanityConfig.perspective ?? 'published'
1808
+ const api = globalConfig.sanityConfig.useCachedAPI ? 'apicdn' : 'api'
1809
+ const url = `https://${globalConfig.sanityConfig.projectId}.${api}.sanity.io/v${globalConfig.sanityConfig.version}/data/query/${globalConfig.sanityConfig.dataset}?perspective=${perspective}`
1810
+ const headers = {
1811
+ Authorization: `Bearer ${globalConfig.sanityConfig.token}`,
1812
+ 'Content-Type': 'application/json',
1813
+ }
1814
+
1815
+ try {
1816
+ const method = 'post'
1817
+ const options = {
1818
+ method,
1819
+ headers,
1820
+ body: JSON.stringify({ query: query }),
1645
1821
  }
1646
1822
 
1647
- if (globalConfig.sanityConfig.debug) {
1648
- console.log("fetchSanity Query:", query);
1823
+ let promisesResult = await Promise.all([
1824
+ fetch(url, options),
1825
+ processNeedAccess ? fetchUserPermissions() : null,
1826
+ ])
1827
+ const response = promisesResult[0]
1828
+ const userPermissions = promisesResult[1]?.permissions
1829
+ const isAdmin = promisesResult[1]?.isAdmin
1830
+
1831
+ if (!response.ok) {
1832
+ throw new Error(`Sanity API error: ${response.status} - ${response.statusText}`)
1649
1833
  }
1650
- const perspective = globalConfig.sanityConfig.perspective ?? 'published';
1651
- const api = globalConfig.sanityConfig.useCachedAPI ? 'apicdn' : 'api';
1652
- const url = `https://${globalConfig.sanityConfig.projectId}.${api}.sanity.io/v${globalConfig.sanityConfig.version}/data/query/${globalConfig.sanityConfig.dataset}?perspective=${perspective}`;
1653
- const headers = {
1654
- 'Authorization': `Bearer ${globalConfig.sanityConfig.token}`,
1655
- 'Content-Type': 'application/json'
1656
- };
1657
-
1658
- try {
1659
- const method = 'post';
1660
- const options = {
1661
- method,
1662
- headers,
1663
- body: JSON.stringify({'query': query})
1664
- };
1665
-
1666
- let promisesResult = await Promise.all([
1667
- fetch(url, options),
1668
- processNeedAccess ? fetchUserPermissions() : null
1669
- ]);
1670
- const response = promisesResult[0];
1671
- const userPermissions = promisesResult[1]?.permissions;
1672
- const isAdmin = promisesResult[1]?.isAdmin;
1673
-
1674
- if (!response.ok) {
1675
- throw new Error(`Sanity API error: ${response.status} - ${response.statusText}`);
1676
- }
1677
- const result = await response.json();
1678
- if (result.result) {
1679
- if (globalConfig.sanityConfig.debug) {
1680
- console.log("fetchSanity Results:", result);
1681
- }
1682
- let results = isList ? result.result : result.result[0];
1683
- results = processNeedAccess ? await needsAccessDecorator(results, userPermissions, isAdmin) : results;
1684
- return customPostProcess ? customPostProcess(results) : results;
1685
- } else {
1686
- throw new Error('No results found');
1687
- }
1688
- } catch (error) {
1689
- console.error('fetchSanity: Fetch error:', error);
1690
- return null;
1834
+ const result = await response.json()
1835
+ if (result.result) {
1836
+ if (globalConfig.sanityConfig.debug) {
1837
+ console.log('fetchSanity Results:', result)
1838
+ }
1839
+ let results = isList ? result.result : result.result[0]
1840
+ results = processNeedAccess
1841
+ ? await needsAccessDecorator(results, userPermissions, isAdmin)
1842
+ : results
1843
+ return customPostProcess ? customPostProcess(results) : results
1844
+ } else {
1845
+ throw new Error('No results found')
1691
1846
  }
1847
+ } catch (error) {
1848
+ console.error('fetchSanity: Fetch error:', error)
1849
+ return null
1850
+ }
1692
1851
  }
1693
1852
 
1694
1853
  function needsAccessDecorator(results, userPermissions, isAdmin) {
1695
- if (globalConfig.sanityConfig.useDummyRailContentMethods) return results;
1696
-
1697
- userPermissions = new Set(userPermissions);
1698
-
1699
- if (Array.isArray(results)) {
1700
- results.forEach((result) => {
1701
- result['need_access'] = doesUserNeedAccessToContent(result, userPermissions, isAdmin);
1702
- });
1703
- } else if (results.entity &amp;&amp; Array.isArray(results.entity)) {
1704
- // Group By
1705
- results.entity.forEach((result) => {
1706
- if (result.lessons) {
1707
- result.lessons.forEach((lesson) => {
1708
- lesson['need_access'] = doesUserNeedAccessToContent(lesson, userPermissions, isAdmin); // Updated to check lesson access
1709
- });
1710
- } else {
1711
- result['need_access'] = doesUserNeedAccessToContent(result, userPermissions, isAdmin);
1712
- }
1713
- });
1714
- } else if (results.related_lessons &amp;&amp; Array.isArray(results.related_lessons)) {
1715
- results.related_lessons.forEach((result) => {
1716
- result['need_access'] = doesUserNeedAccessToContent(result, userPermissions, isAdmin);
1854
+ if (globalConfig.sanityConfig.useDummyRailContentMethods) return results
1855
+
1856
+ userPermissions = new Set(userPermissions)
1857
+
1858
+ if (Array.isArray(results)) {
1859
+ results.forEach((result) => {
1860
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions, isAdmin)
1861
+ })
1862
+ } else if (results.entity &amp;&amp; Array.isArray(results.entity)) {
1863
+ // Group By
1864
+ results.entity.forEach((result) => {
1865
+ if (result.lessons) {
1866
+ result.lessons.forEach((lesson) => {
1867
+ lesson['need_access'] = doesUserNeedAccessToContent(lesson, userPermissions, isAdmin) // Updated to check lesson access
1717
1868
  })
1718
- } else {
1719
- results['need_access'] = doesUserNeedAccessToContent(results, userPermissions, isAdmin);
1720
- }
1721
-
1722
- return results;
1869
+ } else {
1870
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions, isAdmin)
1871
+ }
1872
+ })
1873
+ } else if (results.related_lessons &amp;&amp; Array.isArray(results.related_lessons)) {
1874
+ results.related_lessons.forEach((result) => {
1875
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions, isAdmin)
1876
+ })
1877
+ } else {
1878
+ results['need_access'] = doesUserNeedAccessToContent(results, userPermissions, isAdmin)
1879
+ }
1880
+
1881
+ return results
1723
1882
  }
1724
1883
 
1725
1884
  function doesUserNeedAccessToContent(result, userPermissions, isAdmin) {
1726
- if (isAdmin ?? false) {
1727
- return false;
1728
- }
1729
- const permissions = new Set(result?.permission_id ?? []);
1730
- if (permissions.size === 0) {
1731
- return false;
1732
- }
1733
- for (let permission of permissions) {
1734
- if (userPermissions.has(permission)) {
1735
- return false;
1736
- }
1885
+ if (isAdmin ?? false) {
1886
+ return false
1887
+ }
1888
+ const permissions = new Set(result?.permission_id ?? [])
1889
+ if (permissions.size === 0) {
1890
+ return false
1891
+ }
1892
+ for (let permission of permissions) {
1893
+ if (userPermissions.has(permission)) {
1894
+ return false
1737
1895
  }
1738
- return true;
1896
+ }
1897
+ return true
1739
1898
  }
1740
1899
 
1741
1900
  /**
@@ -1751,15 +1910,15 @@ function doesUserNeedAccessToContent(result, userPermissions, isAdmin) {
1751
1910
  * .catch(error => console.error(error));
1752
1911
  */
1753
1912
  export async function fetchShowsData(brand) {
1754
- let shows = showsTypes[brand] ?? [];
1755
- const showsInfo = [];
1913
+ let shows = showsTypes[brand] ?? []
1914
+ const showsInfo = []
1756
1915
 
1757
- shows.forEach(type => {
1758
- const processedData = processMetadata(brand, type);
1759
- if (processedData) showsInfo.push(processedData)
1760
- });
1916
+ shows.forEach((type) => {
1917
+ const processedData = processMetadata(brand, type)
1918
+ if (processedData) showsInfo.push(processedData)
1919
+ })
1761
1920
 
1762
- return showsInfo;
1921
+ return showsInfo
1763
1922
  }
1764
1923
 
1765
1924
  /**
@@ -1776,223 +1935,208 @@ export async function fetchShowsData(brand) {
1776
1935
  * .catch(error => console.error(error));
1777
1936
  */
1778
1937
  export async function fetchMetadata(brand, type) {
1779
- const processedData = processMetadata(brand, type, true);
1780
- return processedData ? processedData : {};
1938
+ const processedData = processMetadata(brand, type, true)
1939
+ return processedData ? processedData : {}
1781
1940
  }
1782
1941
 
1783
1942
  export async function fetchChatAndLiveEnvent(brand, forcedId = null) {
1784
- const liveEvent = (forcedId !== null) ? await fetchByRailContentIds([forcedId]): [await fetchLiveEvent(brand)];
1785
- if (liveEvent.length === 0 || (liveEvent.length === 1 &amp;&amp; liveEvent[0] === undefined)) {
1786
- return null;
1787
- }
1788
- let url = `/content/live-chat?brand=${brand}`;
1789
- const chatData = await fetchHandler(url);
1790
- const mergedData = { ...chatData, ...liveEvent[0] };
1791
- return mergedData;
1943
+ const liveEvent =
1944
+ forcedId !== null ? await fetchByRailContentIds([forcedId]) : [await fetchLiveEvent(brand)]
1945
+ if (liveEvent.length === 0 || (liveEvent.length === 1 &amp;&amp; liveEvent[0] === undefined)) {
1946
+ return null
1947
+ }
1948
+ let url = `/content/live-chat?brand=${brand}`
1949
+ const chatData = await fetchHandler(url)
1950
+ const mergedData = { ...chatData, ...liveEvent[0] }
1951
+ return mergedData
1792
1952
  }
1793
1953
 
1794
-
1795
1954
  //Helper Functions
1796
1955
  function arrayJoinWithQuotes(array, delimiter = ',') {
1797
- const wrapped = array.map(value => `'${value}'`);
1798
- return wrapped.join(delimiter)
1956
+ const wrapped = array.map((value) => `'${value}'`)
1957
+ return wrapped.join(delimiter)
1799
1958
  }
1800
1959
 
1801
1960
  function getSanityDate(date, roundToHourForCaching = true) {
1802
- if (roundToHourForCaching) {
1803
- // We need to set the published on filter date to be a round time so that it doesn't bypass the query cache
1804
- // with every request by changing the filter date every second. I've set it to one minute past the current hour
1805
- // because publishing usually publishes content on the hour exactly which means it should still skip the cache
1806
- // when the new content is available.
1807
- // Round to the start of the current hour
1808
- const roundedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours());
1809
-
1810
- return roundedDate.toISOString();
1811
- }
1812
-
1813
- return date.toISOString();
1961
+ if (roundToHourForCaching) {
1962
+ // We need to set the published on filter date to be a round time so that it doesn't bypass the query cache
1963
+ // with every request by changing the filter date every second. I've set it to one minute past the current hour
1964
+ // because publishing usually publishes content on the hour exactly which means it should still skip the cache
1965
+ // when the new content is available.
1966
+ // Round to the start of the current hour
1967
+ const roundedDate = new Date(
1968
+ date.getFullYear(),
1969
+ date.getMonth(),
1970
+ date.getDate(),
1971
+ date.getHours()
1972
+ )
1973
+
1974
+ return roundedDate.toISOString()
1975
+ }
1976
+
1977
+ return date.toISOString()
1814
1978
  }
1815
1979
 
1816
1980
  const merge = (a, b, predicate = (a, b) => a === b) => {
1817
- const c = [...a]; // copy to avoid side effects
1818
- // add all items from B to copy C if they're not already present
1819
- b.forEach((bItem) => (c.some((cItem) => predicate(bItem, cItem)) ? null : c.push(bItem)))
1820
- return c;
1981
+ const c = [...a] // copy to avoid side effects
1982
+ // add all items from B to copy C if they're not already present
1983
+ b.forEach((bItem) => (c.some((cItem) => predicate(bItem, cItem)) ? null : c.push(bItem)))
1984
+ return c
1821
1985
  }
1822
1986
 
1823
1987
  function checkSanityConfig(config) {
1824
- if (!config.sanityConfig.token) {
1825
- console.warn('fetchSanity: The "token" property is missing in the config object.');
1826
- return false;
1827
- }
1828
- if (!config.sanityConfig.projectId) {
1829
- console.warn('fetchSanity: The "projectId" property is missing in the config object.');
1830
- return false;
1831
- }
1832
- if (!config.sanityConfig.dataset) {
1833
- console.warn('fetchSanity: The "dataset" property is missing in the config object.');
1834
- return false;
1835
- }
1836
- if (!config.sanityConfig.version) {
1837
- console.warn('fetchSanity: The "version" property is missing in the config object.');
1838
- return false;
1839
- }
1840
- return true;
1988
+ if (!config.sanityConfig.token) {
1989
+ console.warn('fetchSanity: The "token" property is missing in the config object.')
1990
+ return false
1991
+ }
1992
+ if (!config.sanityConfig.projectId) {
1993
+ console.warn('fetchSanity: The "projectId" property is missing in the config object.')
1994
+ return false
1995
+ }
1996
+ if (!config.sanityConfig.dataset) {
1997
+ console.warn('fetchSanity: The "dataset" property is missing in the config object.')
1998
+ return false
1999
+ }
2000
+ if (!config.sanityConfig.version) {
2001
+ console.warn('fetchSanity: The "version" property is missing in the config object.')
2002
+ return false
2003
+ }
2004
+ return true
1841
2005
  }
1842
2006
 
1843
-
1844
2007
  function buildRawQuery(
1845
- filter = '',
1846
- fields = '...',
1847
- {
1848
- sortOrder = 'published_on desc',
1849
- start = 0,
1850
- end = 10,
1851
- isSingle = false,
1852
- }
2008
+ filter = '',
2009
+ fields = '...',
2010
+ { sortOrder = 'published_on desc', start = 0, end = 10, isSingle = false}
1853
2011
  ) {
1854
- const sortString = sortOrder ? `order(${sortOrder})` : '';
1855
- const countString = isSingle ? '[0...1]' : `[${start}...${end}]`;
1856
- const query = `*[${filter}]{
2012
+ const sortString = sortOrder ? `order(${sortOrder})` : ''
2013
+ const countString = isSingle ? '[0...1]' : `[${start}...${end}]`
2014
+ const query = `*[${filter}]{
1857
2015
  ${fields}
1858
2016
  } | ${sortString}${countString}`
1859
- return query;
2017
+ return query
1860
2018
  }
1861
2019
 
1862
-
1863
2020
  async function buildQuery(
1864
- baseFilter = '',
1865
- filterParams = {pullFutureContent: false},
1866
- fields = '...',
1867
- {
1868
- sortOrder = 'published_on desc',
1869
- start = 0,
1870
- end = 10,
1871
- isSingle = false,
1872
- },
2021
+ baseFilter = '',
2022
+ filterParams = { pullFutureContent: false },
2023
+ fields = '...',
2024
+ { sortOrder = 'published_on desc', start = 0, end = 10, isSingle = false}
1873
2025
  ) {
1874
- const filter = await new FilterBuilder(baseFilter, filterParams).buildFilter();
1875
- return buildRawQuery(filter, fields, {sortOrder, start, end, isSingle});
2026
+ const filter = await new FilterBuilder(baseFilter, filterParams).buildFilter()
2027
+ return buildRawQuery(filter, fields, { sortOrder, start, end, isSingle})
1876
2028
  }
1877
2029
 
1878
2030
  function buildEntityAndTotalQuery(
1879
- filter = '',
1880
- fields = '...',
1881
- {
1882
- sortOrder = 'published_on desc',
1883
- start = 0,
1884
- end = 10,
1885
- isSingle = false,
1886
- },
2031
+ filter = '',
2032
+ fields = '...',
2033
+ { sortOrder = 'published_on desc', start = 0, end = 10, isSingle = false }
1887
2034
  ) {
1888
- const sortString = sortOrder ? `order(${sortOrder})` : '';
1889
- const countString = isSingle ? '[0...1]' : `[${start}...${end}]`;
1890
- const query = `{
2035
+ const sortString = sortOrder ? `order(${sortOrder})` : ''
2036
+ const countString = isSingle ? '[0...1]' : `[${start}...${end}]`
2037
+ const query = `{
1891
2038
  "entity": *[${filter}] | ${sortString}${countString}
1892
2039
  {
1893
2040
  ${fields}
1894
2041
  },
1895
2042
  "total": 0
1896
- }`;
1897
- return query;
2043
+ }`
2044
+ return query
1898
2045
  }
1899
2046
 
1900
-
1901
2047
  function getFilterOptions(option, commonFilter, contentType, brand) {
1902
- let filterGroq = '';
1903
- const types = Array.from(new Set([...coachLessonsTypes, ...showsTypes[brand]]));
2048
+ let filterGroq = ''
2049
+ const types = Array.from(new Set([...coachLessonsTypes, ...showsTypes[brand]]))
1904
2050
 
1905
- switch (option) {
1906
- case "difficulty":
1907
- filterGroq = `
2051
+ switch (option) {
2052
+ case 'difficulty':
2053
+ filterGroq = `
1908
2054
  "difficulty": [
1909
2055
  {"type": "All", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "All"])},
1910
- {"type": "Introductory", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Introductory"])},
2056
+ {"type": "Introductory", "count": count(*[${commonFilter} &amp;&amp; (difficulty_string == "Novice" || difficulty_string == "Introductory")])},
1911
2057
  {"type": "Beginner", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Beginner"])},
1912
2058
  {"type": "Intermediate", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Intermediate" ])},
1913
2059
  {"type": "Advanced", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Advanced" ])},
1914
2060
  {"type": "Expert", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Expert" ])}
1915
- ][count > 0],`;
1916
- break;
1917
- case "type":
1918
- const typesString = types.map(t => {
1919
- return `{"type": "${t}"}`
1920
- }).join(', ');
1921
- filterGroq = `"type": [${typesString}]{type, 'count': count(*[_type == ^.type &amp;&amp; ${commonFilter}])}[count > 0],`;
1922
- break;
1923
- case "genre":
1924
- case "essential":
1925
- case "focus":
1926
- case "theory":
1927
- case "topic":
1928
- case "lifestyle":
1929
- case "creativity":
1930
- filterGroq = `
2061
+ ][count > 0],`
2062
+ break
2063
+ case 'type':
2064
+ const typesString = types
2065
+ .map((t) => {
2066
+ return `{"type": "${t}"}`
2067
+ })
2068
+ .join(', ')
2069
+ filterGroq = `"type": [${typesString}]{type, 'count': count(*[_type == ^.type &amp;&amp; ${commonFilter}])}[count > 0],`
2070
+ break
2071
+ case 'genre':
2072
+ case 'essential':
2073
+ case 'focus':
2074
+ case 'theory':
2075
+ case 'topic':
2076
+ case 'lifestyle':
2077
+ case 'creativity':
2078
+ filterGroq = `
1931
2079
  "${option}": *[_type == '${option}' ${contentType ? ` &amp;&amp; '${contentType}' in filter_types` : ''} ] {
1932
2080
  "type": name,
1933
2081
  "count": count(*[${commonFilter} &amp;&amp; references(^._id)])
1934
- }[count > 0],`;
1935
- break;
1936
- case "instrumentless":
1937
- filterGroq = `
2082
+ }[count > 0],`
2083
+ break
2084
+ case 'instrumentless':
2085
+ filterGroq = `
1938
2086
  "${option}": [
1939
2087
  {"type": "Full Song Only", "count": count(*[${commonFilter} &amp;&amp; instrumentless == false ])},
1940
2088
  {"type": "Instrument Removed", "count": count(*[${commonFilter} &amp;&amp; instrumentless == true ])}
1941
- ][count > 0],`;
1942
- break;
1943
- case "gear":
1944
- filterGroq = `
2089
+ ][count > 0],`
2090
+ break
2091
+ case 'gear':
2092
+ filterGroq = `
1945
2093
  "${option}": [
1946
2094
  {"type": "Practice Pad", "count": count(*[${commonFilter} &amp;&amp; gear match 'Practice Pad' ])},
1947
2095
  {"type": "Drum-Set", "count": count(*[${commonFilter} &amp;&amp; gear match 'Drum-Set'])}
1948
- ][count > 0],`;
1949
- break;
1950
- case "bpm":
1951
- filterGroq = `
2096
+ ][count > 0],`
2097
+ break
2098
+ case 'bpm':
2099
+ filterGroq = `
1952
2100
  "${option}": [
1953
2101
  {"type": "50-90", "count": count(*[${commonFilter} &amp;&amp; bpm > 50 &amp;&amp; bpm &lt; 91])},
1954
2102
  {"type": "91-120", "count": count(*[${commonFilter} &amp;&amp; bpm > 90 &amp;&amp; bpm &lt; 121])},
1955
2103
  {"type": "121-150", "count": count(*[${commonFilter} &amp;&amp; bpm > 120 &amp;&amp; bpm &lt; 151])},
1956
2104
  {"type": "151-180", "count": count(*[${commonFilter} &amp;&amp; bpm > 150 &amp;&amp; bpm &lt; 181])},
1957
2105
  {"type": "180+", "count": count(*[${commonFilter} &amp;&amp; bpm > 180])},
1958
- ][count > 0],`;
1959
- break;
1960
- default:
1961
- filterGroq = "";
1962
- break;
1963
- }
1964
-
1965
- return filterGroq;
2106
+ ][count > 0],`
2107
+ break
2108
+ default:
2109
+ filterGroq = ''
2110
+ break
2111
+ }
2112
+
2113
+ return filterGroq
1966
2114
  }
1967
2115
 
1968
2116
  function cleanUpGroq(query) {
1969
- // Split the query into clauses based on the logical operators
1970
- const clauses = query.split(/(\s*&amp;&amp;|\s*\|\|)/).map(clause => clause.trim());
2117
+ // Split the query into clauses based on the logical operators
2118
+ const clauses = query.split(/(\s*&amp;&amp;|\s*\|\|)/).map((clause) => clause.trim())
1971
2119
 
1972
- // Filter out empty clauses
1973
- const filteredClauses = clauses.filter(clause => clause.length > 0);
2120
+ // Filter out empty clauses
2121
+ const filteredClauses = clauses.filter((clause) => clause.length > 0)
1974
2122
 
1975
- // Check if there are valid conditions in the clauses
1976
- const hasConditions = filteredClauses.some(clause => !clause.match(/^\s*&amp;&amp;\s*|\s*\|\|\s*$/));
2123
+ // Check if there are valid conditions in the clauses
2124
+ const hasConditions = filteredClauses.some((clause) => !clause.match(/^\s*&amp;&amp;\s*|\s*\|\|\s*$/))
1977
2125
 
1978
- if (!hasConditions) {
1979
- // If no valid conditions, return an empty string or the original query
1980
- return '';
1981
- }
2126
+ if (!hasConditions) {
2127
+ // If no valid conditions, return an empty string or the original query
2128
+ return ''
2129
+ }
1982
2130
 
1983
- // Remove occurrences of '&amp;&amp; ()'
1984
- const cleanedQuery = filteredClauses.join(' ')
1985
- .replace(/&amp;&amp;\s*\(\)/g, '')
1986
- .replace(/(\s*&amp;&amp;|\s*\|\|)(?=\s*[\s()]*$|(?=\s*&amp;&amp;|\s*\|\|))/g, '')
1987
- .trim();
2131
+ // Remove occurrences of '&amp;&amp; ()'
2132
+ const cleanedQuery = filteredClauses
2133
+ .join(' ')
2134
+ .replace(/&amp;&amp;\s*\(\)/g, '')
2135
+ .replace(/(\s*&amp;&amp;|\s*\|\|)(?=\s*[\s()]*$|(?=\s*&amp;&amp;|\s*\|\|))/g, '')
2136
+ .trim()
1988
2137
 
1989
- return cleanedQuery;
2138
+ return cleanedQuery
1990
2139
  }
1991
-
1992
-
1993
-
1994
-
1995
-
1996
2140
  </code></pre>
1997
2141
  </article>
1998
2142
  </section>
@@ -2007,7 +2151,7 @@ function cleanUpGroq(query) {
2007
2151
  <br class="clear">
2008
2152
 
2009
2153
  <footer>
2010
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Mon Jan 20 2025 08:04:00 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
2154
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Fri Feb 21 2025 20:42:51 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
2011
2155
  </footer>
2012
2156
 
2013
2157
  <script>prettyPrint();</script>