musora-content-services 1.0.173 → 1.0.175

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#.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#.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#.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#.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#.postChallengesCommunityNotification">postChallengesCommunityNotification</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#.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#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postCompleteLesson">postCompleteLesson</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#.fetchAllSongs">fetchAllSongs</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#.fetchCatalogMetadata">fetchCatalogMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchChallengeOverview">fetchChallengeOverview</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchChildren">fetchChildren</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#.fetchCourseOverview">fetchCourseOverview</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#.fetchMethodNextLesson">fetchMethodNextLesson</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#.fetchMethods">fetchMethods</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#.fetchPackChildren">fetchPackChildren</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#.fetchParentByRailContentId">fetchParentByRailContentId</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#.fetchRelatedMethodLessons">fetchRelatedMethodLessons</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#.fetchSongCount">fetchSongCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongFilterOptions">fetchSongFilterOptions</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#.fetchWorkouts">fetchWorkouts</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#.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#.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#.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#.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#.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#.postChallengesUnlock">postChallengesUnlock</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#.fetchAllSongs">fetchAllSongs</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#.fetchAssignments">fetchAssignments</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#.fetchCatalogMetadata">fetchCatalogMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchChallengeOverview">fetchChallengeOverview</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchChildren">fetchChildren</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#.fetchCourseOverview">fetchCourseOverview</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#.fetchMethodNextLesson">fetchMethodNextLesson</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#.fetchMethods">fetchMethods</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#.fetchPackChildren">fetchPackChildren</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#.fetchParentByRailContentId">fetchParentByRailContentId</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#.fetchRelatedMethodLessons">fetchRelatedMethodLessons</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#.fetchSongCount">fetchSongCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongFilterOptions">fetchSongFilterOptions</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#.fetchWorkouts">fetchWorkouts</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -70,8 +70,10 @@ import {
70
70
 
71
71
  import {globalConfig} from "./config";
72
72
 
73
- import { fetchUserPermissions, fetchAllCompletedStates, fetchCurrentSongComplete } from './railcontent.js';
73
+ import {fetchAllCompletedStates, fetchCurrentSongComplete} from './railcontent.js';
74
74
  import {arrayToStringRepresentation, FilterBuilder} from "../filterBuilder";
75
+ import {fetchUserPermissions} from "./userPermissions";
76
+ import {getAllCompleted, getAllStarted, getAllStartedOrCompleted} from "./contentProgress";
75
77
 
76
78
  /**
77
79
  * Exported functions that are excluded from index generation.
@@ -79,21 +81,22 @@ import {arrayToStringRepresentation, FilterBuilder} from "../filterBuilder";
79
81
  * @type {string[]}
80
82
  */
81
83
  const excludeFromGeneratedIndex = [];
84
+
82
85
  /**
83
- * Fetch a song by its document ID from Sanity.
84
- *
85
- * @param {string} documentId - The ID of the document to fetch.
86
- * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing the song data or null if not found.
87
- *
88
- * @example
89
- * fetchSongById('abc123')
90
- * .then(song => console.log(song))
91
- * .catch(error => console.error(error));
92
- */
86
+ * Fetch a song by its document ID from Sanity.
87
+ *
88
+ * @param {string} documentId - The ID of the document to fetch.
89
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing the song data or null if not found.
90
+ *
91
+ * @example
92
+ * fetchSongById('abc123')
93
+ * .then(song => console.log(song))
94
+ * .catch(error => console.error(error));
95
+ */
93
96
  export async function fetchSongById(documentId) {
94
97
  const fields = getFieldsForContentType('song');
95
98
  const filterParams = {};
96
- const query = buildQuery(
99
+ const query = await buildQuery(
97
100
  `_type == "song" &amp;&amp; railcontent_id == ${documentId}`,
98
101
  filterParams,
99
102
  fields,
@@ -104,48 +107,48 @@ export async function fetchSongById(documentId) {
104
107
  }
105
108
 
106
109
  /**
107
- * Fetch all artists with lessons available for a specific brand.
108
- *
109
- * @param {string} brand - The brand for which to fetch artists.
110
- * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of artist objects or null if not found.
111
- *
112
- * @example
113
- * fetchArtists('drumeo')
114
- * .then(artists => console.log(artists))
115
- * .catch(error => console.error(error));
116
- */
110
+ * Fetch all artists with lessons available for a specific brand.
111
+ *
112
+ * @param {string} brand - The brand for which to fetch artists.
113
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of artist objects or null if not found.
114
+ *
115
+ * @example
116
+ * fetchArtists('drumeo')
117
+ * .then(artists => console.log(artists))
118
+ * .catch(error => console.error(error));
119
+ */
117
120
  export async function fetchArtists(brand) {
118
- const filter = new FilterBuilder(`_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)`).buildFilter();
119
- const query = `
121
+ const filter = await new FilterBuilder(`_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)`, {bypassPermissions: true}).buildFilter();
122
+ const query = `
120
123
  *[_type == "artist"]{
121
124
  name,
122
125
  "lessonsCount": count(*[${filter}])
123
126
  }[lessonsCount > 0]`;
124
- return fetchSanity(query, true, {processNeedAccess:false});
127
+ return fetchSanity(query, true, {processNeedAccess: false});
125
128
  }
126
129
 
127
130
  /**
128
- * Fetch current number of artists for songs within a brand.
129
- * @param {string} brand - The current brand.
130
- * @returns {Promise&lt;int|null>} - The fetched count of artists.
131
- */
131
+ * Fetch current number of artists for songs within a brand.
132
+ * @param {string} brand - The current brand.
133
+ * @returns {Promise&lt;int|null>} - The fetched count of artists.
134
+ */
132
135
  export async function fetchSongArtistCount(brand) {
133
- const query = `count(*[_type == 'artist']{'lessonsCount': count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; references(^._id)]._id)}[lessonsCount > 0])`;
134
- return fetchSanity(query, true, {processNeedAccess:false});
136
+ const query = `count(*[_type == 'artist']{'lessonsCount': count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; references(^._id)]._id)}[lessonsCount > 0])`;
137
+ return fetchSanity(query, true, {processNeedAccess: false});
135
138
  }
136
139
 
137
140
  /**
138
- * Fetch related songs for a specific brand and song ID.
139
- *
140
- * @param {string} brand - The brand for which to fetch related songs.
141
- * @param {string} songId - The ID of the song to find related songs for.
142
- * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of related song objects or null if not found.
143
- *
144
- * @example
145
- * fetchRelatedSongs('drumeo', '12345')
146
- * .then(relatedSongs => console.log(relatedSongs))
147
- * .catch(error => console.error(error));
148
- */
141
+ * Fetch related songs for a specific brand and song ID.
142
+ *
143
+ * @param {string} brand - The brand for which to fetch related songs.
144
+ * @param {string} songId - The ID of the song to find related songs for.
145
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of related song objects or null if not found.
146
+ *
147
+ * @example
148
+ * fetchRelatedSongs('drumeo', '12345')
149
+ * .then(relatedSongs => console.log(relatedSongs))
150
+ * .catch(error => console.error(error));
151
+ */
149
152
  export async function fetchRelatedSongs(brand, songId) {
150
153
  const query = `
151
154
  *[_type == "song" &amp;&amp; railcontent_id == ${songId}]{
@@ -237,29 +240,29 @@ export async function fetchRelatedSongs(brand, songId) {
237
240
  * .catch(error => console.error(error));
238
241
  */
239
242
  export async function fetchAllSongs(brand, {
240
- page = 1,
241
- limit = 10,
242
- searchTerm = "",
243
- sort = "-published_on",
244
- includedFields = [],
245
- groupBy = ""
243
+ page = 1,
244
+ limit = 10,
245
+ searchTerm = "",
246
+ sort = "-published_on",
247
+ includedFields = [],
248
+ groupBy = ""
246
249
  }) {
247
250
  return fetchAll(brand, 'song', {page, limit, searchTerm, sort, includedFields, groupBy});
248
251
  }
249
252
 
250
253
  /**
251
- * Fetch filter options for a specific brand.
252
- *
253
- * @param {string} brand - The brand for which to fetch filter options.
254
- * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing filter options or null if not found.
255
- *
256
- * @example
257
- * fetchSongFilterOptions('drumeo')
258
- * .then(options => console.log(options))
259
- * .catch(error => console.error(error));
260
- */
254
+ * Fetch filter options for a specific brand.
255
+ *
256
+ * @param {string} brand - The brand for which to fetch filter options.
257
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing filter options or null if not found.
258
+ *
259
+ * @example
260
+ * fetchSongFilterOptions('drumeo')
261
+ * .then(options => console.log(options))
262
+ * .catch(error => console.error(error));
263
+ */
261
264
  export async function fetchSongFilterOptions(brand) {
262
- const query = `
265
+ const query = `
263
266
  {
264
267
  "difficulty": [
265
268
  {"type": "Introductory", "count": count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; difficulty_string == "Introductory"]._id)},
@@ -278,17 +281,17 @@ export async function fetchSongFilterOptions(brand) {
278
281
  ]
279
282
  }`;
280
283
 
281
- return fetchSanity(query, true);
284
+ return fetchSanity(query, true);
282
285
  }
283
286
 
284
287
  /**
285
- * Fetch the total count of songs for a specific brand.
286
- * @param {string} brand - The brand for which to fetch the song count.
287
- * @returns {Promise&lt;number|null>} - The total count of songs or null if an error occurs.
288
- */
288
+ * Fetch the total count of songs for a specific brand.
289
+ * @param {string} brand - The brand for which to fetch the song count.
290
+ * @returns {Promise&lt;number|null>} - The total count of songs or null if an error occurs.
291
+ */
289
292
  export async function fetchSongCount(brand) {
290
- const query = `count(*[_type == 'song' &amp;&amp; brand == "${brand}"])`;
291
- return fetchSanity(query, true, {processNeedAccess:false});
293
+ const query = `count(*[_type == 'song' &amp;&amp; brand == "${brand}"])`;
294
+ return fetchSanity(query, true, {processNeedAccess: false});
292
295
  }
293
296
 
294
297
  /**
@@ -303,29 +306,29 @@ export async function fetchSongCount(brand) {
303
306
  * @example
304
307
  * fetchWorkouts('drumeo')
305
308
  * .then(workouts => console.log(workouts))
306
- * .catch(error => console.error(error));
309
+ * .catch(error => console.error(error));
307
310
  */
308
311
  export async function fetchWorkouts(brand) {
309
- const fields = getFieldsForContentType('workout');
310
- const query = `*[_type == 'workout' &amp;&amp; brand == '${brand}'] [0...5] {
312
+ const fields = getFieldsForContentType('workout');
313
+ const query = `*[_type == 'workout' &amp;&amp; brand == '${brand}'] [0...5] {
311
314
  ${fields.toString()}
312
315
  } | order(published_on desc)[0...5]`
313
- return fetchSanity(query, true);
316
+ return fetchSanity(query, true);
314
317
  }
315
318
 
316
319
  /**
317
- * Fetch the latest new releases for a specific brand.
318
- * @param {string} brand - The brand for which to fetch new releases.
319
- * @returns {Promise&lt;Object|null>} - The fetched new releases data or null if not found.
320
- */
321
- export async function fetchNewReleases(brand, { page = 1, limit = 20, sort="-published_on" } = {}) {
322
- const newTypes = getNewReleasesTypes(brand);
323
- const typesString = arrayToStringRepresentation(newTypes);
324
- const start = (page - 1) * limit;
325
- const end = start + limit;
326
- const sortOrder = getSortOrder(sort);
327
- const filter = `_type in ${typesString} &amp;&amp; brand == '${brand}'`;
328
- const fields = `
320
+ * Fetch the latest new releases for a specific brand.
321
+ * @param {string} brand - The brand for which to fetch new releases.
322
+ * @returns {Promise&lt;Object|null>} - The fetched new releases data or null if not found.
323
+ */
324
+ export async function fetchNewReleases(brand, {page = 1, limit = 20, sort = "-published_on"} = {}) {
325
+ const newTypes = getNewReleasesTypes(brand);
326
+ const typesString = arrayToStringRepresentation(newTypes);
327
+ const start = (page - 1) * limit;
328
+ const end = start + limit;
329
+ const sortOrder = getSortOrder(sort);
330
+ const filter = `_type in ${typesString} &amp;&amp; brand == '${brand}'`;
331
+ const fields = `
329
332
  "id": railcontent_id,
330
333
  title,
331
334
  "image": thumbnail.asset->url,
@@ -339,41 +342,41 @@ export async function fetchNewReleases(brand, { page = 1, limit = 20, sort="-pub
339
342
  web_url_path,
340
343
  "permission_id": permission[]->railcontent_id,
341
344
  `;
342
- const filterParams = {};
343
- const query = buildQuery(
344
- filter,
345
- filterParams,
346
- fields,
347
- {
348
- sortOrder: sortOrder,
349
- start,
350
- end: end,
351
- });
352
- return fetchSanity(query, true);
345
+ const filterParams = {};
346
+ const query = await buildQuery(
347
+ filter,
348
+ filterParams,
349
+ fields,
350
+ {
351
+ sortOrder: sortOrder,
352
+ start,
353
+ end: end,
354
+ });
355
+ return fetchSanity(query, true);
353
356
  }
354
357
 
355
358
 
356
359
  /**
357
- * Fetch upcoming events for a specific brand.
358
- *
359
- * @param {string} brand - The brand for which to fetch upcoming events.
360
- * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of upcoming event objects or null if not found.
361
- *
362
- * @example
363
- * fetchUpcomingEvents('drumeo', {
364
- * page: 2,
365
- * limit: 20,
366
- * })
367
- * .then(events => console.log(events))
368
- * .catch(error => console.error(error));
369
- */
370
- export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {}) {
371
- const liveTypes = getUpcomingEventsTypes(brand);
372
- const typesString = arrayToStringRepresentation(liveTypes);
373
- const now = getSanityDate(new Date());
374
- const start = (page - 1) * limit;
375
- const end = start + limit;
376
- const fields = `
360
+ * Fetch upcoming events for a specific brand.
361
+ *
362
+ * @param {string} brand - The brand for which to fetch upcoming events.
363
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of upcoming event objects or null if not found.
364
+ *
365
+ * @example
366
+ * fetchUpcomingEvents('drumeo', {
367
+ * page: 2,
368
+ * limit: 20,
369
+ * })
370
+ * .then(events => console.log(events))
371
+ * .catch(error => console.error(error));
372
+ */
373
+ export async function fetchUpcomingEvents(brand, {page = 1, limit = 10} = {}) {
374
+ const liveTypes = getUpcomingEventsTypes(brand);
375
+ const typesString = arrayToStringRepresentation(liveTypes);
376
+ const now = getSanityDate(new Date());
377
+ const start = (page - 1) * limit;
378
+ const end = start + limit;
379
+ const fields = `
377
380
  "id": railcontent_id,
378
381
  title,
379
382
  "image": thumbnail.asset->url,
@@ -386,16 +389,16 @@ export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {})
386
389
  "type": _type,
387
390
  web_url_path,
388
391
  "permission_id": permission[]->railcontent_id,`;
389
- const query = buildRawQuery(
390
- `_type in ${typesString} &amp;&amp; brand == '${brand}' &amp;&amp; published_on > '${now}' &amp;&amp; status == 'scheduled'`,
391
- fields,
392
- {
393
- sortOrder: 'published_on asc',
394
- start: start,
395
- end: end,
396
- },
397
- );
398
- return fetchSanity(query, true);
392
+ const query = buildRawQuery(
393
+ `_type in ${typesString} &amp;&amp; brand == '${brand}' &amp;&amp; published_on > '${now}' &amp;&amp; status == 'scheduled'`,
394
+ fields,
395
+ {
396
+ sortOrder: 'published_on asc',
397
+ start: start,
398
+ end: end,
399
+ },
400
+ );
401
+ return fetchSanity(query, true);
399
402
  }
400
403
 
401
404
  /**
@@ -412,16 +415,16 @@ export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {})
412
415
  * .then(content => console.log(content))
413
416
  * .catch(error => console.error(error));
414
417
  */
415
- export async function fetchScheduledReleases(brand, { page = 1, limit = 10 }) {
416
- const upcomingTypes = getUpcomingEventsTypes(brand);
417
- const newTypes = getNewReleasesTypes(brand);
418
-
419
- const scheduledTypes = merge(upcomingTypes, newTypes)
420
- const typesString = arrayJoinWithQuotes(scheduledTypes);
421
- const now = getSanityDate(new Date());
422
- const start = (page - 1) * limit;
423
- const end = start + limit;
424
- const query = `*[_type in [${typesString}] &amp;&amp; brand == '${brand}' &amp;&amp; status in ['published','scheduled'] &amp;&amp; published_on > '${now}']{
418
+ export async function fetchScheduledReleases(brand, {page = 1, limit = 10}) {
419
+ const upcomingTypes = getUpcomingEventsTypes(brand);
420
+ const newTypes = getNewReleasesTypes(brand);
421
+
422
+ const scheduledTypes = merge(upcomingTypes, newTypes)
423
+ const typesString = arrayJoinWithQuotes(scheduledTypes);
424
+ const now = getSanityDate(new Date());
425
+ const start = (page - 1) * limit;
426
+ const end = start + limit;
427
+ const query = `*[_type in [${typesString}] &amp;&amp; brand == '${brand}' &amp;&amp; status in ['published','scheduled'] &amp;&amp; published_on > '${now}']{
425
428
  "id": railcontent_id,
426
429
  title,
427
430
  "image": thumbnail.asset->url,
@@ -435,21 +438,21 @@ export async function fetchScheduledReleases(brand, { page = 1, limit = 10 }) {
435
438
  web_url_path,
436
439
  "permission_id": permission[]->railcontent_id,
437
440
  } | order(published_on asc)[${start}...${end}]`;
438
- return fetchSanity(query, true);
441
+ return fetchSanity(query, true);
439
442
  }
440
443
 
441
444
  /**
442
- * Fetch content by a specific Railcontent ID.
443
- *
444
- * @param {string} id - The Railcontent ID of the content to fetch.
445
- * @param {string} contentType - The document type of content to fetch
446
- * @returns {Promise&lt;Object|null>} - A promise that resolves to the content object or null if not found.
447
- *
448
- * @example
449
- * fetchByRailContentId('abc123')
450
- * .then(content => console.log(content))
451
- * .catch(error => console.error(error));
452
- */
445
+ * Fetch content by a specific Railcontent ID.
446
+ *
447
+ * @param {string} id - The Railcontent ID of the content to fetch.
448
+ * @param {string} contentType - The document type of content to fetch
449
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to the content object or null if not found.
450
+ *
451
+ * @example
452
+ * fetchByRailContentId('abc123')
453
+ * .then(content => console.log(content))
454
+ * .catch(error => console.error(error));
455
+ */
453
456
  export async function fetchByRailContentId(id, contentType) {
454
457
 
455
458
  const query = buildRawQuery(
@@ -464,24 +467,24 @@ export async function fetchByRailContentId(id, contentType) {
464
467
  }
465
468
 
466
469
  /**
467
- * Fetch content by an array of Railcontent IDs.
468
- *
469
- * @param {Array&lt;string>} ids - The array of Railcontent IDs of the content to fetch.
470
- * @param {string} [contentType] - The content type the IDs to add needed fields to the response.
471
- * @returns {Promise&lt;Array&lt;Object>|null>} - A promise that resolves to an array of content objects or null if not found.
472
- *
473
- * @example
474
- * fetchByRailContentIds(['abc123', 'def456', 'ghi789'])
475
- * .then(contents => console.log(contents))
476
- * .catch(error => console.error(error));
477
- */
470
+ * Fetch content by an array of Railcontent IDs.
471
+ *
472
+ * @param {Array&lt;string>} ids - The array of Railcontent IDs of the content to fetch.
473
+ * @param {string} [contentType] - The content type the IDs to add needed fields to the response.
474
+ * @returns {Promise&lt;Array&lt;Object>|null>} - A promise that resolves to an array of content objects or null if not found.
475
+ *
476
+ * @example
477
+ * fetchByRailContentIds(['abc123', 'def456', 'ghi789'])
478
+ * .then(contents => console.log(contents))
479
+ * .catch(error => console.error(error));
480
+ */
478
481
  export async function fetchByRailContentIds(ids, contentType = undefined) {
479
- const idsString = ids.join(',');
482
+ const idsString = ids.join(',');
480
483
 
481
- const query = `*[railcontent_id in [${idsString}]]{
484
+ const query = `*[railcontent_id in [${idsString}]]{
482
485
  ${getFieldsForContentType(contentType)}
483
486
  }`
484
- return fetchSanity(query, true);
487
+ return fetchSanity(query, true);
485
488
  }
486
489
 
487
490
  /**
@@ -498,6 +501,7 @@ export async function fetchByRailContentIds(ids, contentType = undefined) {
498
501
  * @param {Array&lt;string>} [params.progressIds=undefined] - An array of railcontent IDs to filter the results by. Used for filtering by progress.
499
502
  * @param {boolean} [params.useDefaultFields=true] - use the default sanity fields for content Type
500
503
  * @param {Array&lt;string>} [params.customFields=[]] - An array of sanity fields to include in the request
504
+ * @param {string} [params.progress="all"] - An string representing which progress filter to use ("all", "in progress", "complete", "not started").
501
505
  * @returns {Promise&lt;Object|null>} - The fetched content data or null if not found.
502
506
  *
503
507
  * @example
@@ -516,15 +520,16 @@ export async function fetchByRailContentIds(ids, contentType = undefined) {
516
520
  * .catch(error => console.error(error));
517
521
  */
518
522
  export async function fetchAll(brand, type, {
519
- page = 1,
520
- limit = 10,
521
- searchTerm = "",
522
- sort = "-published_on",
523
- includedFields = [],
524
- groupBy = "",
525
- progressIds = undefined,
526
- useDefaultFields = true,
527
- customFields = [],
523
+ page = 1,
524
+ limit = 10,
525
+ searchTerm = "",
526
+ sort = "-published_on",
527
+ includedFields = [],
528
+ groupBy = "",
529
+ progressIds = undefined,
530
+ useDefaultFields = true,
531
+ customFields = [],
532
+ progress = "all"
528
533
  } = {}) {
529
534
  let config = contentTypeConfig[type] ?? {};
530
535
  let additionalFields = config?.fields ?? [];
@@ -539,8 +544,8 @@ export async function fetchAll(brand, type, {
539
544
  // Construct the search filter
540
545
  const searchFilter = searchTerm
541
546
  ? groupBy !== "" ?
542
- `&amp;&amp; (^.name match "${searchTerm}*" || title match "${searchTerm}*")`
543
- : `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")`
547
+ `&amp;&amp; (^.name match "${searchTerm}*" || title match "${searchTerm}*")`
548
+ : `&amp;&amp; (artist->name match "${searchTerm}*" || instructor[]->name match "${searchTerm}*" || title match "${searchTerm}*" || name match "${searchTerm}*")`
544
549
  : "";
545
550
 
546
551
  // Construct the included fields filter, replacing 'difficulty' with 'difficulty_string'
@@ -549,13 +554,12 @@ export async function fetchAll(brand, type, {
549
554
  : "";
550
555
 
551
556
  // limits the results to supplied progressIds for started &amp; completed filters
552
- const progressFilter = progressIds !== undefined ?
553
- `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
557
+ const progressFilter = await getProgressFilter(progress, progressIds);
554
558
 
555
559
  // Determine the sort order
556
560
  const sortOrder = getSortOrder(sort);
557
561
 
558
- let fields = useDefaultFields ? customFields.concat(DEFAULT_FIELDS, additionalFields) : customFields;
562
+ let fields = useDefaultFields ? customFields.concat(DEFAULT_FIELDS, additionalFields) : customFields;
559
563
  let fieldsString = fields.join(',');
560
564
 
561
565
  // Determine the group by clause
@@ -579,7 +583,7 @@ export async function fetchAll(brand, type, {
579
583
  `;
580
584
  filter = `_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0`;
581
585
  } else if (groupBy !== "") {
582
- const webUrlPath = (groupBy == 'genre')?'/genres':'';
586
+ const webUrlPath = (groupBy == 'genre') ? '/genres' : '';
583
587
  const lessonsFilter = `brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}`;
584
588
  entityFieldsString = `
585
589
  'id': railcontent_id,
@@ -609,8 +613,29 @@ export async function fetchAll(brand, type, {
609
613
  return fetchSanity(query, true);
610
614
  }
611
615
 
612
- export function getSortOrder(sort= '-published_on', groupBy)
613
- {
616
+ async function getProgressFilter(progress, progressIds) {
617
+ switch (progress) {
618
+ case "all":
619
+ return progressIds !== undefined ?
620
+ `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
621
+ case "in progress": {
622
+ const ids = await getAllStarted();
623
+ return `&amp;&amp; railcontent_id in [${ids.join(',')}]`;
624
+ }
625
+ case "completed": {
626
+ const ids = await getAllCompleted();
627
+ return `&amp;&amp; railcontent_id in [${ids.join(',')}]`;
628
+ }
629
+ case "not started": {
630
+ const ids = await getAllStartedOrCompleted();
631
+ return `&amp;&amp; !(railcontent_id in [${ids.join(',')}])`;
632
+ }
633
+ default:
634
+ throw new Error(`'${progress}' progress option not implemented`);
635
+ }
636
+ }
637
+
638
+ export function getSortOrder(sort = '-published_on', groupBy) {
614
639
  // Determine the sort order
615
640
  let sortOrder = '';
616
641
  const isDesc = sort.startsWith('-');
@@ -633,69 +658,69 @@ export function getSortOrder(sort= '-published_on', groupBy)
633
658
  }
634
659
 
635
660
  /**
636
- * Fetches all available filter options based on brand, filters, and various optional criteria.
637
- *
638
- * This function constructs a query to retrieve the total number of results and filter options such as difficulty, instrument type, and genre.
639
- * The filter options are dynamically generated based on the provided filters, style, artist, and content type.
640
- * If a coachId is provided, the content type must be 'coach-lessons'.
641
- *
642
- * @param {string} brand - Brand to filter.
643
- * @param {string[]} filters - Key-value pairs to filter the query.
644
- * @param {string} [style] - Optional style/genre filter.
645
- * @param {string} [artist] - Optional artist name filter.
646
- * @param {string} contentType - Content type (e.g., 'song', 'lesson').
647
- * @param {string} [term] - Optional search term for title, album, artist, or genre.
648
- * @param {Array&lt;string>} [progressIds] - Optional array of progress IDs to filter by.
649
- * @param {string} [coachId] - Optional coach ID (only valid if contentType is 'coach-lessons').
650
- * @param {boolean} [includeTabs=false] - Whether to include tabs in the returned metadata.
651
- * @returns {Promise&lt;Object>} - The filter options and metadata.
652
- * @throws {Error} If coachId is provided but contentType isn't 'coach-lessons'.
653
- *
654
- * @example
655
- * // Fetch filter options for 'song' content type:
656
- * fetchAllFilterOptions('myBrand', [], 'Rock', 'John Doe', 'song', 'Love')
657
- * .then(options => console.log(options))
658
- * .catch(error => console.error(error));
659
- *
660
- * @example
661
- * // Fetch filter options for a coach's lessons with coachId:
662
- * fetchAllFilterOptions('myBrand', [], 'Rock', 'John Doe', 'coach-lessons', 'Love', undefined, '123')
663
- * .then(options => console.log(options))
664
- * .catch(error => console.error(error));
665
- */
661
+ * Fetches all available filter options based on brand, filters, and various optional criteria.
662
+ *
663
+ * This function constructs a query to retrieve the total number of results and filter options such as difficulty, instrument type, and genre.
664
+ * The filter options are dynamically generated based on the provided filters, style, artist, and content type.
665
+ * If a coachId is provided, the content type must be 'coach-lessons'.
666
+ *
667
+ * @param {string} brand - Brand to filter.
668
+ * @param {string[]} filters - Key-value pairs to filter the query.
669
+ * @param {string} [style] - Optional style/genre filter.
670
+ * @param {string} [artist] - Optional artist name filter.
671
+ * @param {string} contentType - Content type (e.g., 'song', 'lesson').
672
+ * @param {string} [term] - Optional search term for title, album, artist, or genre.
673
+ * @param {Array&lt;string>} [progressIds] - Optional array of progress IDs to filter by.
674
+ * @param {string} [coachId] - Optional coach ID (only valid if contentType is 'coach-lessons').
675
+ * @param {boolean} [includeTabs=false] - Whether to include tabs in the returned metadata.
676
+ * @returns {Promise&lt;Object>} - The filter options and metadata.
677
+ * @throws {Error} If coachId is provided but contentType isn't 'coach-lessons'.
678
+ *
679
+ * @example
680
+ * // Fetch filter options for 'song' content type:
681
+ * fetchAllFilterOptions('myBrand', [], 'Rock', 'John Doe', 'song', 'Love')
682
+ * .then(options => console.log(options))
683
+ * .catch(error => console.error(error));
684
+ *
685
+ * @example
686
+ * // Fetch filter options for a coach's lessons with coachId:
687
+ * fetchAllFilterOptions('myBrand', [], 'Rock', 'John Doe', 'coach-lessons', 'Love', undefined, '123')
688
+ * .then(options => console.log(options))
689
+ * .catch(error => console.error(error));
690
+ */
666
691
  export async function fetchAllFilterOptions(
667
- brand,
668
- filters = [],
669
- style,
670
- artist,
671
- contentType,
672
- term,
673
- progressIds,
674
- coachId,
675
- includeTabs = false,
692
+ brand,
693
+ filters = [],
694
+ style,
695
+ artist,
696
+ contentType,
697
+ term,
698
+ progressIds,
699
+ coachId,
700
+ includeTabs = false,
676
701
  ) {
677
- if (coachId &amp;&amp; contentType !== 'coach-lessons') {
678
- throw new Error(`Invalid contentType: '${contentType}' for coachId. It must be 'coach-lessons'.`);
679
- }
702
+ if (coachId &amp;&amp; contentType !== 'coach-lessons') {
703
+ throw new Error(`Invalid contentType: '${contentType}' for coachId. It must be 'coach-lessons'.`);
704
+ }
680
705
 
681
- const includedFieldsFilter = filters?.length ? filtersToGroq(filters) : undefined;
682
- const progressFilter = progressIds ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
706
+ const includedFieldsFilter = filters?.length ? filtersToGroq(filters) : undefined;
707
+ const progressFilter = progressIds ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
683
708
 
684
- const constructCommonFilter = (excludeFilter) => {
685
- const filterWithoutOption = excludeFilter ? filtersToGroq(filters, excludeFilter) : includedFieldsFilter;
686
- return coachId
687
- ? `brand == '${brand}' &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${coachId}]._id) ${filterWithoutOption || ''}`
688
- : `_type == '${contentType}' &amp;&amp; brand == "${brand}"${style &amp;&amp; excludeFilter !== "style" ? ` &amp;&amp; '${style}' in genre[]->name` : ''}${artist &amp;&amp; excludeFilter !== "artist" ? ` &amp;&amp; artist->name == '${artist}'` : ''} ${progressFilter} ${filterWithoutOption || ''}`;
689
- };
709
+ const constructCommonFilter = (excludeFilter) => {
710
+ const filterWithoutOption = excludeFilter ? filtersToGroq(filters, excludeFilter) : includedFieldsFilter;
711
+ return coachId
712
+ ? `brand == '${brand}' &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${coachId}]._id) ${filterWithoutOption || ''}`
713
+ : `_type == '${contentType}' &amp;&amp; brand == "${brand}"${style &amp;&amp; excludeFilter !== "style" ? ` &amp;&amp; '${style}' in genre[]->name` : ''}${artist &amp;&amp; excludeFilter !== "artist" ? ` &amp;&amp; artist->name == '${artist}'` : ''} ${progressFilter} ${filterWithoutOption || ''}`;
714
+ };
690
715
 
691
- const metaData = processMetadata(brand, contentType, true);
692
- const allowableFilters = metaData?.allowableFilters || [];
693
- const tabs = metaData?.tabs || [];
694
- const catalogName = metaData?.shortname || metaData?.name;
716
+ const metaData = processMetadata(brand, contentType, true);
717
+ const allowableFilters = metaData?.allowableFilters || [];
718
+ const tabs = metaData?.tabs || [];
719
+ const catalogName = metaData?.shortname || metaData?.name;
695
720
 
696
- const dynamicFilterOptions = allowableFilters.map(filter => getFilterOptions(filter, constructCommonFilter(filter), contentType, brand)).join(' ');
721
+ const dynamicFilterOptions = allowableFilters.map(filter => getFilterOptions(filter, constructCommonFilter(filter), contentType, brand)).join(' ');
697
722
 
698
- const query = `
723
+ const query = `
699
724
  {
700
725
  "meta": {
701
726
  "totalResults": count(*[${constructCommonFilter()}
@@ -706,28 +731,28 @@ export async function fetchAllFilterOptions(
706
731
  }
707
732
  }`;
708
733
 
709
- const results = await fetchSanity(query, true, { processNeedAccess: false });
734
+ const results = await fetchSanity(query, true, {processNeedAccess: false});
710
735
 
711
- return includeTabs ? { ...results, tabs, catalogName } : results;
736
+ return includeTabs ? {...results, tabs, catalogName} : results;
712
737
  }
713
738
 
714
739
 
715
740
  /**
716
- * Fetch children content by Railcontent ID.
717
- * @param {string} railcontentId - The Railcontent ID of the parent content.
718
- * @param {string} [contentType] - The content type the IDs to add needed fields to the response.
719
- * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children content data or [] if not found.
720
- */
741
+ * Fetch children content by Railcontent ID.
742
+ * @param {string} railcontentId - The Railcontent ID of the parent content.
743
+ * @param {string} [contentType] - The content type the IDs to add needed fields to the response.
744
+ * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children content data or [] if not found.
745
+ */
721
746
  export async function fetchChildren(railcontentId, contentType) {
722
- const query = `*[railcontent_id == ${railcontentId}]{
747
+ const query = `*[railcontent_id == ${railcontentId}]{
723
748
  title,
724
749
 
725
750
  'children': child[]->{
726
751
  ${getFieldsForContentType(contentType)}
727
752
  },
728
753
  }[0..1]`;
729
- let parent = await fetchSanity(query, false);
730
- return parent['children'] ?? [];
754
+ let parent = await fetchSanity(query, false);
755
+ return parent['children'] ?? [];
731
756
  }
732
757
 
733
758
  /**
@@ -748,44 +773,44 @@ export async function fetchParentByRailContentId(railcontentId) {
748
773
  }
749
774
 
750
775
  /**
751
- * Fetch the Methods (learning-paths) for a specific brand.
752
- * @param {string} brand - The brand for which to fetch methods.
753
- * @returns {Promise&lt;Object|null>} - The fetched methods data or null if not found.
754
- */
776
+ * Fetch the Methods (learning-paths) for a specific brand.
777
+ * @param {string} brand - The brand for which to fetch methods.
778
+ * @returns {Promise&lt;Object|null>} - The fetched methods data or null if not found.
779
+ */
755
780
  export async function fetchMethods(brand) {
756
781
  const query = `*[_type == 'learning-path' &amp;&amp; brand == '${brand}'] {
757
- ${ getFieldsForContentType() }
782
+ ${getFieldsForContentType()}
758
783
  } | order(published_on asc)`
759
- return fetchSanity(query, true);
784
+ return fetchSanity(query, true);
760
785
  }
761
786
 
762
787
  /**
763
- * Fetch the Foundations 2019.
764
- * @param {string} slug - The slug of the method.
765
- * @returns {Promise&lt;Object|null>} - The fetched foundation data or null if not found.
766
- */
788
+ * Fetch the Foundations 2019.
789
+ * @param {string} slug - The slug of the method.
790
+ * @returns {Promise&lt;Object|null>} - The fetched foundation data or null if not found.
791
+ */
767
792
  export async function fetchFoundation(slug) {
768
- const filterParams = {};
769
- const query = buildQuery(
770
- `_type == 'foundation' &amp;&amp; slug.current == "${slug}"`,
771
- filterParams,
772
- getFieldsForContentType('foundation'),
773
- {
774
- sortOrder: 'published_on asc',
775
- isSingle: true,
776
- }
777
- );
778
- return fetchSanity(query, false);
793
+ const filterParams = {};
794
+ const query = await buildQuery(
795
+ `_type == 'foundation' &amp;&amp; slug.current == "${slug}"`,
796
+ filterParams,
797
+ getFieldsForContentType('foundation'),
798
+ {
799
+ sortOrder: 'published_on asc',
800
+ isSingle: true,
801
+ }
802
+ );
803
+ return fetchSanity(query, false);
779
804
  }
780
805
 
781
806
  /**
782
- * Fetch the Method (learning-paths) for a specific brand.
783
- * @param {string} brand - The brand for which to fetch methods.
784
- * @param {string} slug - The slug of the method.
785
- * @returns {Promise&lt;Object|null>} - The fetched methods data or null if not found.
786
- */
807
+ * Fetch the Method (learning-paths) for a specific brand.
808
+ * @param {string} brand - The brand for which to fetch methods.
809
+ * @param {string} slug - The slug of the method.
810
+ * @returns {Promise&lt;Object|null>} - The fetched methods data or null if not found.
811
+ */
787
812
  export async function fetchMethod(brand, slug) {
788
- const query = `*[_type == 'learning-path' &amp;&amp; brand == "${brand}" &amp;&amp; slug.current == "${slug}"] {
813
+ const query = `*[_type == 'learning-path' &amp;&amp; brand == "${brand}" &amp;&amp; slug.current == "${slug}"] {
789
814
  "description": ${descriptionField},
790
815
  "instructors":instructor[]->name,
791
816
  published_on,
@@ -815,16 +840,16 @@ export async function fetchMethod(brand, slug) {
815
840
  xp,
816
841
  }
817
842
  } | order(published_on asc)`
818
- return fetchSanity(query, false);
843
+ return fetchSanity(query, false);
819
844
  }
820
845
 
821
846
  /**
822
- * Fetch the child courses for a specific method by Railcontent ID.
823
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
824
- * @returns {Promise&lt;Object|null>} - The fetched next lesson data or null if not found.
825
- */
847
+ * Fetch the child courses for a specific method by Railcontent ID.
848
+ * @param {string} railcontentId - The Railcontent ID of the current lesson.
849
+ * @returns {Promise&lt;Object|null>} - The fetched next lesson data or null if not found.
850
+ */
826
851
  export async function fetchMethodChildren(railcontentId) {
827
- const query = `*[railcontent_id == ${railcontentId}]{
852
+ const query = `*[railcontent_id == ${railcontentId}]{
828
853
  child_count,
829
854
  "id": railcontent_id,
830
855
  "description": ${descriptionField},
@@ -835,20 +860,20 @@ export async function fetchMethodChildren(railcontentId) {
835
860
  ${getFieldsForContentType('method')}
836
861
  },
837
862
  }[0..1]`;
838
- return fetchSanity(query, true);
863
+ return fetchSanity(query, true);
839
864
  }
840
865
 
841
866
  /**
842
- * Fetch the next lesson for a specific method by Railcontent ID.
843
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
867
+ * Fetch the next lesson for a specific method by Railcontent ID.
868
+ * @param {string} railcontentId - The Railcontent ID of the current lesson.
844
869
  * @param {string} methodId - The RailcontentID of the method
845
- * @returns {Promise&lt;Object|null>} - The fetched next lesson data or null if not found.
846
- */
870
+ * @returns {Promise&lt;Object|null>} - The fetched next lesson data or null if not found.
871
+ */
847
872
  export async function fetchMethodNextLesson(railcontentId, methodId) {
848
- const sortedChildren = await fetchMethodChildrenIds(methodId);
849
- const index = sortedChildren.indexOf(railcontentId);
850
- const childIndex = sortedChildren[index + 1];
851
- return childIndex ? await fetchByRailContentId(childIndex) : null;
873
+ const sortedChildren = await fetchMethodChildrenIds(methodId);
874
+ const index = sortedChildren.indexOf(railcontentId);
875
+ const childIndex = sortedChildren[index + 1];
876
+ return childIndex ? await fetchByRailContentId(childIndex) : null;
852
877
  }
853
878
 
854
879
  /**
@@ -865,18 +890,22 @@ export async function fetchMethodPreviousNextLesson(railcontentId, methodId) {
865
890
  const sortedChildren = await fetchMethodChildrenIds(methodId);
866
891
  const index = sortedChildren.indexOf(Number(railcontentId));
867
892
  let nextId = sortedChildren[index + 1];
868
- let previousId = sortedChildren[index -1];
893
+ let previousId = sortedChildren[index - 1];
869
894
  let nextPrev = await fetchByRailContentIds([nextId, previousId]);
870
- const nextLesson = nextPrev.find((elem) => {return elem['id'] === nextId});
871
- const prevLesson = nextPrev.find((elem) => {return elem['id'] === previousId});
895
+ const nextLesson = nextPrev.find((elem) => {
896
+ return elem['id'] === nextId
897
+ });
898
+ const prevLesson = nextPrev.find((elem) => {
899
+ return elem['id'] === previousId
900
+ });
872
901
  return {nextLesson, prevLesson};
873
902
  }
874
903
 
875
904
  /**
876
- * Fetch all children of a specific method by Railcontent ID.
877
- * @param {string} railcontentId - The Railcontent ID of the method.
878
- * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children data or null if not found.
879
- */
905
+ * Fetch all children of a specific method by Railcontent ID.
906
+ * @param {string} railcontentId - The Railcontent ID of the method.
907
+ * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children data or null if not found.
908
+ */
880
909
  export async function fetchMethodChildrenIds(railcontentId) {
881
910
  const query = `*[ railcontent_id == ${railcontentId}]{
882
911
  'children': child[]-> {
@@ -896,25 +925,24 @@ export async function fetchMethodChildrenIds(railcontentId) {
896
925
  return getChildrenToDepth(allChildren, 4);
897
926
  }
898
927
 
899
- function getChildrenToDepth(parent, depth = 1)
900
- {
928
+ function getChildrenToDepth(parent, depth = 1) {
901
929
  let allChildrenIds = [];
902
930
  if (parent &amp;&amp; parent['children'] &amp;&amp; depth > 0) {
903
931
  parent['children'].forEach((child) => {
904
- if(!child['children']) {
932
+ if (!child['children']) {
905
933
  allChildrenIds.push(child['id']);
906
934
  }
907
- allChildrenIds = allChildrenIds.concat(getChildrenToDepth(child, depth-1));
935
+ allChildrenIds = allChildrenIds.concat(getChildrenToDepth(child, depth - 1));
908
936
  })
909
937
  }
910
938
  return allChildrenIds;
911
939
  }
912
940
 
913
941
  /**
914
- * Fetch the next and previous lessons for a specific lesson by Railcontent ID.
915
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
916
- * @returns {Promise&lt;Object|null>} - The fetched next and previous lesson data or null if found.
917
- */
942
+ * Fetch the next and previous lessons for a specific lesson by Railcontent ID.
943
+ * @param {string} railcontentId - The Railcontent ID of the current lesson.
944
+ * @returns {Promise&lt;Object|null>} - The fetched next and previous lesson data or null if found.
945
+ */
918
946
  export async function fetchNextPreviousLesson(railcontentId) {
919
947
  const document = await fetchLessonContent(railcontentId);
920
948
  if (document.parent_content_data &amp;&amp; document.parent_content_data.length > 0) {
@@ -997,7 +1025,7 @@ export async function fetchLessonContent(railContentId) {
997
1025
  parent_content_data,
998
1026
  sort,
999
1027
  xp`;
1000
- const query = buildQuery(
1028
+ const query = await buildQuery(
1001
1029
  `railcontent_id == ${railContentId}`,
1002
1030
  filterParams,
1003
1031
  fields,
@@ -1005,15 +1033,15 @@ export async function fetchLessonContent(railContentId) {
1005
1033
  isSingle: true,
1006
1034
  }
1007
1035
  );
1008
- return fetchSanity(query, false);
1036
+ return fetchSanity(query, false);
1009
1037
  }
1010
1038
 
1011
1039
  /**
1012
- * Fetch related lessons for a specific lesson by RailContent ID and type.
1013
- * @param {string} railContentId - The RailContent ID of the current lesson.
1014
- * @param {string} brand - The current brand.
1015
- * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons data or null if not found.
1016
- */
1040
+ * Fetch related lessons for a specific lesson by RailContent ID and type.
1041
+ * @param {string} railContentId - The RailContent ID of the current lesson.
1042
+ * @param {string} brand - The current brand.
1043
+ * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons data or null if not found.
1044
+ */
1017
1045
  export async function fetchRelatedLessons(railContentId, brand) {
1018
1046
  const query = `*[railcontent_id == ${railContentId} &amp;&amp; brand == "${brand}" &amp;&amp; references(*[_type=='permission']._id)]{
1019
1047
  _type, parent_type, railcontent_id,
@@ -1028,13 +1056,13 @@ export async function fetchRelatedLessons(railContentId, brand) {
1028
1056
  }
1029
1057
 
1030
1058
  /**
1031
- * Fetch related method lessons for a specific lesson by RailContent ID and type.
1032
- * @param {string} railContentId - The RailContent ID of the current lesson.
1033
- * @param {string} brand - The current brand.
1034
- * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons
1035
- */
1059
+ * Fetch related method lessons for a specific lesson by RailContent ID and type.
1060
+ * @param {string} railContentId - The RailContent ID of the current lesson.
1061
+ * @param {string} brand - The current brand.
1062
+ * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons
1063
+ */
1036
1064
  export async function fetchRelatedMethodLessons(railContentId, brand) {
1037
- const query = `*[railcontent_id == ${railContentId} &amp;&amp; brand == "${brand}"]{
1065
+ const query = `*[railcontent_id == ${railContentId} &amp;&amp; brand == "${brand}"]{
1038
1066
  "id":_id,
1039
1067
  "related_lessons": *[references(^._id)][0].child[]->{
1040
1068
  "id": railcontent_id,
@@ -1048,57 +1076,57 @@ export async function fetchRelatedMethodLessons(railContentId, brand) {
1048
1076
  }
1049
1077
  }
1050
1078
  }`
1051
- return fetchSanity(query, false);
1079
+ return fetchSanity(query, false);
1052
1080
  }
1053
1081
 
1054
1082
  /**
1055
- * Fetch all packs.
1056
- * @param {string} brand - The brand for which to fetch packs.
1057
- * @param {string} [searchTerm=""] - The search term to filter packs.
1058
- * @param {string} [sort="-published_on"] - The field to sort the packs by.
1059
- * @param {number} [params.page=1] - The page number for pagination.
1060
- * @param {number} [params.limit=10] - The number of items per page.
1061
- * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
1062
- */
1083
+ * Fetch all packs.
1084
+ * @param {string} brand - The brand for which to fetch packs.
1085
+ * @param {string} [searchTerm=""] - The search term to filter packs.
1086
+ * @param {string} [sort="-published_on"] - The field to sort the packs by.
1087
+ * @param {number} [params.page=1] - The page number for pagination.
1088
+ * @param {number} [params.limit=10] - The number of items per page.
1089
+ * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
1090
+ */
1063
1091
  export async function fetchAllPacks(brand, sort = "-published_on", searchTerm = "", page = 1, limit = 10) {
1064
- const sortOrder = getSortOrder(sort);
1065
- const filter = `_type == 'pack' &amp;&amp; brand == '${brand}' &amp;&amp; title match "${searchTerm}*"`
1066
- const filterParams = {};
1067
- const fields = getFieldsForContentType('pack');
1068
- const start = (page - 1) * limit;
1069
- const end = start + limit;
1070
-
1071
- const query = buildQuery(
1072
- filter,
1073
- filterParams,
1074
- getFieldsForContentType('pack'),
1075
- {
1076
- logo_image_url: 'logo_image_url.asset->url',
1077
- sortOrder: sortOrder,
1078
- start,
1079
- end
1080
- }
1081
- );
1082
- return fetchSanity(query, true);
1092
+ const sortOrder = getSortOrder(sort);
1093
+ const filter = `_type == 'pack' &amp;&amp; brand == '${brand}' &amp;&amp; title match "${searchTerm}*"`
1094
+ const filterParams = {};
1095
+ const fields = getFieldsForContentType('pack');
1096
+ const start = (page - 1) * limit;
1097
+ const end = start + limit;
1098
+
1099
+ const query = await buildQuery(
1100
+ filter,
1101
+ filterParams,
1102
+ getFieldsForContentType('pack'),
1103
+ {
1104
+ logo_image_url: 'logo_image_url.asset->url',
1105
+ sortOrder: sortOrder,
1106
+ start,
1107
+ end
1108
+ }
1109
+ );
1110
+ return fetchSanity(query, true);
1083
1111
  }
1084
1112
 
1085
1113
  /**
1086
- * Fetch all content for a specific pack by Railcontent ID.
1087
- * @param {string} railcontentId - The Railcontent ID of the pack.
1088
- * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
1089
- */
1114
+ * Fetch all content for a specific pack by Railcontent ID.
1115
+ * @param {string} railcontentId - The Railcontent ID of the pack.
1116
+ * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
1117
+ */
1090
1118
  export async function fetchPackAll(railcontentId) {
1091
- return fetchByRailContentId(railcontentId, 'pack');
1119
+ return fetchByRailContentId(railcontentId, 'pack');
1092
1120
  }
1093
1121
 
1094
1122
  export async function fetchLiveEvent(brand) {
1095
1123
  //calendarIDs taken from addevent.php
1096
1124
  // TODO import instructor calendars to Sanity
1097
1125
  let defaultCalendarID = '';
1098
- switch(brand) {
1126
+ switch (brand) {
1099
1127
  case ('drumeo'):
1100
1128
  defaultCalendarID = 'GP142387';
1101
- break;
1129
+ break;
1102
1130
  case ('pianote'):
1103
1131
  defaultCalendarID = 'be142408';
1104
1132
  break;
@@ -1148,7 +1176,7 @@ export async function fetchLiveEvent(brand) {
1148
1176
  * .catch(error => console.error(error));
1149
1177
  */
1150
1178
  export async function fetchPackChildren(railcontentId) {
1151
- return fetchChildren(railcontentId, 'pack-children');
1179
+ return fetchChildren(railcontentId, 'pack-children');
1152
1180
  }
1153
1181
 
1154
1182
  /**
@@ -1162,10 +1190,10 @@ export async function fetchPackChildren(railcontentId) {
1162
1190
  * .catch(error => console.error(error));
1163
1191
  */
1164
1192
  export async function fetchPackData(id) {
1165
- const query = `*[railcontent_id == ${id}]{
1193
+ const query = `*[railcontent_id == ${id}]{
1166
1194
  ${getFieldsForContentType("pack")}
1167
1195
  } [0...1]`;
1168
- return fetchSanity(query, false);
1196
+ return fetchSanity(query, false);
1169
1197
  }
1170
1198
 
1171
1199
  /**
@@ -1179,11 +1207,11 @@ export async function fetchPackData(id) {
1179
1207
  * .catch(error => console.error(error));
1180
1208
  */
1181
1209
  export async function fetchChallengeOverview(id) {
1182
- // WIP
1183
- const query = `*[railcontent_id == ${id}]{
1210
+ // WIP
1211
+ const query = `*[railcontent_id == ${id}]{
1184
1212
  ${getFieldsForContentType("challenge")}
1185
1213
  } [0...1]`;
1186
- return fetchSanity(query, false);
1214
+ return fetchSanity(query, false);
1187
1215
  }
1188
1216
 
1189
1217
  /**
@@ -1204,32 +1232,32 @@ export async function fetchChallengeOverview(id) {
1204
1232
  * .catch(error => console.error(error));
1205
1233
  */
1206
1234
  export async function fetchCoachLessons(brand, id, {
1207
- sortOrder = '-published_on',
1208
- searchTerm = '',
1209
- page = 1,
1210
- limit = 20,
1211
- includedFields = [],
1235
+ sortOrder = '-published_on',
1236
+ searchTerm = '',
1237
+ page = 1,
1238
+ limit = 20,
1239
+ includedFields = [],
1212
1240
  } = {}) {
1213
- const fieldsString = getFieldsForContentType();
1214
- const start = (page - 1) * limit;
1215
- const end = start + limit;
1216
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"`: ''
1217
- const includedFieldsFilter = includedFields.length > 0
1241
+ const fieldsString = getFieldsForContentType();
1242
+ const start = (page - 1) * limit;
1243
+ const end = start + limit;
1244
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1245
+ const includedFieldsFilter = includedFields.length > 0
1218
1246
  ? filtersToGroq(includedFields)
1219
1247
  : "";
1220
- const filter = `brand == '${brand}' ${searchFilter} ${includedFieldsFilter} &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${id}]._id)`;
1248
+ const filter = `brand == '${brand}' ${searchFilter} ${includedFieldsFilter} &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${id}]._id)`;
1221
1249
 
1222
- sortOrder = getSortOrder(sortOrder);
1223
- const query = buildEntityAndTotalQuery(
1224
- filter,
1225
- fieldsString,
1226
- {
1227
- sortOrder: sortOrder,
1228
- start: start,
1229
- end: end,
1230
- },
1231
- );
1232
- return fetchSanity(query, true);
1250
+ sortOrder = getSortOrder(sortOrder);
1251
+ const query = buildEntityAndTotalQuery(
1252
+ filter,
1253
+ fieldsString,
1254
+ {
1255
+ sortOrder: sortOrder,
1256
+ start: start,
1257
+ end: end,
1258
+ },
1259
+ );
1260
+ return fetchSanity(query, true);
1233
1261
  }
1234
1262
 
1235
1263
  /**
@@ -1243,7 +1271,7 @@ export async function fetchCoachLessons(brand, id, {
1243
1271
  * .catch(error => console.error(error));
1244
1272
  */
1245
1273
  export async function fetchCourseOverview(id) {
1246
- return fetchByRailContentId(id, 'course');
1274
+ return fetchByRailContentId(id, 'course');
1247
1275
  }
1248
1276
 
1249
1277
  /**
@@ -1257,21 +1285,21 @@ export async function fetchCourseOverview(id) {
1257
1285
  * .catch(error => console.error(error));
1258
1286
  */
1259
1287
  export async function fetchParentForDownload(id) {
1260
- const query = buildRawQuery(
1261
- `railcontent_id == ${id}`,
1262
- getFieldsForContentType('parent-download'),
1263
- {
1264
- isSingle: true,
1265
- },
1266
- );
1288
+ const query = buildRawQuery(
1289
+ `railcontent_id == ${id}`,
1290
+ getFieldsForContentType('parent-download'),
1291
+ {
1292
+ isSingle: true,
1293
+ },
1294
+ );
1267
1295
 
1268
- return fetchSanity(query, false);
1296
+ return fetchSanity(query, false);
1269
1297
  }
1270
1298
 
1271
1299
  /**
1272
1300
  * Fetch the data needed for the coach screen.
1273
1301
  * @param {string} id - The Railcontent ID of the coach
1274
- *
1302
+ *
1275
1303
  * @returns {Promise&lt;Object|null>} - The lessons for the instructor or null if not found.
1276
1304
  *
1277
1305
  * @example
@@ -1280,30 +1308,30 @@ export async function fetchParentForDownload(id) {
1280
1308
  * .catch(error => console.error(error));
1281
1309
  */
1282
1310
  export async function fetchByReference(brand, {
1283
- sortOrder = '-published_on',
1284
- searchTerm = '',
1285
- page = 1,
1286
- limit = 20,
1287
- includedFields = [],
1311
+ sortOrder = '-published_on',
1312
+ searchTerm = '',
1313
+ page = 1,
1314
+ limit = 20,
1315
+ includedFields = [],
1288
1316
  } = {}) {
1289
- const fieldsString = getFieldsForContentType();
1290
- const start = (page - 1) * limit;
1291
- const end = start + limit;
1292
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"`: '';
1293
- const includedFieldsFilter = includedFields.length > 0
1317
+ const fieldsString = getFieldsForContentType();
1318
+ const start = (page - 1) * limit;
1319
+ const end = start + limit;
1320
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : '';
1321
+ const includedFieldsFilter = includedFields.length > 0
1294
1322
  ? includedFields.join(' &amp;&amp; ')
1295
1323
  : "";
1296
- const filter = `brand == '${brand}' ${searchFilter} &amp;&amp; references(*[${includedFieldsFilter}]._id)`;
1297
- const query = buildEntityAndTotalQuery(
1298
- filter,
1299
- fieldsString,
1300
- {
1301
- sortOrder: getSortOrder(sortOrder),
1302
- start: start,
1303
- end: end,
1304
- },
1305
- );
1306
- return fetchSanity(query, true);
1324
+ const filter = `brand == '${brand}' ${searchFilter} &amp;&amp; references(*[${includedFieldsFilter}]._id)`;
1325
+ const query = buildEntityAndTotalQuery(
1326
+ filter,
1327
+ fieldsString,
1328
+ {
1329
+ sortOrder: getSortOrder(sortOrder),
1330
+ start: start,
1331
+ end: end,
1332
+ },
1333
+ );
1334
+ return fetchSanity(query, true);
1307
1335
  }
1308
1336
 
1309
1337
  /**
@@ -1326,28 +1354,28 @@ export async function fetchByReference(brand, {
1326
1354
  * .catch(error => console.error(error));
1327
1355
  */
1328
1356
  export async function fetchArtistLessons(brand, name, contentType, {
1329
- sort = '-published_on',
1330
- searchTerm = '',
1331
- page = 1,
1332
- limit = 10,
1333
- includedFields = [],
1334
- progressIds = undefined,
1357
+ sort = '-published_on',
1358
+ searchTerm = '',
1359
+ page = 1,
1360
+ limit = 10,
1361
+ includedFields = [],
1362
+ progressIds = undefined,
1335
1363
  } = {}) {
1336
1364
 
1337
- const fieldsString = DEFAULT_FIELDS.join(',');
1338
- const start = (page - 1) * limit;
1339
- const end = start + limit;
1340
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"`: ''
1341
- const sortOrder = getSortOrder(sort);
1342
- const addType = contentType &amp;&amp; Array.isArray(contentType) ? `_type in ['${contentType.join("', '")}'] &amp;&amp;` : contentType ? `_type == '${contentType}' &amp;&amp; `:''
1343
- const includedFieldsFilter = includedFields.length > 0
1344
- ? filtersToGroq(includedFields)
1345
- : "";
1365
+ const fieldsString = DEFAULT_FIELDS.join(',');
1366
+ const start = (page - 1) * limit;
1367
+ const end = start + limit;
1368
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1369
+ const sortOrder = getSortOrder(sort);
1370
+ const addType = contentType &amp;&amp; Array.isArray(contentType) ? `_type in ['${contentType.join("', '")}'] &amp;&amp;` : contentType ? `_type == '${contentType}' &amp;&amp; ` : ''
1371
+ const includedFieldsFilter = includedFields.length > 0
1372
+ ? filtersToGroq(includedFields)
1373
+ : "";
1346
1374
 
1347
- // limits the results to supplied progressIds for started &amp; completed filters
1348
- const progressFilter = progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
1375
+ // limits the results to supplied progressIds for started &amp; completed filters
1376
+ const progressFilter = progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
1349
1377
 
1350
- const query = `{
1378
+ const query = `{
1351
1379
  "entity":
1352
1380
  *[_type == 'artist' &amp;&amp; name == '${name}']
1353
1381
  {'type': _type, name, 'thumbnail_url':thumbnail_url.asset->url,
@@ -1356,7 +1384,7 @@ export async function fetchArtistLessons(brand, name, contentType, {
1356
1384
  [${start}...${end}]}
1357
1385
  |order(${sortOrder})
1358
1386
  }`;
1359
- return fetchSanity(query, true);
1387
+ return fetchSanity(query, true);
1360
1388
  }
1361
1389
 
1362
1390
  /**
@@ -1378,26 +1406,26 @@ export async function fetchArtistLessons(brand, name, contentType, {
1378
1406
  * .catch(error => console.error(error));
1379
1407
  */
1380
1408
  export async function fetchGenreLessons(brand, name, contentType, {
1381
- sort = '-published_on',
1382
- searchTerm = '',
1383
- page = 1,
1384
- limit = 10,
1385
- includedFields = [],
1386
- progressIds = undefined,
1409
+ sort = '-published_on',
1410
+ searchTerm = '',
1411
+ page = 1,
1412
+ limit = 10,
1413
+ includedFields = [],
1414
+ progressIds = undefined,
1387
1415
  } = {}) {
1388
- const fieldsString = DEFAULT_FIELDS.join(',');
1389
- const start = (page - 1) * limit;
1390
- const end = start + limit;
1391
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"`: ''
1392
- const sortOrder = getSortOrder(sort);
1393
- const addType = contentType ? `_type == '${contentType}' &amp;&amp; `:''
1394
- const includedFieldsFilter = includedFields.length > 0
1395
- ? filtersToGroq(includedFields)
1396
- : "";
1397
- // limits the results to supplied progressIds for started &amp; completed filters
1398
- const progressFilter = progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
1399
-
1400
- const query = `{
1416
+ const fieldsString = DEFAULT_FIELDS.join(',');
1417
+ const start = (page - 1) * limit;
1418
+ const end = start + limit;
1419
+ const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1420
+ const sortOrder = getSortOrder(sort);
1421
+ const addType = contentType ? `_type == '${contentType}' &amp;&amp; ` : ''
1422
+ const includedFieldsFilter = includedFields.length > 0
1423
+ ? filtersToGroq(includedFields)
1424
+ : "";
1425
+ // limits the results to supplied progressIds for started &amp; completed filters
1426
+ const progressFilter = progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
1427
+
1428
+ const query = `{
1401
1429
  "entity":
1402
1430
  *[_type == 'genre' &amp;&amp; name == '${name}']
1403
1431
  {'type': _type, name, 'thumbnail_url':thumbnail_url.asset->url,
@@ -1406,7 +1434,7 @@ export async function fetchGenreLessons(brand, name, contentType, {
1406
1434
  [${start}...${end}]}
1407
1435
  |order(${sortOrder})
1408
1436
  }`;
1409
- return fetchSanity(query, true);
1437
+ return fetchSanity(query, true);
1410
1438
  }
1411
1439
 
1412
1440
  export async function fetchTopLevelParentId(railcontentId) {
@@ -1442,18 +1470,22 @@ export async function fetchHierarchy(railcontentId) {
1442
1470
  let topLevelId = await fetchTopLevelParentId(railcontentId);
1443
1471
  const query = `*[railcontent_id == ${topLevelId}]{
1444
1472
  railcontent_id,
1473
+ 'assignments': assignment[]{railcontent_id},
1445
1474
  'children': child[]->{
1446
1475
  railcontent_id,
1476
+ 'assignments': assignment[]{railcontent_id},
1447
1477
  'children': child[]->{
1448
1478
  railcontent_id,
1479
+ 'assignments': assignment[]{railcontent_id},
1449
1480
  'children': child[]->{
1450
1481
  railcontent_id,
1482
+ 'assignments': assignment[]{railcontent_id},
1451
1483
  'children': child[]->{
1452
- railcontent_id,
1484
+ railcontent_id,
1453
1485
  }
1454
1486
  }
1455
1487
  }
1456
- }
1488
+ },
1457
1489
  }`;
1458
1490
  let response = await fetchSanity(query, false, {processNeedAccess: false});
1459
1491
  if (!response) return null;
@@ -1465,9 +1497,11 @@ export async function fetchHierarchy(railcontentId) {
1465
1497
  return data;
1466
1498
  }
1467
1499
 
1500
+
1468
1501
  function populateHierarchyLookups(currentLevel, data, parentId) {
1469
1502
  let contentId = currentLevel['railcontent_id'];
1470
1503
  let children = currentLevel['children'];
1504
+
1471
1505
  data.parents[contentId] = parentId;
1472
1506
  if (children) {
1473
1507
  data.children[contentId] = children.map(child => child['railcontent_id']);
@@ -1477,8 +1511,64 @@ function populateHierarchyLookups(currentLevel, data, parentId) {
1477
1511
  } else {
1478
1512
  data.children[contentId] = [];
1479
1513
  }
1514
+
1515
+ let assignments = currentLevel['assignments'];
1516
+ if (assignments) {
1517
+ let assignmentIds = assignments.map(assignment => assignment['railcontent_id']);
1518
+ data.children[contentId] = (data.children[contentId] ?? []).concat(assignmentIds);
1519
+ assignmentIds.forEach(assignmentId => {
1520
+ data.parents[assignmentId] = contentId;
1521
+ });
1522
+ }
1523
+
1480
1524
  }
1481
1525
 
1526
+ /**
1527
+ * Fetch assignments for content
1528
+ *
1529
+ * @param {integer} contentId - List of ids get data for
1530
+ * @returns {Promise&lt;array|null>} - A promise that resolves to an array containing the data
1531
+ */
1532
+ export async function fetchAssignments(contentId) {
1533
+ const fields = `"id": railcontent_id,"assignments":assignment[]{"id": railcontent_id}`;
1534
+ const query = await buildQuery(`railcontent_id == ${contentId}`,
1535
+ {bypassPermissions: true},
1536
+ fields,
1537
+ {end: 100});
1538
+ let data = await fetchSanity(query, false);
1539
+ let mapped = [];
1540
+ data.assignments.forEach(function (content) {
1541
+ mapped.push(content.id);
1542
+ });
1543
+ return mapped;
1544
+ }
1545
+
1546
+ /**
1547
+ * Fetch data for comment mod page
1548
+ *
1549
+ * @param {array} ids - List of ids get data for
1550
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing the data
1551
+ */
1552
+ export async function fetchCommentModContentData(ids) {
1553
+ const idsString = ids.join(',');
1554
+ const fields = `"id": railcontent_id, "type": _type, title, "url": web_url_path, "parent": *[^._id in child[]._ref]{"id": railcontent_id, title}`;
1555
+ const query = await buildQuery(`railcontent_id in [${idsString}]`,
1556
+ {bypassPermissions: true},
1557
+ fields,
1558
+ {end: 50});
1559
+ let data = await fetchSanity(query, true);
1560
+ let mapped = {};
1561
+ data.forEach(function (content) {
1562
+ mapped[content.id] = {
1563
+ "id": content.id,
1564
+ "type": content.type,
1565
+ "title": content.title,
1566
+ "url": content.url,
1567
+ "parentTitle": content.parent[0]?.title ?? null
1568
+ };
1569
+ });
1570
+ return mapped;
1571
+ }
1482
1572
 
1483
1573
 
1484
1574
  /**
@@ -1498,83 +1588,89 @@ function populateHierarchyLookups(currentLevel, data, parentId) {
1498
1588
 
1499
1589
  export async function fetchSanity(query,
1500
1590
  isList,
1501
- { customPostProcess = null,
1502
- processNeedAccess = true,} = {}
1591
+ {
1592
+ customPostProcess = null,
1593
+ processNeedAccess = true,
1594
+ } = {}
1503
1595
  ) {
1504
- // Check the config object before proceeding
1505
- if (!checkSanityConfig(globalConfig)) {
1506
- return null;
1507
- }
1508
-
1509
- if (globalConfig.sanityConfig.debug) {
1510
- console.log("fetchSanity Query:", query);
1511
- }
1512
- const perspective = globalConfig.sanityConfig.perspective ?? 'published';
1513
- const encodedQuery = encodeURIComponent(query);
1514
- const api = globalConfig.sanityConfig.useCachedAPI ? 'apicdn' : 'api';
1515
- const url = `https://${globalConfig.sanityConfig.projectId}.${api}.sanity.io/v${globalConfig.sanityConfig.version}/data/query/${globalConfig.sanityConfig.dataset}?perspective=${perspective}&amp;query=${encodedQuery}`;
1516
- const headers = {
1517
- 'Authorization': `Bearer ${globalConfig.sanityConfig.token}`,
1518
- 'Content-Type': 'application/json'
1519
- };
1520
-
1521
- try {
1522
- const response = await fetch(url, {headers});
1523
- if (!response.ok) {
1524
- throw new Error(`Sanity API error: ${response.status} - ${response.statusText}`);
1525
- }
1526
- const result = await response.json();
1527
- if (result.result) {
1528
- if (globalConfig.sanityConfig.debug) {
1529
- console.log("fetchSanity Results:", result);
1530
- }
1531
- let results = isList ? result.result : result.result[0];
1532
- results = processNeedAccess ? await needsAccessDecorator(results) : results;
1533
- return customPostProcess ? customPostProcess(results) : results;
1534
- } else {
1535
- throw new Error('No results found');
1536
- }
1537
- } catch (error) {
1538
- console.error('fetchSanity: Fetch error:', error);
1539
- return null;
1540
- }
1596
+ // Check the config object before proceeding
1597
+ if (!checkSanityConfig(globalConfig)) {
1598
+ return null;
1599
+ }
1600
+
1601
+ if (globalConfig.sanityConfig.debug) {
1602
+ console.log("fetchSanity Query:", query);
1603
+ }
1604
+ const perspective = globalConfig.sanityConfig.perspective ?? 'published';
1605
+ const encodedQuery = encodeURIComponent(query);
1606
+ const api = globalConfig.sanityConfig.useCachedAPI ? 'apicdn' : 'api';
1607
+ const url = `https://${globalConfig.sanityConfig.projectId}.${api}.sanity.io/v${globalConfig.sanityConfig.version}/data/query/${globalConfig.sanityConfig.dataset}?perspective=${perspective}&amp;query=${encodedQuery}`;
1608
+ const headers = {
1609
+ 'Authorization': `Bearer ${globalConfig.sanityConfig.token}`,
1610
+ 'Content-Type': 'application/json'
1611
+ };
1612
+
1613
+ try {
1614
+ let promisesResult = await Promise.all([
1615
+ fetch(url, {headers}),
1616
+ processNeedAccess ? fetchUserPermissions() : null
1617
+ ]);
1618
+ const response = promisesResult[0];
1619
+ const userPermissions = promisesResult[1]?.permissions;
1620
+
1621
+ if (!response.ok) {
1622
+ throw new Error(`Sanity API error: ${response.status} - ${response.statusText}`);
1623
+ }
1624
+ const result = await response.json();
1625
+ if (result.result) {
1626
+ if (globalConfig.sanityConfig.debug) {
1627
+ console.log("fetchSanity Results:", result);
1628
+ }
1629
+ let results = isList ? result.result : result.result[0];
1630
+ results = processNeedAccess ? await needsAccessDecorator(results, userPermissions) : results;
1631
+ return customPostProcess ? customPostProcess(results) : results;
1632
+ } else {
1633
+ throw new Error('No results found');
1634
+ }
1635
+ } catch (error) {
1636
+ console.error('fetchSanity: Fetch error:', error);
1637
+ return null;
1638
+ }
1541
1639
  }
1542
1640
 
1543
- async function needsAccessDecorator(results) {
1544
- if (globalConfig.sanityConfig.useDummyRailContentMethods) return results;
1545
-
1546
- let userPermissions = await getUserPermissions();
1547
- userPermissions = new Set(userPermissions);
1548
-
1549
- if (Array.isArray(results)) {
1550
- results.forEach((result) => {
1551
- result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1552
- });
1553
- } else if (results.entity &amp;&amp; Array.isArray(results.entity)) {
1554
- // Group By
1555
- results.entity.forEach((result) => {
1556
- if (result.lessons) {
1557
- result.lessons.forEach((lesson) => {
1558
- lesson['need_access'] = doesUserNeedAccessToContent(lesson, userPermissions); // Updated to check lesson access
1559
- });
1560
- } else {
1561
- result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1562
- }
1563
- });
1564
- } else if (results.related_lessons &amp;&amp; Array.isArray(results.related_lessons)) {
1565
- results.related_lessons.forEach((result) => {
1566
- result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1567
- })
1568
- } else {
1569
- results['need_access'] = doesUserNeedAccessToContent(results, userPermissions);
1570
- }
1571
-
1572
- return results;
1641
+ function needsAccessDecorator(results, userPermissions) {
1642
+ if (globalConfig.sanityConfig.useDummyRailContentMethods) return results;
1643
+
1644
+ userPermissions = new Set(userPermissions);
1645
+
1646
+ if (Array.isArray(results)) {
1647
+ results.forEach((result) => {
1648
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1649
+ });
1650
+ } else if (results.entity &amp;&amp; Array.isArray(results.entity)) {
1651
+ // Group By
1652
+ results.entity.forEach((result) => {
1653
+ if (result.lessons) {
1654
+ result.lessons.forEach((lesson) => {
1655
+ lesson['need_access'] = doesUserNeedAccessToContent(lesson, userPermissions); // Updated to check lesson access
1656
+ });
1657
+ } else {
1658
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1659
+ }
1660
+ });
1661
+ } else if (results.related_lessons &amp;&amp; Array.isArray(results.related_lessons)) {
1662
+ results.related_lessons.forEach((result) => {
1663
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1664
+ })
1665
+ } else {
1666
+ results['need_access'] = doesUserNeedAccessToContent(results, userPermissions);
1667
+ }
1668
+
1669
+ return results;
1573
1670
  }
1574
1671
 
1575
- function doesUserNeedAccessToContent(result, userPermissions)
1576
- {
1577
- const permissions = new Set(result?.permission_id ?? []);
1672
+ function doesUserNeedAccessToContent(result, userPermissions) {
1673
+ const permissions = new Set(result?.permission_id ?? []);
1578
1674
  if (permissions.size === 0) {
1579
1675
  return false;
1580
1676
  }
@@ -1586,12 +1682,6 @@ function doesUserNeedAccessToContent(result, userPermissions)
1586
1682
  return true;
1587
1683
  }
1588
1684
 
1589
- async function getUserPermissions()
1590
- {
1591
- return await fetchUserPermissions();
1592
- }
1593
-
1594
-
1595
1685
  /**
1596
1686
  * Fetch CatalogueMetadata from Sanity. This information may be duplicated in the contentTypeConfig.js.
1597
1687
  * It's an ongoing discussion (Aug 2024), but it's been included here if necessary
@@ -1605,8 +1695,8 @@ async function getUserPermissions()
1605
1695
  * .then(data => console.log(data))
1606
1696
  * .catch(error => console.error(error));
1607
1697
  */
1608
- export async function fetchCatalogMetadata(contentType)
1609
- { const query = `*[_type == 'CatalogMetadata']{
1698
+ export async function fetchCatalogMetadata(contentType) {
1699
+ const query = `*[_type == 'CatalogMetadata']{
1610
1700
  catalog_type,
1611
1701
  brand,
1612
1702
  groq_results,
@@ -1615,7 +1705,7 @@ export async function fetchCatalogMetadata(contentType)
1615
1705
  modal_text,
1616
1706
  sort_by,
1617
1707
  }`
1618
- return fetchSanity(query, false, {processNeedAccess:false});
1708
+ return fetchSanity(query, false, {processNeedAccess: false});
1619
1709
  }
1620
1710
 
1621
1711
  /**
@@ -1663,43 +1753,43 @@ export async function fetchMetadata(brand, type) {
1663
1753
 
1664
1754
  //Helper Functions
1665
1755
  function arrayJoinWithQuotes(array, delimiter = ',') {
1666
- const wrapped = array.map(value => `'${value}'`);
1667
- return wrapped.join(delimiter)
1756
+ const wrapped = array.map(value => `'${value}'`);
1757
+ return wrapped.join(delimiter)
1668
1758
  }
1669
1759
 
1670
1760
  function getSanityDate(date) {
1671
- return date.toISOString();
1761
+ return date.toISOString();
1672
1762
  }
1673
1763
 
1674
1764
  const merge = (a, b, predicate = (a, b) => a === b) => {
1675
- const c = [...a]; // copy to avoid side effects
1676
- // add all items from B to copy C if they're not already present
1677
- b.forEach((bItem) => (c.some((cItem) => predicate(bItem, cItem)) ? null : c.push(bItem)))
1678
- return c;
1765
+ const c = [...a]; // copy to avoid side effects
1766
+ // add all items from B to copy C if they're not already present
1767
+ b.forEach((bItem) => (c.some((cItem) => predicate(bItem, cItem)) ? null : c.push(bItem)))
1768
+ return c;
1679
1769
  }
1680
1770
 
1681
1771
  function checkSanityConfig(config) {
1682
- if (!config.sanityConfig.token) {
1683
- console.warn('fetchSanity: The "token" property is missing in the config object.');
1684
- return false;
1685
- }
1686
- if (!config.sanityConfig.projectId) {
1687
- console.warn('fetchSanity: The "projectId" property is missing in the config object.');
1688
- return false;
1689
- }
1690
- if (!config.sanityConfig.dataset) {
1691
- console.warn('fetchSanity: The "dataset" property is missing in the config object.');
1692
- return false;
1693
- }
1694
- if (!config.sanityConfig.version) {
1695
- console.warn('fetchSanity: The "version" property is missing in the config object.');
1696
- return false;
1697
- }
1698
- return true;
1772
+ if (!config.sanityConfig.token) {
1773
+ console.warn('fetchSanity: The "token" property is missing in the config object.');
1774
+ return false;
1775
+ }
1776
+ if (!config.sanityConfig.projectId) {
1777
+ console.warn('fetchSanity: The "projectId" property is missing in the config object.');
1778
+ return false;
1779
+ }
1780
+ if (!config.sanityConfig.dataset) {
1781
+ console.warn('fetchSanity: The "dataset" property is missing in the config object.');
1782
+ return false;
1783
+ }
1784
+ if (!config.sanityConfig.version) {
1785
+ console.warn('fetchSanity: The "version" property is missing in the config object.');
1786
+ return false;
1787
+ }
1788
+ return true;
1699
1789
  }
1700
1790
 
1701
1791
 
1702
- function buildRawQuery(
1792
+ function buildRawQuery(
1703
1793
  filter = '',
1704
1794
  fields = '...',
1705
1795
  {
@@ -1718,7 +1808,7 @@ function buildRawQuery(
1718
1808
  }
1719
1809
 
1720
1810
 
1721
- function buildQuery(
1811
+ async function buildQuery(
1722
1812
  baseFilter = '',
1723
1813
  filterParams = {},
1724
1814
  fields = '...',
@@ -1729,11 +1819,11 @@ function buildQuery(
1729
1819
  isSingle = false,
1730
1820
  },
1731
1821
  ) {
1732
- const filter = new FilterBuilder(baseFilter, filterParams).buildFilter();
1822
+ const filter = await new FilterBuilder(baseFilter, filterParams).buildFilter();
1733
1823
  return buildRawQuery(filter, fields, {sortOrder, start, end, isSingle});
1734
1824
  }
1735
1825
 
1736
- function buildEntityAndTotalQuery(
1826
+ function buildEntityAndTotalQuery(
1737
1827
  filter = '',
1738
1828
  fields = '...',
1739
1829
  {
@@ -1756,9 +1846,9 @@ function buildEntityAndTotalQuery(
1756
1846
  }
1757
1847
 
1758
1848
 
1759
- function getFilterOptions(option, commonFilter,contentType, brand){
1849
+ function getFilterOptions(option, commonFilter, contentType, brand) {
1760
1850
  let filterGroq = '';
1761
- const types = Array.from(new Set([...coachLessonsTypes,...showsTypes[brand]]));
1851
+ const types = Array.from(new Set([...coachLessonsTypes, ...showsTypes[brand]]));
1762
1852
 
1763
1853
  switch (option) {
1764
1854
  case "difficulty":
@@ -1864,7 +1954,7 @@ function cleanUpGroq(query) {
1864
1954
  <br class="clear">
1865
1955
 
1866
1956
  <footer>
1867
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Fri Nov 08 2024 14:13:46 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1957
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Thu Nov 14 2024 23:44:16 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1868
1958
  </footer>
1869
1959
 
1870
1960
  <script>prettyPrint();</script>