diff --git a/.changeset/chilled-houses-study.md b/.changeset/chilled-houses-study.md new file mode 100644 index 0000000000..0fd37b8d5b --- /dev/null +++ b/.changeset/chilled-houses-study.md @@ -0,0 +1,8 @@ +--- +'@commercetools-docs/gatsby-theme-learning': minor +'@commercetools-docs/gatsby-theme-docs': minor +'@commercetools-website/docs-smoke-test': minor +'@commercetools-website/documentation': minor +--- + +Added status indicator for course and course topics diff --git a/packages/gatsby-theme-docs/gatsby-node.mjs b/packages/gatsby-theme-docs/gatsby-node.mjs index 54281fa6f1..0296194152 100644 --- a/packages/gatsby-theme-docs/gatsby-node.mjs +++ b/packages/gatsby-theme-docs/gatsby-node.mjs @@ -47,6 +47,40 @@ const debugMem = () => { } }; +/** + * Given navigation and content nodes, checks if all the content nodes + * belonging to a single self-learning chapter (course) have the same courseId. + */ +const validateSelfLearningContentStructure = ( + allNavigationNodes, + allContentNodes +) => { + // get only self learning content + const slugToCourseMap = new Map(); + allContentNodes + .filter((contentNode) => contentNode.courseId) + .forEach((contentNode) => + slugToCourseMap.set(contentNode.slug, contentNode.courseId) + ); + + allNavigationNodes.forEach((navigationNode) => { + let prevCourseId = undefined; + const chapterTitle = navigationNode.chapterTitle; + navigationNode.pages.forEach((page) => { + if (!slugToCourseMap.has(page.path)) { + return; // the path is not self-learning content + } + const courseId = slugToCourseMap.get(page.path); + if (prevCourseId !== undefined && prevCourseId !== courseId) { + const msg = `Mismatch self-learning courseId property (${courseId}) found in topic with slug ${page.path}. All topics within a single course should referece the same courseId, please check the frontmatter sections within the "${chapterTitle}" course`; + throw new Error(msg); + } else { + prevCourseId = courseId; + } + }); + }); +}; + // Ensure that certain directories exist. // https://www.gatsbyjs.org/tutorial/building-a-theme/#create-a-data-directory-using-the-onprebootstrap-lifecycle export const onPreBootstrap = async (gatsbyApi, themeOptions) => { @@ -218,6 +252,7 @@ export const createSchemaCustomization = ({ actions, schema }) => { }), }, courseId: { type: 'Int' }, + topicName: { type: 'String' }, }, interfaces: ['Node'], }), @@ -352,6 +387,9 @@ export const onCreateNode = async ( courseId: node.frontmatter.courseId ? Number(node.frontmatter.courseId) : null, + topicName: node.frontmatter.topicName + ? String(node.frontmatter.topicName) + : null, }; actions.createNode({ @@ -411,6 +449,7 @@ async function createContentPages( nodes { slug courseId + topicName } } allReleaseNotePage(sort: { date: DESC }) { @@ -441,13 +480,18 @@ async function createContentPages( if (navigationYamlResult.errors) { reporter.panicOnBuild('🚨 ERROR: Loading "allNavigationYaml" query'); } + // validate self-learning content structure + validateSelfLearningContentStructure( + navigationYamlResult.data.allNavigationYaml.nodes, + result.data.allContentPage.nodes + ); const pages = result.data.allContentPage.nodes; const navigationPages = navigationYamlResult.data.allNavigationYaml.nodes.reduce( (pageLinks, node) => [...pageLinks, ...(node.pages || [])], [] ); - pages.forEach(({ slug, courseId }) => { + pages.forEach(({ slug, courseId, topicName }) => { const matchingNavigationPage = navigationPages.find( (page) => trimTrailingSlash(page.path) === trimTrailingSlash(slug) ); @@ -489,9 +533,18 @@ async function createContentPages( let contentPageData = { ...pageData, component: require.resolve('./src/templates/page-content.js'), - } + }; if (courseId) { - contentPageData = {...contentPageData, context: {...contentPageData.context, courseId}} + contentPageData = { + ...contentPageData, + context: { ...contentPageData.context, courseId }, + }; + } + if (topicName) { + contentPageData = { + ...contentPageData, + context: { ...contentPageData.context, topicName }, + }; } actions.createPage(contentPageData); diff --git a/packages/gatsby-theme-docs/src/hooks/use-course-pages.js b/packages/gatsby-theme-docs/src/hooks/use-course-pages.js index 7302c6dd90..67726f70c6 100644 --- a/packages/gatsby-theme-docs/src/hooks/use-course-pages.js +++ b/packages/gatsby-theme-docs/src/hooks/use-course-pages.js @@ -8,6 +8,7 @@ export const useCoursePages = () => { nodes { slug courseId + topicName } } } @@ -25,17 +26,22 @@ var isIndexed = false; const courseMapToPages = (coursePagesData) => { if (!isIndexed) { coursePagesData.forEach((element) => { - coursePageMap.set(element.slug, { courseId: element.courseId }); + const { courseId, topicName } = element; + coursePageMap.set(element.slug, { courseId, topicName }); }); } isIndexed = true; }; /** - * Given a page slug, it returns the courseId where the page belongs + * Given an array of page slugs, it returns an array with course info * if exists, otherwise undefined */ -export const useCourseInfoByPageSlug = (pageSlug) => { +export const useCourseInfoByPageSlugs = (pageSlugs) => { courseMapToPages(useCoursePages()); - return coursePageMap.get(pageSlug); + const courseInfo = pageSlugs.reduce( + (prev, curr) => ({ ...prev, [curr]: coursePageMap.get(curr) }), + {} + ); + return courseInfo; }; diff --git a/packages/gatsby-theme-docs/src/layouts/content.js b/packages/gatsby-theme-docs/src/layouts/content.js index 8d8691a991..716010df77 100644 --- a/packages/gatsby-theme-docs/src/layouts/content.js +++ b/packages/gatsby-theme-docs/src/layouts/content.js @@ -22,7 +22,6 @@ import LayoutPageNavigation from './internals/layout-page-navigation'; import LayoutPageContent from './internals/layout-page-content'; import PageContentInset from './internals/page-content-inset'; import PageReadTime from './internals/page-read-time-estimation'; -import { PageCourseStatus } from '@commercetools-docs/gatsby-theme-learning'; const LayoutContent = (props) => { const { ref, inView, entry } = useInView(); @@ -82,9 +81,6 @@ const LayoutContent = (props) => { {props.pageData.showTimeToRead && ( )} - {props.pageContext.courseId && ( - - )} diff --git a/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js b/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js index ef5edc02a5..0b14edab1f 100644 --- a/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js +++ b/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js @@ -16,8 +16,11 @@ import SiteIcon from '../../overrides/site-icon'; import useScrollPosition from '../../hooks/use-scroll-position'; import { BetaFlag } from '../../components'; import LayoutHeaderLogo from './layout-header-logo'; -import { useCourseInfoByPageSlug } from '../../hooks/use-course-pages'; -import { PageCourseStatus } from '@commercetools-docs/gatsby-theme-learning'; +import { useCourseInfoByPageSlugs } from '../../hooks/use-course-pages'; +import { + SidebarCourseStatus, + SidebarTopicStatus, +} from '@commercetools-docs/gatsby-theme-learning'; const ReleaseNotesIcon = createStyledIcon(Icons.ReleaseNotesSvgIcon); @@ -91,6 +94,19 @@ const LinkItem = styled.div` display: flex; flex-direction: row; align-items: flex-end; + vertical-align: middle; +`; +const LinkItemWithIcon = styled.div` + padding: 0 0 0 ${designSystem.dimensions.spacings.m}; + display: flex; + flex-direction: row; + vertical-align: middle; + svg { + margin-right: 2px; + } + div { + line-height: ${designSystem.typography.lineHeights.cardSmallTitle}; + } `; const linkStyles = css` border-left: ${designSystem.dimensions.spacings.xs} solid @@ -121,6 +137,24 @@ const activeLinkStyles = css` color: ${designSystem.colors.light.linkNavigation} !important; `; +const StatusIconWrapper = styled.span` + display: flex; + vertical-align: middle; + padding-left: 10px; // change this setting to remove the indentation + svg { + margin-right: 5px; + } +`; + +const LinkSubtitleWithIcon = (props) => ( + + {props.children} + +); +LinkSubtitleWithIcon.propTypes = { + children: PropTypes.any, +}; + const SidebarLink = (props) => { const { locationPath, customStyles, customActiveStyles, ...forwardProps } = props; @@ -234,7 +268,10 @@ SidebarLinkWrapper.propTypes = { }; const SidebarChapter = (props) => { - const courseInfo = useCourseInfoByPageSlug(props.chapter.pages[0].path); + const courseInfo = useCourseInfoByPageSlugs( + props.chapter.pages.map((page) => page.path) + ); + const courseId = Object.values(courseInfo)[0]?.courseId; const elemId = `sidebar-chapter-${props.index}`; const getChapterDOMElement = React.useCallback( () => document.getElementById(elemId), @@ -244,26 +281,48 @@ const SidebarChapter = (props) => { return (
- - {props.chapter.chapterTitle} - {courseInfo?.courseId && ( - - )} - + {courseId ? ( + + + {props.chapter.chapterTitle} + + ) : ( + + {props.chapter.chapterTitle} + + )} + {props.chapter.pages && - props.chapter.pages.map((pageLink, pageIndex) => ( - - {pageLink.title} - - ))} + props.chapter.pages.map((pageLink, pageIndex) => { + const currTopicName = courseInfo[pageLink.path]?.topicName; + const TopicIcon = + courseId && currTopicName ? ( + + ) : null; + return ( + + {TopicIcon ? ( + + {TopicIcon} + {pageLink.title} + + ) : ( + {pageLink.title} + )} + + ); + })}
diff --git a/packages/gatsby-theme-learning/README.md b/packages/gatsby-theme-learning/README.md index a18079e8f7..82132ee294 100644 --- a/packages/gatsby-theme-learning/README.md +++ b/packages/gatsby-theme-learning/README.md @@ -11,8 +11,8 @@ Works against the learning-api. - `auth0Domain`: the auth0 application domain url (it is defined in the auth0 management app) - `learnApiBaseUrl`: the learn API base url. It can be omitted if the host running the site matches the api host. -- `features`: a list of feature flags (boolean values) to enable/disable specific functionalities - - `courseStatusIndicator`: feature flag to toggle the course status indicator. +- `features`: an array of strings representing feature flags used to enable/disable specific functionalities. Expected values: + - `status-indicator`: feature flag to toggle the course and topics status indicator. In order to enable the plugin, at least the following configuration should be added to the `gatsby-config.js` plugin section: diff --git a/packages/gatsby-theme-learning/gatsby-browser.js b/packages/gatsby-theme-learning/gatsby-browser.js index 01f0db3729..8b7af7f273 100644 --- a/packages/gatsby-theme-learning/gatsby-browser.js +++ b/packages/gatsby-theme-learning/gatsby-browser.js @@ -6,10 +6,7 @@ export const wrapRootElement = ({ element }, pluginOptions) => { value={{ learnApiBaseUrl: pluginOptions.learnApiBaseUrl, auth0Domain: pluginOptions.auth0Domain, - features: { - courseStatusIndicator: - pluginOptions?.features?.courseStatusIndicator || false, - }, + features: pluginOptions?.features || [], }} > {element} diff --git a/packages/gatsby-theme-learning/gatsby-node.mjs b/packages/gatsby-theme-learning/gatsby-node.mjs index 1b71514f6e..6e34a74f07 100644 --- a/packages/gatsby-theme-learning/gatsby-node.mjs +++ b/packages/gatsby-theme-learning/gatsby-node.mjs @@ -5,8 +5,6 @@ export const pluginOptionsSchema = ({ Joi }) => { .allow('') .default('') .description(`Learn API base url`), - features: Joi.object({ - courseStatusIndicator: Joi.boolean().default(false), - }) + features: Joi.array().items(Joi.string()), }); }; diff --git a/packages/gatsby-theme-learning/gatsby-ssr.js b/packages/gatsby-theme-learning/gatsby-ssr.js new file mode 100644 index 0000000000..8b7af7f273 --- /dev/null +++ b/packages/gatsby-theme-learning/gatsby-ssr.js @@ -0,0 +1,15 @@ +import ConfigContext from './src/components/config-context'; + +export const wrapRootElement = ({ element }, pluginOptions) => { + return ( + + {element} + + ); +}; diff --git a/packages/gatsby-theme-learning/index.ts b/packages/gatsby-theme-learning/index.ts index 0502671a6d..f66b89a48e 100644 --- a/packages/gatsby-theme-learning/index.ts +++ b/packages/gatsby-theme-learning/index.ts @@ -3,3 +3,4 @@ export { useFetchCourses, getCourseStatusByCourseId, } from './src/hooks/use-course-status'; +export { useFetchCourseDetails } from './src/hooks/use-course-details'; diff --git a/packages/gatsby-theme-learning/src/components/config-context.ts b/packages/gatsby-theme-learning/src/components/config-context.ts index 9b64feca65..b595eb6b16 100644 --- a/packages/gatsby-theme-learning/src/components/config-context.ts +++ b/packages/gatsby-theme-learning/src/components/config-context.ts @@ -1,19 +1,24 @@ import { createContext } from 'react'; +export enum EFeatureFlag { + CourseStatus = 'status-indicator', +} + export type Config = { learnApiBaseUrl: string; auth0Domain: string; - features: { - courseStatusIndicator: boolean; - }; + features: Array; }; const ConfigContext = createContext({ learnApiBaseUrl: '', auth0Domain: '', - features: { - courseStatusIndicator: false, - }, + features: [], }); +export const isFeatureEnabled = ( + feature: EFeatureFlag, + features: EFeatureFlag[] +) => features.includes(feature); + export default ConfigContext; diff --git a/packages/gatsby-theme-learning/src/components/page-course-status.tsx b/packages/gatsby-theme-learning/src/components/page-course-status.tsx deleted file mode 100644 index 137ca639f8..0000000000 --- a/packages/gatsby-theme-learning/src/components/page-course-status.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { useContext } from 'react'; -import { useAuth0 } from '@auth0/auth0-react'; -import { - getCourseStatusByCourseId, - useFetchCourses, -} from '../hooks/use-course-status'; -import ConfigContext from './config-context'; - -type CourseStatusProps = { - error?: string; - status?: string; -}; - -const CourseStatus = (props: CourseStatusProps) => { - if (props.error) { - return unavailable; - } - if (props.status) { - return {props.status}; - } - return null; -}; - -type PageCourseStatusProps = { - courseId: number; -}; - -const PageCourseStatus = (props: PageCourseStatusProps) => { - const { isAuthenticated } = useAuth0(); - const { data, isLoading, error } = useFetchCourses(); - const { - features: { courseStatusIndicator }, - } = useContext(ConfigContext); - - // courseStatusIndicator feature flag - if (!courseStatusIndicator) { - return null; - } - - const courseStatus = data?.result?.enrolledCourses - ? getCourseStatusByCourseId(data.result.enrolledCourses, props.courseId) - : undefined; - return ( - <> - {props.courseId && isAuthenticated && ( -
- Course status:{' '} - {isLoading ? ( - '...' - ) : ( - - )} -
- )} - - ); -}; - -export default PageCourseStatus; diff --git a/packages/gatsby-theme-learning/src/components/sidebar-course-status.tsx b/packages/gatsby-theme-learning/src/components/sidebar-course-status.tsx new file mode 100644 index 0000000000..0cf3d1b088 --- /dev/null +++ b/packages/gatsby-theme-learning/src/components/sidebar-course-status.tsx @@ -0,0 +1,54 @@ +import React, { useContext } from 'react'; +import { CircleIcon, VerifiedIcon } from '@commercetools-uikit/icons'; +import { + getCourseStatusByCourseId, + useFetchCourses, +} from '../hooks/use-course-status'; +import ConfigContext, { + isFeatureEnabled, + EFeatureFlag, +} from './config-context'; +import styled from '@emotion/styled'; +import { designSystem } from '@commercetools-docs/ui-kit'; + +const UnknownStateSpacer = styled.div` + width: ${designSystem.dimensions.spacings.l}; + margin-right: 5px; +`; + +type StatusIndicatorProps = { + status?: string; +}; + +export const StatusIndicator = (props: StatusIndicatorProps) => { + console.log(props.status); + switch (props.status) { + case 'completed': + return ; + case 'inProgress': + return ; + default: + return ; + } +}; + +type SidebarCourseStatusProps = { + courseId: number; +}; + +const SidebarCourseStatus = (props: SidebarCourseStatusProps) => { + const { data } = useFetchCourses(); + const { features } = useContext(ConfigContext); + + // CourseStatus feature flag + if (!isFeatureEnabled(EFeatureFlag.CourseStatus, features)) { + return null; + } + + const courseStatus = data?.result?.enrolledCourses + ? getCourseStatusByCourseId(data.result.enrolledCourses, props.courseId) + : undefined; + return <>{props.courseId && }; +}; + +export default SidebarCourseStatus; diff --git a/packages/gatsby-theme-learning/src/components/sidebar-topic-status.tsx b/packages/gatsby-theme-learning/src/components/sidebar-topic-status.tsx new file mode 100644 index 0000000000..af1ac2f161 --- /dev/null +++ b/packages/gatsby-theme-learning/src/components/sidebar-topic-status.tsx @@ -0,0 +1,55 @@ +import React, { useContext } from 'react'; +import { CheckActiveIcon, CircleIcon } from '@commercetools-uikit/icons'; +import { + useFetchCourseDetails, + getTopicStatusByPageTitle, +} from '../hooks/use-course-details'; +import ConfigContext, { + isFeatureEnabled, + EFeatureFlag, +} from './config-context'; +import { designSystem } from '@commercetools-docs/ui-kit'; +import styled from '@emotion/styled'; + +const UnknownStateSpacer = styled.div` + width: ${designSystem.dimensions.spacings.m}; + margin-right: 5px; +`; + +type StatusIndicatorProps = { + status?: string; +}; + +export const StatusIndicator = (props: StatusIndicatorProps) => { + switch (props.status) { + case 'completed': + return ; + case 'notCompleted': + return ; + default: + return ; + } +}; + +type PageTopicStatusProps = { + courseId: number; + pageTitle: string; +}; + +const SidebarTopicStatus = (props: PageTopicStatusProps) => { + const { data } = useFetchCourseDetails(props.courseId); + const { features } = useContext(ConfigContext); + + // CourseStatus feature flag + if (!isFeatureEnabled(EFeatureFlag.CourseStatus, features)) { + return null; + } + + const topicStatus = data?.result?.topics + ? getTopicStatusByPageTitle(data.result.topics, props.pageTitle) + : undefined; + + return props.courseId && ; +}; + +export default SidebarTopicStatus; diff --git a/packages/gatsby-theme-learning/src/hooks/use-course-details.ts b/packages/gatsby-theme-learning/src/hooks/use-course-details.ts new file mode 100644 index 0000000000..98b7c022ab --- /dev/null +++ b/packages/gatsby-theme-learning/src/hooks/use-course-details.ts @@ -0,0 +1,63 @@ +import useSWR from 'swr'; +import { useContext } from 'react'; +import ConfigContext, { + EFeatureFlag, + isFeatureEnabled, +} from '../components/config-context'; +import { useAuth0 } from '@auth0/auth0-react'; +import type { + ApiCallResult, + CourseWithDetails, + CourseTopic, +} from '../external-types'; +import { fetcherWithToken } from './hooks.utils'; +import { useAuthToken } from './use-auth-token'; + +type UseFetchCoursesIdResponse = { + data: ApiCallResult | undefined; + error: string; + isLoading: boolean; +}; + +export const useFetchCourseDetails = ( + courseId: number +): { + data: ApiCallResult | undefined; + error: string | undefined; + isLoading: boolean; +} => { + const { learnApiBaseUrl, features } = useContext(ConfigContext); + const { isAuthenticated } = useAuth0(); + const { getAuthToken } = useAuthToken(); + const apiEndpoint = `/api/courses/${courseId}`; + + // fetch data only if course status feature flag is true and the user is logged in + const shouldFetchData = + courseId && + isFeatureEnabled(EFeatureFlag.CourseStatus, features) && + isAuthenticated; + + const { data, error, isLoading } = useSWR( + shouldFetchData ? apiEndpoint : null, + (url) => fetcherWithToken(url, getAuthToken, learnApiBaseUrl) + ) as UseFetchCoursesIdResponse; + return { + data, + error, + isLoading, + }; +}; + +export const getTopicStatusByPageTitle = ( + topics: CourseTopic[], + pageTitle: string +) => { + const matchingTopic = topics.find( + (topic) => + topic.name.trim().toLowerCase() === pageTitle.trim().toLowerCase() + ); + if (matchingTopic) { + return matchingTopic.completed ? 'completed' : 'notCompleted'; + } + return 'notAvailable'; +}; diff --git a/packages/gatsby-theme-learning/src/hooks/use-course-status.ts b/packages/gatsby-theme-learning/src/hooks/use-course-status.ts index 541cb1c682..f88cd70df5 100644 --- a/packages/gatsby-theme-learning/src/hooks/use-course-status.ts +++ b/packages/gatsby-theme-learning/src/hooks/use-course-status.ts @@ -1,6 +1,9 @@ import useSWR from 'swr'; import { useContext } from 'react'; -import ConfigContext from '../components/config-context'; +import ConfigContext, { + EFeatureFlag, + isFeatureEnabled, +} from '../components/config-context'; import { useAuth0 } from '@auth0/auth0-react'; import type { ApiCallResult, @@ -28,16 +31,14 @@ export const useFetchCourses = (): { error: string | undefined; isLoading: boolean; } => { - const { - learnApiBaseUrl, - features: { courseStatusIndicator }, - } = useContext(ConfigContext); + const { learnApiBaseUrl, features } = useContext(ConfigContext); const { isAuthenticated } = useAuth0(); const { getAuthToken } = useAuthToken(); const apiEndpoint = `/api/courses`; // fetch data only if course status feature flag is true and the user is logged in - const shouldFetchData = courseStatusIndicator && isAuthenticated; + const shouldFetchData = + isFeatureEnabled(EFeatureFlag.CourseStatus, features) && isAuthenticated; const { data, error, isLoading } = useSWR( shouldFetchData ? apiEndpoint : null, diff --git a/packages/gatsby-theme-learning/src/hooks/use-submit-attempt.ts b/packages/gatsby-theme-learning/src/hooks/use-submit-attempt.ts index 55cb37805f..7f457e6b1f 100644 --- a/packages/gatsby-theme-learning/src/hooks/use-submit-attempt.ts +++ b/packages/gatsby-theme-learning/src/hooks/use-submit-attempt.ts @@ -27,7 +27,10 @@ export const useSubmitAttempt = (submitAttemptParams: SubmitAttemptParams) => { attemptData: SubmissionAttempt, finish: boolean ) => { - const invalidateCache = () => mutate('/api/courses'); + const invalidateCache = () => { + mutate('/api/courses'); + mutate(`/api/courses/${courseId}`); + }; const apiEndpoint = `${learnApiBaseUrl}/api/courses/${courseId}/quizzes/${quizId}/attempts/${attemptId}?finish=${finish}`; const accessToken = await getAuthToken(); const data = await fetch(apiEndpoint, { diff --git a/packages/gatsby-theme-learning/src/index.ts b/packages/gatsby-theme-learning/src/index.ts index 4883038dbf..0264263aac 100644 --- a/packages/gatsby-theme-learning/src/index.ts +++ b/packages/gatsby-theme-learning/src/index.ts @@ -1,4 +1,5 @@ export { default as Quiz } from './components/quiz'; export * from './components/quiz'; export * from './components/quiz.types'; -export { default as PageCourseStatus } from './components/page-course-status'; +export { default as SidebarCourseStatus } from './components/sidebar-course-status'; +export { default as SidebarTopicStatus } from './components/sidebar-topic-status'; diff --git a/websites/docs-smoke-test/gatsby-config.mjs b/websites/docs-smoke-test/gatsby-config.mjs index b57d754104..be93716363 100644 --- a/websites/docs-smoke-test/gatsby-config.mjs +++ b/websites/docs-smoke-test/gatsby-config.mjs @@ -32,6 +32,7 @@ const config = { options: { auth0Domain: 'auth.id.commercetools.com', learnApiBaseUrl: 'https://api.learn.commercetools.com', + features: ['status-indicator'] }, }, { diff --git a/websites/docs-smoke-test/src/content/self-learning/2-quiz.mdx b/websites/docs-smoke-test/src/content/self-learning/2-quiz.mdx index afdb3a80e6..be2ff9d01d 100644 --- a/websites/docs-smoke-test/src/content/self-learning/2-quiz.mdx +++ b/websites/docs-smoke-test/src/content/self-learning/2-quiz.mdx @@ -1,8 +1,9 @@ --- title: Quiz component -courseId: 55 +courseId: 66 +topicName: Quiz 2 --- # Test your knowledge - + diff --git a/websites/docs-smoke-test/src/content/self-learning/overview.mdx b/websites/docs-smoke-test/src/content/self-learning/overview.mdx index dfb7f632b6..86844ba5c8 100644 --- a/websites/docs-smoke-test/src/content/self-learning/overview.mdx +++ b/websites/docs-smoke-test/src/content/self-learning/overview.mdx @@ -1,6 +1,7 @@ --- title: Course overview -courseId: 55 +courseId: 66 +topicName: 'Overview' --- The purpose of this page is to provide an introduction to the quiz component. diff --git a/websites/docs-smoke-test/src/content/self-learning/quiz.mdx b/websites/docs-smoke-test/src/content/self-learning/quiz.mdx index 80ddc42501..a5c8f7d52a 100644 --- a/websites/docs-smoke-test/src/content/self-learning/quiz.mdx +++ b/websites/docs-smoke-test/src/content/self-learning/quiz.mdx @@ -1,8 +1,9 @@ --- title: Quiz component -courseId: 55 +courseId: 66 +topicName: 'Quiz 1' --- # Test your knowledge - + diff --git a/websites/documentation/src/content/writing/quizzes.mdx b/websites/documentation/src/content/writing/quizzes.mdx index 0c04cecf8b..cc4548b791 100644 --- a/websites/documentation/src/content/writing/quizzes.mdx +++ b/websites/documentation/src/content/writing/quizzes.mdx @@ -14,8 +14,8 @@ Works against commercetools' learning-api, which is not a part of this open sour - `auth0Domain`: the auth0 application domain url (it is defined in the auth0 management app) - `learnApiBaseUrl`: the learn API base url. It can be omitted if the host running the site matches the api host. -- `features`: a list of feature flags (boolean values) to toggle specific functionalities. - - `courseStatusIndicator`: feature flag to toggle the course status indicator. +- `features`: an array of strings representing feature flags used to toggle specific functionalities. Expected values: + - `status-indicator`: feature flag to toggle the course status indicator. In order to enable the plugin, the following configuration should be added to the `gatsby-config.js` plugin section: