@clickview/lite 0.57.3-rc.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/dist/bundles.json +1 -1
  2. package/dist/scripts/{2564-98ba0d782a-lite.chunk.js → 2564-04ffede8c7-lite.chunk.js} +3 -3
  3. package/dist/scripts/{2564-98ba0d782a-lite.chunk.js.map → 2564-04ffede8c7-lite.chunk.js.map} +1 -1
  4. package/dist/scripts/2615-27b126b1ab-lite.chunk.js +3 -0
  5. package/dist/scripts/2615-27b126b1ab-lite.chunk.js.map +1 -0
  6. package/dist/scripts/{2978-b7bcc3eac4-lite.chunk.js → 2978-e4a60f90a5-lite.chunk.js} +2 -2
  7. package/dist/scripts/2978-e4a60f90a5-lite.chunk.js.map +1 -0
  8. package/dist/scripts/{8095-afb976fac0-lite.chunk.js → 8095-7236697220-lite.chunk.js} +2 -2
  9. package/dist/scripts/8095-7236697220-lite.chunk.js.map +1 -0
  10. package/dist/scripts/8849-7d50f76777-lite.chunk.js +2 -0
  11. package/dist/scripts/8849-7d50f76777-lite.chunk.js.map +1 -0
  12. package/dist/scripts/{bundle-b25c09d3e8.min.js → bundle-176a4f3a0a.min.js} +3 -3
  13. package/dist/scripts/{bundle-b25c09d3e8.min.js.map → bundle-176a4f3a0a.min.js.map} +1 -1
  14. package/package.json +1 -1
  15. package/dist/scripts/2615-e9b2938c18-lite.chunk.js +0 -3
  16. package/dist/scripts/2615-e9b2938c18-lite.chunk.js.map +0 -1
  17. package/dist/scripts/2978-b7bcc3eac4-lite.chunk.js.map +0 -1
  18. package/dist/scripts/8095-afb976fac0-lite.chunk.js.map +0 -1
  19. package/dist/scripts/8849-020bfd8cdd-lite.chunk.js +0 -2
  20. package/dist/scripts/8849-020bfd8cdd-lite.chunk.js.map +0 -1
  21. /package/dist/scripts/{2564-98ba0d782a-lite.chunk.js.LICENSE.txt → 2564-04ffede8c7-lite.chunk.js.LICENSE.txt} +0 -0
  22. /package/dist/scripts/{2615-e9b2938c18-lite.chunk.js.LICENSE.txt → 2615-27b126b1ab-lite.chunk.js.LICENSE.txt} +0 -0
  23. /package/dist/scripts/{bundle-b25c09d3e8.min.js.LICENSE.txt → bundle-176a4f3a0a.min.js.LICENSE.txt} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"scripts/8849-020bfd8cdd-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/shared/src/apps/analytics/components/engagement-heat-map/engagement-heat-map.scss","file:///app/packages/libs/shared/src/apps/analytics/components/engagement-heat-map/EngagementHeatMap.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insight-card/insight-card.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insight-card/InsightCard.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insight-chart/InsightChart.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insight-chart/insight-chart.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insight-student-list/insight-student-list.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insight-student-list/InsightStudentList.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/devices/insight-devices.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insights/devices/InsightDevices.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/heatmap/insight-heatmap.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insights/heatmap/InsightHeatmap.tsx","file:///app/packages/libs/shared/src/apps/analytics/flight-requests/InteractiveResultsRequests.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseFetchInteractiveResults.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/EngagementUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/InteractiveUtils.ts","file:///app/packages/libs/shared/src/apps/share/components/recipient-item/user-recipient-item-metadata/UserRecipientItemMetadata.tsx","file:///app/packages/libs/shared/src/enums/InteractionCorrectness.ts","file:///app/packages/libs/shared/src/enums/InteractiveAnswerStatus.ts","file:///app/packages/libs/shared/src/flight-requests/VideoViewRequests.ts","file:///app/packages/libs/shared/src/utils/InteractiveCorrectnessHelper.ts","file:///app/packages/libs/shared/src/utils/InteractiveHelper.ts","file:///app/packages/libs/shared/src/apps/analytics/components/insights/average-attempts/insight-average-attempts.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insights/average-attempts/InsightAverageAttempts.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/average-score/insight-average-score.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insights/average-score/InsightAverageScore.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/completed-students/InsightCompletedStudents.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/easiest-question/InsightEasiestQuestion.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/hardest-question/InsightHardestQuestion.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/high-scoring-students/InsightHighScoringStudents.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/low-scoring-students/InsightLowScoringStudents.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/marking-required/InsightMarkingRequired.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/not-completed-students/InsightNotCompletedStudents.tsx","file:///app/packages/projects/lite/src/apps/insights/views/interactive/overview/InteractiveInsightsOverviewView.tsx","file:///app/packages/projects/lite/src/apps/insights/views/interactive/overview/InteractiveInsightsOverviewUtils.ts","file:///app/packages/libs/shared/src/apps/share/components/recipient-item/recipient-item.scss"],"sourcesContent":["// extracted by mini-css-extract-plugin\nexport default {\"heatMap\":\"epapa\",\"legend\":\"uhH4p\"};","import React from 'react';\nimport chroma from 'chroma-js';\n\nimport { getFullHeatMap } from 'libs/shared/apps/analytics/utils/EngagementUtils';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Engagement } from 'libs/shared/interfaces';\n\nimport styles from './engagement-heat-map.scss';\n\nconst namespace = 'shared.engagementHeatMap';\n\nconst ZERO_COLOUR = '#f1f1f1';\nconst MIN_COLOUR = '#daf07d';\nconst MAX_COLOUR = '#08bd1a';\n\nconst COLOUR_SCALE = chroma.scale([ MIN_COLOUR, MAX_COLOUR ]);\n\nconst LEGEND_VALUES = [ 0, 0.01, 0.25, 0.5, 0.75, 1 ];\n\nfunction getBackgroundColor(value: number, max: number): string {\n if (!value)\n return ZERO_COLOUR;\n\n return COLOUR_SCALE(value / max).hex();\n}\n\nfunction getGradient(data: number[], max: number): string {\n const gradient: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const previousValue = i > 0 && data[i - 1];\n const currentValue = data[i];\n const nextValue = i < data.length - 1 && data[i + 1];\n\n /**\n * We want to capture colour changes but if a value has the same value\n * of both of its neighbours, we can skip it.\n */\n if (currentValue === previousValue && currentValue === nextValue)\n continue;\n\n gradient.push(`${getBackgroundColor(currentValue, max)} ${100 / data.length * i}%`);\n }\n\n return `linear-gradient(to right, ${gradient.join(',')})`;\n}\n\nexport function EngagementHeatMapLegend(): JSX.Element {\n const max = Math.max(...LEGEND_VALUES);\n const legendSquareWidthPercentage = 100 / LEGEND_VALUES.length;\n\n return (\n <div className='d-flex justify-content-between w-100'>\n <Text namespace={namespace} phrase='less' />\n <div className={`d-flex mx-1 flex-grow-1 ${styles.legend}`}>\n {LEGEND_VALUES.map((val, idx) => (\n <div\n key={idx}\n style={{\n width: `${legendSquareWidthPercentage}%`,\n backgroundColor: getBackgroundColor(val, max)\n }}\n />\n ))}\n </div>\n <Text namespace={namespace} phrase='more' />\n </div>\n );\n}\n\ninterface EngagementHeatMapProps {\n engagement: Engagement;\n max?: number;\n className?: string;\n}\n\nexport function EngagementHeatMap(props: EngagementHeatMapProps): JSX.Element {\n const heatMap = getFullHeatMap(props.engagement);\n const max = props.max ?? Math.max(...heatMap);\n\n return (\n <div\n className={`border rounded ${styles.heatMap} ${props.className ?? ''}`}\n style={{\n background: getGradient(heatMap, max)\n }}\n />\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"icon\":\"sAmpy\",\"count\":\"faDs4\"};","import React from 'react';\n\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\n\nimport styles from './insight-card.scss';\n\ninterface InsightCardProps extends React.PropsWithChildren {\n svgName: string;\n svgClassName: string;\n title: string;\n subtitle?: string;\n count?: number;\n}\n\nexport function InsightCard(props: InsightCardProps) {\n return (\n <section className='d-flex flex-column border border-light rounded p-3 h-100'>\n <div className='d-flex align-items-center mb-2'>\n <div className={`${styles.icon} ${props.svgClassName} rounded-circle d-flex align-items-center justify-content-center`}>\n <SvgContainer svgName={props.svgName} />\n </div>\n <div className='d-flex flex-column ms-2'>\n <h2 className='h6 mb-0'>{props.title}</h2>\n {props.subtitle && <p className='text-secondary font-size-sm mb-0'>{props.subtitle}</p>}\n </div>\n {typeof props.count === 'number' && (\n <div className={`${styles.count} d-flex justify-content-center align-items-center bg-light rounded-circle ms-auto`}>\n {props.count}\n </div>\n )}\n </div>\n {props.children}\n </section>\n );\n}","import React from 'react';\nimport Highcharts from 'highcharts';\nimport HighchartsReact from 'highcharts-react-official';\n\nimport { ChartData } from 'libs/shared/apps/analytics/interfaces/ChartData';\n\nimport styles from './insight-chart.scss';\n\nconst getStaticChartOptions = (label: string): Highcharts.Options => {\n return {\n title: {\n text: null\n },\n credits: {\n enabled: false\n },\n yAxis: {\n title: {\n text: null\n },\n labels: {\n enabled: false\n },\n gridLineWidth: 0,\n min: 0,\n tickAmount: 1\n },\n xAxis: {\n title: {\n text: label,\n style: {\n color: '#313543',\n fontSize: '12px'\n }\n },\n labels: {\n style: {\n color: '#313543',\n fontSize: '12px'\n }\n },\n className: styles.font,\n lineWidth: 0\n },\n legend: {\n enabled: false\n },\n chart: {\n type: 'column',\n backgroundColor: 'transparent',\n height: '160px',\n spacingTop: 20\n },\n plotOptions: {\n column: {\n dataLabels: {\n enabled: false\n },\n enableMouseTracking: false,\n minPointLength: 8\n }\n }\n };\n};\n\ninterface InsightChartProps {\n label: string;\n chartData: ChartData;\n}\n\nexport function InsightChart(props: InsightChartProps) {\n function getChartOptions(): Highcharts.Options {\n const data = props.chartData;\n const staticChartOptions = getStaticChartOptions(props.label);\n\n return {\n ...staticChartOptions,\n xAxis: {\n ...staticChartOptions.xAxis,\n categories: data.categories\n },\n series: data.series\n };\n }\n\n return (\n <HighchartsReact\n highcharts={Highcharts}\n options={getChartOptions()}\n />\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"font\":\"nSTtI\"};","// extracted by mini-css-extract-plugin\nexport default {\"avatar\":\"uMuZt\",\"image\":\"WdKiU\"};","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { UserRecipientItemMetadata } from 'libs/shared/apps/share/components/recipient-item/user-recipient-item-metadata/UserRecipientItemMetadata';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { PercentageIndicator } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { User } from 'libs/shared/interfaces';\n\nimport styles from './insight-student-list.scss';\n\nconst MAX_ITEMS = 3;\n\ninterface UserPercentage extends User {\n percentage?: number;\n}\n\ninterface InsightStudentListProps {\n students: UserPercentage[];\n imageUrl: string;\n imageCdnUrl: string;\n appLink: Core.AppLink;\n description: string;\n appLinkText: string;\n percentages?: number[];\n anonymiseUsers: boolean;\n}\n\nexport function InsightStudentList(props: InsightStudentListProps) {\n return (\n <>\n {props.students.length ? (\n <ul className='list-unstyled mb-2'>\n {props.students.slice(0, MAX_ITEMS).map((student, index) => (\n <li key={index} className='d-flex align-items-center mb-2'>\n <UserRecipientItemMetadata\n user={student}\n imageCdnUrl={props.imageCdnUrl}\n avatarClassName={styles.avatar}\n detailsClassName='ms-2'\n showDisplayName\n showSubText={false}\n anonymiseUsers={props.anonymiseUsers}\n />\n\n <div className='d-flex align-items-center ms-auto'>\n <span className='me-1'>{student.percentage === undefined ? '- ' : Math.round(student.percentage * 100)}%</span>\n <PercentageIndicator percentage={student.percentage} />\n </div>\n </li>\n ))}\n </ul>\n ) : (\n <div className='text-center'>\n <img className={`${styles.image} mb-2`} src={props.imageUrl} />\n <p className='text-secondary mb-0' dangerouslySetInnerHTML={{ __html: props.description }} />\n </div>\n )}\n\n {!!props.students.length && (\n <AppLink appLink={props.appLink} className='text-info mt-auto'>\n {props.appLinkText}\n </AppLink>\n )}\n </>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"font\":\"xTiKg\",\"purpleChart\":\"OPcvi\",\"grayChart\":\"HlWj7\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightChart } from 'libs/shared/apps/analytics/components/insight-chart/InsightChart';\nimport { GroupedAnalyticsCount } from 'libs/shared/apps/analytics/interfaces/BaseAnalyticsEvent';\nimport { ChartData } from 'libs/shared/apps/analytics/interfaces/ChartData';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './insight-devices.scss';\n\nconst namespace = 'shared.insightDevices';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\n// Names from UserAgentHelper.getOperatingSystem()\nfunction getDeviceType(name: string) {\n switch (name) {\n case 'Android':\n case 'Windows Phone':\n case 'iOS':\n case 'BlackBerry':\n return 'Mobile';\n case 'Linux':\n case 'Unix':\n case 'Macintosh':\n case 'Windows':\n return 'Computer';\n }\n}\n\ninterface InsightDevicesProps {\n osCount: GroupedAnalyticsCount[]\n}\n\nexport function InsightDevices(props: InsightDevicesProps) {\n const categoriesData = getCategoriesData();\n const highestDeviceCount = getHighestDeviceCount();\n\n function getCategoriesData() {\n const defaultDevices: HashObject = { Phone: 0, Computer: 0 };\n\n if (!props.osCount?.length)\n return defaultDevices;\n\n return props.osCount.reduce((acc, group) => {\n if (!group.name) return acc;\n\n const deviceCategory = getDeviceType(group.name);\n\n acc[deviceCategory] = acc[deviceCategory] + group.count;\n\n return acc;\n }, defaultDevices);\n }\n\n function getHighestDeviceCount() {\n if (!props.osCount?.length) return null;\n\n return props.osCount.reduce((acc, group) => group.name && group.count > acc.count\n ? group\n : ArrayHelper.first(props.osCount));\n }\n\n function getChartData(): ChartData {\n return {\n categories: Object.keys(categoriesData),\n series: [{\n type: 'column',\n borderRadius: 4,\n dataLabels: {\n enabled: true,\n style: {\n fontSize: '12px',\n fontWeight: 'normal'\n },\n inside: false,\n overflow: 'allow',\n crop: false,\n className: styles.font\n },\n data: Object.keys(categoriesData).map(category => ({\n className: `${categoriesData[category] === 0 ? styles.grayChart : styles.purpleChart} ${categoriesData[category] !== highestDeviceCount?.count ? 'opacity-25' : ''}`,\n y: categoriesData[category]\n }))\n }]\n };\n }\n\n const chartData = getChartData();\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svgClassName='bg-light-ultramarine text-ultramarine'\n svgName={cvSvgLibrary.Monitor}\n >\n <p className='mb-0'>\n {props.osCount?.filter(group => group.name).length\n ? (\n <Text\n namespace={namespace}\n phrase='description'\n options={{ device: getDeviceType(highestDeviceCount?.name)?.toLowerCase() }}\n />\n ) : (\n <Text\n namespace={namespace}\n phrase='notViewed'\n />\n )}\n </p>\n\n <div className='position-relative mt-auto'>\n <InsightChart label={getPhrase('title')} chartData={chartData} />\n </div>\n </InsightCard>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"heatMap\":\"Rfr9N\",\"heatMapTimepointIndicator\":\"s6JbA\",\"heatMapTimepointIndicatorVisible\":\"mgjWX\"};","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EngagementHeatMap } from 'libs/shared/apps/analytics/components/engagement-heat-map/EngagementHeatMap';\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Engagement } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './insight-heatmap.scss';\n\nconst namespace = 'shared.insightHeatmap';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightHeatmapProps {\n engagement: Engagement;\n heatmapAppLink: Core.AppLink;\n}\n\nexport function InsightHeatmap(props: InsightHeatmapProps) {\n const engagementRate = props.engagement.engagementRate > 0 ? Math.round(props.engagement.engagementRate * 100) : null;\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Timer}\n svgClassName='bg-light-green text-green'\n >\n <div className='mb-2'>\n <p className='mb-0'>\n {engagementRate\n ? (\n <Text namespace={namespace} phrase='everyoneWatched' options={{ engagementRate }} />\n )\n : <Text namespace={namespace} phrase='notWatched' />\n }\n </p>\n {engagementRate &&\n <AppLink appLink={props.heatmapAppLink} className='text-info'>\n <Text namespace={namespace} phrase='viewHeatmap' />\n </AppLink>\n }\n </div>\n\n <div className='mb-2'>\n <EngagementHeatMap\n engagement={props.engagement}\n className={styles.heatMap}\n />\n </div>\n\n <p className='h3 text-center mb-2'>{engagementRate || '--'}%</p>\n <p className='text-center mb-0 font-size-sm'><Text namespace={namespace} phrase='amountWatched' /></p>\n </InsightCard>\n );\n}","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { Flight } from 'libs/common/react/index';\n\nimport { MarkInteractiveAnswer } from 'libs/shared/apps/analytics/interfaces/MarkInteractiveAnswer';\nimport { InteractiveResultsReport } from 'libs/shared/apps/analytics/interfaces/requests/InteractiveResultsReport';\nimport { InteractivesPendingReviewsRequest } from 'libs/shared/apps/analytics/interfaces/requests/InteractivesPendingReviewsRequest';\nimport { AnalyticsRequestFilter, CurrentUser, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\ninterface InteractiveResultFilters {\n currentUserId: string;\n currentCustomerId: string;\n dateRange?: { start: string, end: string }\n userIds?: string | string[];\n classroomsAndGroups?: string | string[];\n}\n\nfunction getInteractiveResultFilters(\n currentUser: CurrentUser,\n filter: AnalyticsRequestFilter\n): InteractiveResultFilters {\n return {\n currentUserId: currentUser.id,\n currentCustomerId: currentUser.customerId,\n dateRange: { start: filter.start, end: filter.end },\n userIds: filter.userId,\n classroomsAndGroups: filter.groupId\n };\n}\n\nexport const InteractiveResultsRequests = {\n /** \n * This endpoint returns data with a lot of duplicated ids,\n * e.g. student answers to the same question will have the same id.\n * Because of that, we don't normalize.\n */\n interactiveResultSet(\n interactiveId: string,\n interactiveMetadataId: string,\n currentUser: CurrentUser,\n filter: AnalyticsRequestFilter,\n success?: (data: InteractiveResultSet) => void,\n error?: (data: any) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/domain/v2/analytics/interactives/${interactiveId}/metadata/${interactiveMetadataId}`,\n key: getAnalyticsRequestKey(`interactive:result:set:${interactiveId}:${interactiveMetadataId}`, filter),\n data: getInteractiveResultFilters(currentUser, filter),\n type: HttpVerbs.POST,\n normalize: false,\n success,\n error,\n always\n };\n },\n \n /**\n * As the response from `interactiveResultSet` isn't normalised, we need to invalidate the cache\n * to update the results data.\n */\n mark(\n interactiveId: string,\n interactiveMetadataId: string,\n answerId: string,\n data: MarkInteractiveAnswer,\n success?: () => void,\n error?: (data: any) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/domain/v1/analytics/answers/${answerId}`,\n key: `mark:answer:${answerId}:${data.resultId}`,\n type: HttpVerbs.PUT,\n data,\n normalize: false,\n invalidationKeys: `interactive:result:set:${interactiveId}:${interactiveMetadataId}`,\n success,\n error,\n always\n };\n },\n\n pendingReviews(data: InteractivesPendingReviewsRequest): Flight.Request {\n return {\n url: `/api/domain/v1/analytics/interactives/pending-reviews/summary`,\n key: `interactives:pending:reviews`,\n type: HttpVerbs.POST,\n data\n };\n },\n\n interactiveResultsReport(data: InteractiveResultsReport): Flight.Request {\n return {\n url: '{gateway}/v2/analytics/interactives/report',\n key: 'interactive:results:report',\n data,\n type: HttpVerbs.POST,\n normalize: false\n };\n }\n};","import { Flight } from 'libs/common/flight';\n\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { AnalyticsRequestFilter, CurrentUser, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nexport function useFetchInteractiveResults(\n interactiveMetadataId: string,\n requestFilter: AnalyticsRequestFilter\n): Flight.Response<InteractiveResultSet> {\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(!!interactiveMetadataId &&\n InteractiveRequests.interactiveMetadata(interactiveMetadataId));\n\n const interactive = Flight.useBasicFetch<Interactive>(!!interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const shouldFetchResults = !!currentUser.data && !!interactive.data && (!!requestFilter);\n\n return Flight.useBasicFetch<InteractiveResultSet>(shouldFetchResults &&\n InteractiveResultsRequests.interactiveResultSet(\n interactiveMetadata.data.interactiveId,\n interactiveMetadata.data.id,\n currentUser.data,\n requestFilter\n ));\n}","import { Engagement } from 'libs/shared/interfaces';\n\n/**\n * The heat map in the API response won't contain trailing zeros so we need to add those\n * in manually.\n */\nexport function getFullHeatMap(engagement: Engagement): number[] {\n return (new Array(Math.ceil(engagement.videoDuration))).fill(null).map((t, idx) => engagement.heatMap[idx] || 0);\n}","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { ResultsSummary } from 'libs/shared/apps/analytics/interfaces/ResultsSummary';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { ScoreThresholdDefaults, ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, StudentAnswer, StudentResults } from 'libs/shared/interfaces';\nimport { Interactive, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { flattenInteractions, getInteractions, getStudentAttempt, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\n\ninterface StudentGroups {\n markingRequired: StudentResultsWithSummary[];\n lowScore: StudentResultsWithSummary[];\n highScore: StudentResultsWithSummary[];\n completed: StudentResultsWithSummary[];\n notCompleted: StudentResultsWithSummary[];\n}\n\nexport function groupStudents(\n interactive: Interactive,\n results: InteractiveResultSet,\n scoreThreshold?: ScoreThresholds\n): StudentGroups {\n const groups: StudentGroups = {\n markingRequired: [],\n lowScore: [],\n highScore: [],\n completed: [],\n notCompleted: []\n };\n\n const interactions = getInteractions(interactive);\n\n const numInteractions = interactions.length;\n \n results.students.forEach(s => {\n const withSummary = {\n ...s,\n summary: getStudentResultsSummary(interactive, s)\n };\n \n if (withSummary.summary.awaitingMarking) {\n groups.markingRequired.push(withSummary);\n return;\n }\n\n if (ArrayHelper.last(s.results).attempts.length === numInteractions) {\n groups.completed.push(withSummary);\n } else {\n groups.notCompleted.push(withSummary);\n return;\n }\n \n if (withSummary.summary.percentCorrect >= (scoreThreshold.HIGH || ScoreThresholdDefaults.HIGH))\n groups.highScore.push(withSummary);\n \n if (withSummary.summary.percentCorrect < (scoreThreshold.MODERATE || ScoreThresholdDefaults.MODERATE))\n groups.lowScore.push(withSummary);\n });\n \n const sortedLowScore = ArrayHelper.sortBy(groups.lowScore, s => s.summary.percentCorrect);\n const sortedHighScore = ArrayHelper.sortBy(groups.highScore, s => -s.summary.percentCorrect);\n \n return {\n ...groups,\n lowScore: sortedLowScore,\n highScore: sortedHighScore\n };\n}\n\nexport function getInteractionById(interactive: Interactive, interactionId: string): Interaction {\n const flattenedInteractions = flattenInteractions(interactive);\n return flattenedInteractions.find(i => i.id.toString() === interactionId.toString());\n}\n\n/**\n * We need to use the question and result ids as a list of one student's responses\n * to multiple questions will all have the same result id and a list of multiple\n * students responses to one question will all have the same questionId.\n */\nexport function getMarkedAnswerId(answer: StudentAnswer): string {\n return `${answer.questionId}:${answer.resultId}`;\n}\n\nexport function getMarkedStatus(\n interactionId: string,\n studentResults: StudentResults,\n markedAnswers: MarkedAnswerHash\n): InteractiveAnswerStatus {\n const result = getStudentResult(studentResults);\n const studentResponse = getStudentAttempt(interactionId, result);\n\n const isMarkedCorrect = studentResponse?.answers.every(a => {\n return markedAnswers[getMarkedAnswerId(a)]?.status === InteractiveAnswerStatus.Correct;\n });\n\n if (isMarkedCorrect)\n return InteractiveAnswerStatus.Correct;\n\n const isMarkedIncorrect = studentResponse?.answers.every(a => {\n return markedAnswers[getMarkedAnswerId(a)]?.status === InteractiveAnswerStatus.Incorrect;\n });\n\n if (isMarkedIncorrect)\n return InteractiveAnswerStatus.Incorrect;\n}\n\nexport function getInteractionResultsSummary(\n interaction: Interaction,\n results: InteractiveResultSet\n): ResultsSummary {\n const numStudents = results.students.length;\n let numCorrect = 0;\n let answered = 0;\n let unanswered = 0;\n let awaitingMarking = 0;\n let attempts = 0;\n\n results.students.forEach(s => {\n const result = getStudentResult(s);\n\n if (!result)\n return;\n\n attempts = attempts + s.results.length;\n\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(interaction, result);\n\n if (correctness === InteractionCorrectness.Correct)\n numCorrect++;\n\n if (correctness === InteractionCorrectness.UnAnswered)\n unanswered++;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n awaitingMarking++;\n\n if (correctness !== InteractionCorrectness.UnAnswered)\n answered++;\n });\n\n\n const percentCorrect = numStudents > 0\n ? numCorrect / numStudents\n : 0;\n\n return {\n percentCorrect,\n correct: numCorrect,\n answered,\n unanswered,\n awaitingMarking,\n attempts\n };\n}\n\nexport function getStudentResultsSummary(interactive: Interactive, studentResults: StudentResults): ResultsSummary {\n const result = getStudentResult(studentResults);\n\n const interactions = getInteractions(interactive);\n\n const numInteractions = interactions.length;\n\n let numCorrect = 0;\n let awaitingMarking = 0;\n\n interactions.forEach(i => {\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(i, result);\n\n if (correctness === InteractionCorrectness.Correct)\n numCorrect++;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n awaitingMarking++;\n });\n\n const percentCorrect = numInteractions > 0 ? numCorrect / numInteractions : 0;\n\n /**\n * Our interactions list has images and annotations filtered out.\n * We built a map of valid questions, so that we can calculate the unswered accurately.\n * We're doing this because of a bug that caused annotations and images to record answers in the player.\n * - Sha\n */\n const interactionIds = new Set(interactions.map(i => i.id));\n const answeredInteractions = result.attempts.filter(a => !!interactionIds.has(a?.answers[0]?.questionId)).length;\n\n return {\n answered: result.attempts.length,\n attempts: studentResults.results.length,\n unanswered: numInteractions - answeredInteractions,\n percentCorrect,\n correct: numCorrect,\n awaitingMarking\n };\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { Avatar } from 'libs/shared/components/avatar/Avatar';\nimport { UserGroup } from 'libs/shared/enums/UserGroup';\nimport { UserRole } from 'libs/shared/enums/UserRole';\nimport { BaseObject, User } from 'libs/shared/interfaces';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nimport styles from '../recipient-item.scss';\n\nconst namespace = 'shared.userRecipientItemMetadata';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getSubText(user: User): string {\n const userType = UserHelper.getUserType(user);\n const role = UserHelper.getUserRole(user);\n\n if (userType === UserGroup.Staff) {\n if (role === UserRole.Admin)\n return getPhrase('admin');\n\n return getPhrase('staff');\n }\n\n const yearGroup = UserHelper.getYearGroup(user);\n\n if (yearGroup?.name)\n return yearGroup.name;\n\n return getPhrase('student');\n}\n\nUserRecipientItemMetadata.defaults = {\n showSubText: true\n};\n\ninterface UserRecipientItemMetadataProps {\n user: User;\n imageCdnUrl: string;\n detailsClassName?: string;\n avatarClassName?: string;\n showDisplayName: boolean;\n showSubText?: boolean;\n anonymiseUsers?: boolean;\n getSubText?: (user: BaseObject) => string;\n}\n\nexport function UserRecipientItemMetadata(props: UserRecipientItemMetadataProps): JSX.Element {\n return (\n <>\n <div className={`${styles.avatarContainer} ${props.avatarClassName} d-inline-block`}>\n <Avatar\n imageUrl={props.user.avatar?.url}\n imageCdnUrl={props.imageCdnUrl}\n initials={UserHelper.getInitials(props.user.name, props.user.surname)}\n />\n </div>\n\n <div className={props.detailsClassName}>\n <h4 className='font-size-normal fw-normal m-0'>\n {props.anonymiseUsers\n ? anonymiseUserName(props.user, true)\n : props.showDisplayName\n ? UserHelper.getDisplayName(props.user)\n : UserHelper.getFullName(props.user)\n }\n </h4>\n {props.showSubText && <p className='text-secondary m-0'>{props.getSubText ? props.getSubText(props.user) : getSubText(props.user)}</p>}\n </div>\n </>\n );\n}","export enum InteractionCorrectness {\n Correct,\n Incorrect,\n AwaitingMarking,\n \n Answered,\n UnAnswered,\n NotApplicable\n}","export enum InteractiveAnswerStatus {\n Incorrect = 0,\n Correct = 1,\n PendingReview = 2\n}","import { Xhr } from 'libs/common/backbone/interfaces/Xhr';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { AnalyticsRequestFilter, Engagement, IndividualEngagementResponse } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\nexport const VideoViewRequests = {\n individualEngagement(\n objectId: string,\n filter: AnalyticsRequestFilter,\n sharerId?: string,\n success?: (data: IndividualEngagementResponse) => void,\n error?: (xhr: Xhr) => void,\n always?: () => void\n ): Flight.Request {\n const queryParams: HashObject = {\n objectId,\n ...filter\n };\n\n if (sharerId)\n queryParams.sharerId = sharerId;\n\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/heat-map', queryParams),\n key: getAnalyticsRequestKey(`engagement:${objectId}`, filter, sharerId),\n formatData: (data: any) => {\n return {\n ...data,\n data: data.data?.map((d: any) => ({\n ...d,\n heatMap: d.heatMap ?? []\n }))\n };\n },\n normalize: false,\n success,\n error,\n always\n };\n },\n \n aggregateEngagement(\n objectId: string,\n filter: AnalyticsRequestFilter,\n sharerId?: string,\n success?: (data: Engagement) => void,\n error?: (xhr: Xhr) => void,\n always?: () => void\n ): Flight.Request {\n const queryParams: HashObject = {\n objectId,\n ...filter\n };\n\n if (sharerId)\n queryParams.sharerId = sharerId;\n\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/heat-map/aggregations', queryParams),\n key: getAnalyticsRequestKey(`aggregate:engagement:${objectId}`, filter, sharerId),\n formatData: (data: Engagement) => {\n return {\n ...data,\n heatMap: data.heatMap ?? []\n };\n },\n normalize: false,\n success,\n error,\n always\n };\n },\n \n views(\n filter: AnalyticsRequestFilter,\n objectId?: string,\n sharerId?: string,\n success?: (data: VideoViewEventResponse) => void,\n error?: (xhr: Xhr) => void,\n always?: () => void\n ): Flight.Request {\n let baseKey = 'video:views';\n\n if (objectId)\n baseKey += `:${objectId}`;\n\n const queryParams: HashObject = {\n objectId,\n ...filter,\n timeOffset: DateHelper.getTimezoneOffset()\n };\n\n if (sharerId)\n queryParams.sharerId = sharerId;\n\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/video-views', queryParams),\n key: getAnalyticsRequestKey(baseKey, filter, sharerId),\n normalize: false,\n success,\n error,\n always\n };\n }\n};","import { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, InteractionTypeId, InteractiveResult, StudentAnswer } from 'libs/shared/interfaces';\n\ntype GetStudentAnswerByActionableItemId = (id: string) => string;\n\nfunction notApplicable(): InteractionCorrectness {\n return InteractionCorrectness.NotApplicable;\n}\n\nfunction awaitingMarking(): InteractionCorrectness {\n return InteractionCorrectness.AwaitingMarking;\n}\n\nfunction isMissingWordCorrect(\n interaction: Interaction,\n getStudentAnswer: GetStudentAnswerByActionableItemId\n): InteractionCorrectness {\n const items = interaction.actionableItems.filter(a => a\n .isCorrect);\n\n if (items.every(a => !getStudentAnswer(a.id)))\n return InteractionCorrectness.UnAnswered;\n\n const correct = items.every(a => a.name.trim().toLowerCase() === getStudentAnswer(a.id)?.trim().toLowerCase());\n return correct ? InteractionCorrectness.Correct : InteractionCorrectness.Incorrect;\n}\n\nfunction isMultipleChoiceCorrect(\n interaction: Interaction,\n getStudentAnswer: GetStudentAnswerByActionableItemId\n): InteractionCorrectness {\n if (interaction.actionableItems.every(a => !getStudentAnswer(a.id)))\n return InteractionCorrectness.UnAnswered;\n \n const correctItems = interaction.actionableItems.filter(a => a.isCorrect);\n\n const correct = correctItems.every(a => {\n const studentAnswer = getStudentAnswer(a.id);\n\n /**\n * In the past we've only ever checked the answer name. But since we introduced the ability to have image interactions\n * with no question text, we've need to swap to saving the id. But past submissions still have the name\n * - Sha\n */\n return studentAnswer?.toString() === a.id?.toString() || studentAnswer === a.name;\n });\n return correct ? InteractionCorrectness.Correct : InteractionCorrectness.Incorrect;\n}\n\nfunction isMarkableAnswerMarkedCorrect(\n interaction: Interaction,\n getStudentAnswer: (id: string) => StudentAnswer\n): InteractionCorrectness {\n let correctness: InteractionCorrectness;\n\n // There should only be one actionableItem\n interaction.actionableItems.forEach(item => {\n const studentAnswer = getStudentAnswer(item.id);\n\n if (!studentAnswer) {\n correctness = InteractionCorrectness.UnAnswered;\n return;\n }\n\n if (studentAnswer.status === InteractiveAnswerStatus.Correct) {\n correctness = InteractionCorrectness.Correct;\n return;\n }\n\n if (studentAnswer.status === InteractiveAnswerStatus.Incorrect) {\n correctness = InteractionCorrectness.Incorrect;\n return;\n }\n\n correctness = InteractionCorrectness.AwaitingMarking;\n });\n\n return correctness;\n}\n\ntype IsCorrectFunction = (interaction: Interaction, result: InteractiveResult) => InteractionCorrectness;\n\nfunction getGetStudentAnswer(interaction: Interaction, result: InteractiveResult): (id: string) => StudentAnswer {\n return (id: string) => {\n const attempt = result.attempts.find(a => a.id === interaction.id);\n return attempt?.answers.find(s => s.id === id);\n };\n}\n\nfunction wrapIsMissingWordCorrect(interaction: Interaction, result: InteractiveResult): InteractionCorrectness {\n const getStudentAnswer = getGetStudentAnswer(interaction, result);\n\n return isMissingWordCorrect(interaction, (id: string) => {\n const answer = getStudentAnswer(id);\n return answer?.text;\n });\n}\n\nfunction wrapIsMultipleChoiceCorrect(interaction: Interaction, result: InteractiveResult): InteractionCorrectness {\n const getStudentAnswer = getGetStudentAnswer(interaction, result);\n\n return isMultipleChoiceCorrect(interaction, (id: string) => {\n const answer = getStudentAnswer(id);\n return answer?.text;\n });\n}\n\nfunction wrapIsMarkableAnswerMarkedCorrect(\n interaction: Interaction,\n result: InteractiveResult\n): InteractionCorrectness {\n const getStudentAnswer = getGetStudentAnswer(interaction, result);\n return isMarkableAnswerMarkedCorrect(interaction, getStudentAnswer);\n}\n\nconst IsCorrectLookup: {[typeId: number]: IsCorrectFunction} = {\n [InteractionTypeId.Annotation]: notApplicable,\n [InteractionTypeId.Image]: notApplicable,\n [InteractionTypeId.MissingWord]: wrapIsMissingWordCorrect,\n [InteractionTypeId.MultipleChoice]: wrapIsMultipleChoiceCorrect,\n [InteractionTypeId.ShortAnswer]: wrapIsMarkableAnswerMarkedCorrect,\n [InteractionTypeId.TrueOrFalse]: wrapIsMultipleChoiceCorrect,\n [InteractionTypeId.Illustration]: wrapIsMarkableAnswerMarkedCorrect\n};\n\nfunction isInteractionCorrect(interaction: Interaction, result: InteractiveResult): InteractionCorrectness {\n const isCorrectFn = IsCorrectLookup[interaction.typeId];\n\n return isCorrectFn(interaction, result);\n}\n\nexport const InteractiveCorrectnessHelper = {\n notApplicable,\n awaitingMarking,\n isMissingWordCorrect,\n isMultipleChoiceCorrect,\n isInteractionCorrect\n};\n","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport {\n Interaction,\n InteractionTypeId,\n Interactive,\n InteractiveResult,\n StudentAttempt,\n StudentResults\n} from 'libs/shared/interfaces';\n\nfunction interactionRequiresAnswer(interaction: Interaction): boolean {\n return interaction.typeId !== InteractionTypeId.Annotation && interaction.typeId !== InteractionTypeId.Image;\n}\n\nexport function flattenInteractions(interactive: Interactive): Interaction[] {\n return ArrayHelper.flatten(interactive.timepoints.map(i => i.interactions));\n}\n\n/**\n * Centralised logic for using the most recent student result.\n */\nexport function getStudentResult(studentResults: StudentResults): InteractiveResult {\n return ArrayHelper.last(studentResults.results);\n}\n\nexport function getStudentAttempt(interactionId: string, result: InteractiveResult): StudentAttempt {\n return ArrayHelper.findWhere(result?.attempts, { id: interactionId });\n}\n\n/**\n * Returns a flat list of interactions on an interactive and filters out\n * those that don't require an answer (annotations and images).\n */\nexport function getInteractions(interactive: Interactive): Interaction [] {\n return flattenInteractions(interactive).filter(interactionRequiresAnswer);\n}","// extracted by mini-css-extract-plugin\nexport default {\"tealChart\":\"lZZf0\",\"grayChart\":\"wJQc4\",\"font\":\"o1Xbr\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightChart } from 'libs/shared/apps/analytics/components/insight-chart/InsightChart';\nimport { ChartData } from 'libs/shared/apps/analytics/interfaces/ChartData';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './insight-average-attempts.scss';\n\nconst namespace = 'shared.insightAverageAttempts';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightAverageAttemptsProps {\n students: StudentResultsWithSummary[];\n}\n\nexport function InsightAverageAttempts(props: InsightAverageAttemptsProps) {\n const averageAttempts = getAverageAttempts();\n const chartData = getChartData();\n\n function getCategoriesData() {\n const categoriesData = props.students.reduce((acc, student) => {\n const attemptsCategory = student.summary.attempts.toString();\n\n if (!(attemptsCategory in acc)) {\n Object.assign(acc, { [attemptsCategory]: 0 });\n }\n\n acc[attemptsCategory]++;\n\n return acc;\n }, {} as HashObject);\n return Object.keys(categoriesData).length ? categoriesData : { 0: 0 };\n }\n\n function getAverageAttempts() {\n return props.students.reduce((acc, student) => student.summary.attempts > acc ? student.summary.attempts : acc, 0);\n }\n\n function getChartData(): ChartData {\n const categoriesData = getCategoriesData();\n const noAttempts = categoriesData[0] === 0;\n\n return {\n categories: Object.keys(categoriesData),\n series: [{\n type: 'column',\n color: categoriesData[0] ? '#EAEAEA' : '#40C2BB',\n borderRadius: 4,\n dataLabels: {\n enabled: !noAttempts,\n style: {\n fontSize: '12px',\n fontWeight: 'normal'\n },\n inside: false,\n overflow: 'allow',\n crop: false,\n className: styles.font\n },\n data: Object.keys(categoriesData).map(category => ({\n className: `${noAttempts ? styles.grayChart : styles.tealChart} ${averageAttempts.toString() !== category ? 'opacity-25' : ''}`,\n y: categoriesData[category]\n }))\n }]\n };\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Refresh}\n svgClassName='bg-light-purple text-purple'\n >\n <p>\n {averageAttempts\n ? <Text namespace={namespace} phrase='averageAttempts' options={{ smartCount: averageAttempts }} />\n : <Text namespace={namespace} phrase='noAttempts'/>\n }\n </p>\n\n <div className='mt-auto'>\n <InsightChart label={getPhrase('attempts')} chartData={chartData} />\n </div>\n </InsightCard>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"redChart\":\"G7zOw\",\"yellowChart\":\"k34mm\",\"greenChart\":\"vBneA\",\"blueChart\":\"RPTWm\",\"grayChart\":\"k4JFZ\",\"borderDark\":\"LWor3\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightChart } from 'libs/shared/apps/analytics/components/insight-chart/InsightChart';\nimport { ChartData } from 'libs/shared/apps/analytics/interfaces/ChartData';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './insight-average-score.scss';\n\nconst namespace = 'shared.insightAverageScore';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\n\ninterface InsightAverageScoreProps {\n students: StudentResultsWithSummary[];\n}\n\nexport function InsightAverageScore(props: InsightAverageScoreProps) {\n function getChartData(): ChartData {\n const scoreCount = Array(11).fill(0);\n const scorePercentageData = props.students.reduce((acc, value) => {\n const scoreIndex = Math.floor(value.summary.percentCorrect * 10);\n acc[scoreIndex]++;\n\n return acc;\n }, scoreCount);\n\n const PERCENTAGES = [ '0', '10', '20', '30', '40', '50', '60', '70', '80', '90', '100' ];\n // TODO Outline \n // const averageScore = scorePercentageData.reduce((acc, value) => {\n // return value > acc ? value : acc;\n // }, 0);\n // ${averageScore === score ? styles.borderDark : ''}\n\n return {\n categories: PERCENTAGES,\n series: [{\n type: 'column',\n color: '#4E9ACE',\n borderRadius: 4,\n data: scorePercentageData.map((score, index) => {\n const percentageCategory = Number(PERCENTAGES[index]);\n\n const getChartColour = (percentage: number, score: number) => {\n if (score === 0)\n return styles.grayChart;\n if (percentage < 50)\n return styles.redChart;\n if (percentage < 70)\n return styles.yellowChart;\n if (percentage < 90)\n return styles.greenChart;\n\n return styles.blueChart;\n };\n\n return {\n className: `${getChartColour(percentageCategory, score)} rounded`,\n y: score\n };\n })\n }]\n };\n }\n\n function getAverageNumbers() {\n const averageScores = props.students.map(student => student.summary.percentCorrect);\n const averagePercentage = averageScores.reduce((a, b) => a + b, 0) / averageScores.length;\n const totalQuestions = ArrayHelper.last(\n ArrayHelper.last(props.students).results\n ).attempts.length;\n\n return {\n averageScore: Math.round(totalQuestions * averagePercentage),\n totalQuestions,\n averagePercentage: (averagePercentage * 100).toFixed(1)\n };\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Analytics}\n svgClassName='bg-light-orange text-orange'\n >\n <p>\n {props.students.length\n ? <Text namespace={namespace} phrase='averageScore' options={getAverageNumbers()} />\n : <Text namespace={namespace} phrase='noAnswers' />\n }\n </p>\n\n <InsightChart label={`${getPhrase('studentScores')} (%)`} chartData={getChartData()} />\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightStudentList } from 'libs/shared/apps/analytics/components/insight-student-list/InsightStudentList';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightCompletedStudents';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightCompletedStudentsProps {\n students: StudentResultsWithSummary[];\n imageCdnUrl: string;\n imageUrl: string;\n resultsAppLink: Core.AppLink;\n anonymiseUsers: boolean;\n}\n\nexport function InsightCompletedStudents(props: InsightCompletedStudentsProps) {\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Flag}\n svgClassName='bg-light-indigo text-indigo'\n count={props.students.length}\n >\n <InsightStudentList\n students={props.students.map(student => ({ ...student.user, percentage: student.summary.percentCorrect }))}\n imageCdnUrl={props.imageCdnUrl}\n imageUrl={props.imageUrl}\n description={getPhrase('completedStudents')}\n appLink={props.resultsAppLink}\n appLinkText={getPhrase('viewAll')}\n anonymiseUsers={props.anonymiseUsers}\n />\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InteractionWithResultsSummary } from 'libs/shared/apps/analytics/interfaces/InteractionWithResultsSummary';\nimport { getInteractionResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { getInteractions } from 'libs/shared/utils/InteractiveHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightEasiestQuestion';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightEasiestQuestionProps {\n interactive: Interactive;\n interactiveMetadata: InteractiveMetadata;\n results: InteractiveResultSet;\n questionsAppLink: Core.AppLink;\n}\n\nexport function InsightEasiestQuestion(props: InsightEasiestQuestionProps) {\n const easiestQuestion = React.useMemo(\n () => getEasiestQuestion(props.interactive, props.results),\n [props.results.students.length]\n );\n\n function getEasiestQuestion(interactive: Interactive, results: InteractiveResultSet): InteractionWithResultsSummary {\n const interactions: InteractionWithResultsSummary[] = getInteractions(interactive).map(i => ({\n ...i,\n resultsSummary: getInteractionResultsSummary(i, results)\n }));\n\n const answeredInteractions = interactions.filter(i =>\n !!i.resultsSummary.answered && !i.resultsSummary.awaitingMarking);\n\n const sortedInteractions = ArrayHelper.sortBy(\n answeredInteractions,\n i => i.resultsSummary.percentCorrect\n );\n\n return ArrayHelper.last(sortedInteractions);\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n subtitle={getPhrase('subtitle')}\n svgName={cvSvgLibrary.StarOutline}\n svgClassName='bg-light-blue text-blue'\n >\n <div className='d-flex align-items-center'>\n <PercentageIndicator\n percentage={easiestQuestion?.resultsSummary?.percentCorrect}\n layout={PercentageIndicatorLayout.LabelInside}\n />\n {easiestQuestion\n ? <div className='d-flex ms-2'>\n <InteractionLabel interaction={easiestQuestion} iconClassName='flex-shrink-0' />\n </div>\n : <span className='ms-2'>{getPhrase('noAnswers')}</span>\n }\n </div>\n\n {easiestQuestion && (\n <AppLink\n appLink={{\n ...props.questionsAppLink,\n params: {\n ...props.questionsAppLink.params as HashObject,\n sortBy: 'score_desc'\n }\n }}\n className='text-info'>\n <Text namespace={namespace} phrase='viewQuestions' />\n </AppLink>\n )}\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InteractionWithResultsSummary } from 'libs/shared/apps/analytics/interfaces/InteractionWithResultsSummary';\nimport { getInteractionResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { getInteractions } from 'libs/shared/utils/InteractiveHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightHardestQuestion';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightHardestQuestionProps {\n interactive: Interactive;\n interactiveMetadata: InteractiveMetadata;\n results: InteractiveResultSet;\n questionsAppLink: Core.AppLink;\n}\n\nexport function InsightHardestQuestion(props: InsightHardestQuestionProps) {\n const hardestQuestion = React.useMemo(\n () => getHardestQuestion(props.interactive, props.results),\n [props.results.students.length]\n );\n\n function getHardestQuestion(interactive: Interactive, results: InteractiveResultSet): InteractionWithResultsSummary {\n const interactions: InteractionWithResultsSummary[] = getInteractions(interactive).map(i => ({\n ...i,\n resultsSummary: getInteractionResultsSummary(i, results)\n }));\n\n const answeredInteractions = interactions.filter(i =>\n !!i.resultsSummary.answered && !i.resultsSummary.awaitingMarking);\n\n const sortedInteractions = ArrayHelper.sortBy(\n answeredInteractions,\n i => i.resultsSummary.percentCorrect\n );\n\n return ArrayHelper.first(sortedInteractions);\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n subtitle={getPhrase('subtitle')}\n svgName={cvSvgLibrary.QuestionMark}\n svgClassName='bg-light-orange text-orange'\n >\n <div className='d-flex align-items-center'>\n <PercentageIndicator\n percentage={hardestQuestion?.resultsSummary?.percentCorrect}\n layout={PercentageIndicatorLayout.LabelInside}\n />\n {hardestQuestion\n ? <div className='d-flex ms-2'>\n <InteractionLabel interaction={hardestQuestion} iconClassName='flex-shrink-0' />\n </div>\n : <span className='ms-2'>{getPhrase('noAnswers')}</span>\n }\n </div>\n\n {hardestQuestion && (\n <AppLink\n appLink={{\n ...props.questionsAppLink,\n params: {\n ...props.questionsAppLink.params as HashObject,\n sortBy: 'score_asc'\n }\n }}\n className='text-info'\n >\n <Text namespace={namespace} phrase='viewQuestions' />\n </AppLink>\n )}\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightStudentList } from 'libs/shared/apps/analytics/components/insight-student-list/InsightStudentList';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightHighScoringStudents';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightHighScoringStudentsProps {\n students: StudentResultsWithSummary[];\n imageCdnUrl: string;\n greenChartImageUrl: string;\n resultsAppLink: Core.AppLink;\n completed: StudentResultsWithSummary[];\n anonymiseUsers?: boolean;\n}\n\nexport function InsightHighScoringStudents(props: InsightHighScoringStudentsProps) {\n return (\n <InsightCard\n title={getPhrase('title')}\n subtitle={getPhrase('subtitle')}\n svgName={cvSvgLibrary.Trophy}\n svgClassName='bg-light-teal text-teal'\n count={props.students.length}\n >\n <InsightStudentList\n students={props.students.map(student => ({ ...student.user, percentage: student.summary.percentCorrect }))}\n imageCdnUrl={props.imageCdnUrl}\n imageUrl={props.greenChartImageUrl}\n description={getPhrase(props.completed.length ? 'noStudents' : 'highScore')}\n appLink={{\n ...props.resultsAppLink,\n params: {\n ...props.resultsAppLink.params as HashObject,\n sortBy: 'score_desc'\n }\n }}\n appLinkText={getPhrase('viewByHighest')}\n anonymiseUsers={props.anonymiseUsers}\n />\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightStudentList } from 'libs/shared/apps/analytics/components/insight-student-list/InsightStudentList';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightLowScoringStudents';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightLowScoringStudentsProps {\n students: StudentResultsWithSummary[];\n imageCdnUrl: string;\n redChartImageUrl: string;\n heartImageUrl: string;\n resultsAppLink: Core.AppLink;\n completed: StudentResultsWithSummary[];\n anonymiseUsers: boolean;\n}\n\nexport function InsightLowScoringStudents(props: InsightLowScoringStudentsProps) {\n return (\n <InsightCard\n title={getPhrase('title')}\n subtitle={getPhrase('subtitle')}\n svgName={cvSvgLibrary.Hand}\n svgClassName='bg-light-red text-red'\n count={props.students.length}\n >\n <InsightStudentList\n students={props.students.map(student => ({ ...student.user, percentage: student.summary.percentCorrect }))}\n imageCdnUrl={props.imageCdnUrl}\n imageUrl={props.completed.length ? props.heartImageUrl : props.redChartImageUrl}\n description={getPhrase(props.completed.length ? 'doingWell' : 'lowScore')}\n appLink={{\n ...props.resultsAppLink,\n params: {\n ...props.resultsAppLink.params as HashObject,\n sortBy: 'score_asc'\n }\n }}\n appLinkText={getPhrase('viewByLowest')}\n anonymiseUsers={props.anonymiseUsers}\n />\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightStudentList } from 'libs/shared/apps/analytics/components/insight-student-list/InsightStudentList';\nimport { User } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\n\nconst namespace = 'shared.insightMarkingRequired';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\n\ninterface InsightMarkingRequiredProps {\n students: User[];\n imageCdnUrl: string;\n imageUrl: string;\n resultsAppLink: Core.AppLink;\n anonymiseUsers: boolean;\n}\n\nexport function InsightMarkingRequired(props: InsightMarkingRequiredProps) {\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Hand}\n svgClassName='bg-light-blue text-blue'\n count={props.students.length}\n >\n <InsightStudentList\n students={props.students}\n imageCdnUrl={props.imageCdnUrl}\n imageUrl={props.imageUrl}\n description={getPhrase('studentsRequireMarking')}\n appLink={props.resultsAppLink}\n appLinkText={getPhrase('viewAll')}\n anonymiseUsers={props.anonymiseUsers}\n />\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { InsightStudentList } from 'libs/shared/apps/analytics/components/insight-student-list/InsightStudentList';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { User } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightNotCompletedStudents';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightNotCompletedStudentsProps {\n markingRequiredStudents: StudentResultsWithSummary[];\n completedStudents: StudentResultsWithSummary[];\n notCompletedStudents: StudentResultsWithSummary[];\n classroomStudents: User[];\n imageCdnUrl: string;\n imageUrl: string;\n resultsAppLink: Core.AppLink;\n anonymiseUsers: boolean;\n}\n\nexport function InsightNotCompletedStudents(props: InsightNotCompletedStudentsProps) {\n const notCompletedStudents = getNotCompletedStudents();\n\n function getNotCompletedStudents() {\n const markingRequiredStudentIds = props.markingRequiredStudents.map(student => student?.user.id);\n const completedStudentIds = props.completedStudents.map(student => student?.user.id);\n\n const notStartedStudents = props.classroomStudents.filter(student => {\n return !markingRequiredStudentIds.includes(student.id) &&\n !completedStudentIds.includes(student.id);\n });\n\n return ArrayHelper.uniq([\n ...props.notCompletedStudents.map(student => student.user),\n ...notStartedStudents\n ], 'id');\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Puzzle}\n svgClassName='bg-light-teal text-teal'\n count={notCompletedStudents.length}\n >\n <InsightStudentList\n students={notCompletedStudents}\n imageCdnUrl={props.imageCdnUrl}\n imageUrl={props.imageUrl}\n description={getPhrase('completed')}\n appLink={props.resultsAppLink}\n appLinkText={getPhrase('viewAll')}\n anonymiseUsers={props.anonymiseUsers}\n />\n </InsightCard>\n );\n}","import React from 'react';\n\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\nimport { Flight } from 'libs/common/react/index';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { InsightAverageAttempts } from 'libs/shared/apps/analytics/components/insights/average-attempts/InsightAverageAttempts';\nimport { InsightAverageScore } from 'libs/shared/apps/analytics/components/insights/average-score/InsightAverageScore';\nimport { InsightCompletedStudents } from 'libs/shared/apps/analytics/components/insights/completed-students/InsightCompletedStudents';\nimport { InsightDevices } from 'libs/shared/apps/analytics/components/insights/devices/InsightDevices';\nimport { InsightEasiestQuestion } from 'libs/shared/apps/analytics/components/insights/easiest-question/InsightEasiestQuestion';\nimport { InsightHardestQuestion } from 'libs/shared/apps/analytics/components/insights/hardest-question/InsightHardestQuestion';\nimport { InsightHeatmap } from 'libs/shared/apps/analytics/components/insights/heatmap/InsightHeatmap';\nimport { InsightHighScoringStudents } from 'libs/shared/apps/analytics/components/insights/high-scoring-students/InsightHighScoringStudents';\nimport { InsightLowScoringStudents } from 'libs/shared/apps/analytics/components/insights/low-scoring-students/InsightLowScoringStudents';\nimport { InsightMarkingRequired } from 'libs/shared/apps/analytics/components/insights/marking-required/InsightMarkingRequired';\nimport { InsightNotCompletedStudents } from 'libs/shared/apps/analytics/components/insights/not-completed-students/InsightNotCompletedStudents';\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { BaseAnalyticsEventResponse } from 'libs/shared/apps/analytics/interfaces/BaseAnalyticsEvent';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { AnalyticsFilterHelper } from 'libs/shared/apps/analytics/utils/AnalyticsFilterUtils';\nimport { getAudienceParams } from 'libs/shared/apps/analytics/utils/AudienceUtils';\nimport { getInsightsDateRangePresets, getStartEndParams } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { groupStudents } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { ScoreThresholdInsights } from 'libs/shared/constants/ScoreThresholds';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { VideoViewRequests } from 'libs/shared/flight-requests/VideoViewRequests';\nimport { BasePaginatedCollection, Classroom, Config, CurrentUser, Engagement, Interactive, InteractiveMetadata, User } from 'libs/shared/interfaces';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\n\nimport { ClassroomRequests } from 'apps/classrooms/flight-requests/ClassroomRequests';\nimport { getInsightsInteractiveTabs } from 'apps/insights/utils/InsightsAppLinkUtils';\nimport { InsightsHeaderView } from 'apps/insights/views/header/InsightsHeaderView';\nimport { getInteractiveInsightsAppLinks } from 'apps/insights/views/interactive/overview/InteractiveInsightsOverviewUtils';\n\nconst namespace = 'insights.interactiveInsightsOverview';\n\ninterface InteractiveInsightsViewProps {\n interactiveId: string;\n classroomId?: string;\n}\n\nexport function InteractiveInsightsOverviewView(props: InteractiveInsightsViewProps) {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const classroom = Flight.useBasicFetch<Classroom>(currentUser.data && props.classroomId &&\n ClassroomRequests.getClassroom(props.classroomId, currentUser.data.id));\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InteractiveRequests.interactiveMetadata(props.interactiveId)\n );\n\n const interactive = Flight.useBasicFetch<Interactive>(interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const audienceAppLinkParams = AnalyticsFilterHelper.getAudienceAppLinkParams();\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n const requestFilter = {\n ...getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams),\n ...getAudienceParams(audienceAppLinkParams)\n };\n\n const results = useFetchInteractiveResults(props.interactiveId, requestFilter);\n\n const classroomFilterOnly =\n audienceAppLinkParams.classrooms?.length === 1 && !audienceAppLinkParams.classroomGroups?.length;\n const classroomStudents = Flight.useBasicFetch<BasePaginatedCollection<User>>(classroomFilterOnly &&\n ClassroomRequests.getClassroomStudents(ArrayHelper.first(audienceAppLinkParams.classrooms)));\n\n const aggregateEngagement = Flight.useBasicFetch<Engagement>(\n VideoViewRequests.aggregateEngagement(\n props.interactiveId,\n requestFilter,\n currentUser.data.id\n )\n );\n\n const videoViews = Flight.useBasicFetch<BaseAnalyticsEventResponse>(currentUser.data &&\n VideoViewRequests.views(requestFilter, props.interactiveId, currentUser.data.id));\n\n const hasDataLoaded =\n currentUser.data &&\n config.data &&\n (!props.classroomId || classroom.data) &&\n interactiveMetadata.data &&\n interactive.data &&\n results.data &&\n (!classroomFilterOnly || classroomStudents.data) &&\n aggregateEngagement.data &&\n videoViews.data;\n\n const studentGroups = hasDataLoaded && groupStudents(interactive.data, results.data, ScoreThresholdInsights);\n\n function getUsers(studentResult: StudentResultsWithSummary[]): User[] {\n return studentResult.map(student => student.user);\n }\n\n if (!hasDataLoaded) return <></>;\n const params = {\n ...audienceAppLinkParams,\n ...dateRangeAppLinkParams\n };\n const interactiveInsightsAppLinks = getInteractiveInsightsAppLinks(\n props.interactiveId\n );\n\n return (\n <div className='px-3'>\n <InsightsHeaderView\n video={interactiveMetadata.data}\n audienceAppLinkParams={audienceAppLinkParams}\n dateRangeAppLinkParams={dateRangeAppLinkParams}\n tabs={getInsightsInteractiveTabs(interactiveMetadata.data.id, 'overview', params)}\n />\n\n <section className='mb-5'>\n <h2 className='h4'>\n <Text namespace={namespace} phrase='studentResponses' />\n <span>: {studentGroups.completed.length}{classroomStudents.data ? `/${classroomStudents.data.data.length}` : ''}</span>\n </h2>\n\n <div className='row g-3'>\n <div className='col-12 col-md'>\n <InsightMarkingRequired\n imageUrl={ImageUrls.Insights.SPEECH_BUBBLE_ASTERISK}\n resultsAppLink={interactiveInsightsAppLinks.resultsAppLink}\n imageCdnUrl={config.data.imageCdnUrl}\n students={getUsers(studentGroups.markingRequired)}\n anonymiseUsers={anonymiseUsers}\n />\n </div>\n\n {classroomFilterOnly && (\n <div className='col-12 col-md'>\n <InsightNotCompletedStudents\n markingRequiredStudents={studentGroups.markingRequired}\n completedStudents={studentGroups.completed}\n notCompletedStudents={studentGroups.notCompleted}\n classroomStudents={classroomStudents.data.data}\n imageCdnUrl={config.data.imageCdnUrl}\n imageUrl={ImageUrls.Insights.JIGSAW}\n resultsAppLink={interactiveInsightsAppLinks.resultsAppLink}\n anonymiseUsers={anonymiseUsers}\n />\n </div>\n )}\n\n <div className='col-12 col-md'>\n <InsightCompletedStudents\n students={studentGroups.completed}\n imageCdnUrl={config.data.imageCdnUrl}\n imageUrl={ImageUrls.Insights.AVATAR}\n resultsAppLink={interactiveInsightsAppLinks.resultsAppLink}\n anonymiseUsers={anonymiseUsers}\n />\n </div>\n </div>\n </section>\n\n <section className='mb-5'>\n <h2 className='h4'>\n <Text namespace={namespace} phrase='studentsPerformance' />\n </h2>\n\n <div className='row g-3'>\n <div className='col-12 col-md-6'>\n <InsightLowScoringStudents\n redChartImageUrl={ImageUrls.Insights.RED_CHART}\n heartImageUrl={ImageUrls.Insights.SPEECH_BUBBLE_HEART}\n resultsAppLink={interactiveInsightsAppLinks.resultsAppLink}\n imageCdnUrl={config.data.imageCdnUrl}\n students={studentGroups.lowScore}\n completed={studentGroups.completed}\n anonymiseUsers={anonymiseUsers}\n />\n </div>\n <div className='col-12 col-md-6'>\n <InsightHighScoringStudents\n greenChartImageUrl={ImageUrls.Insights.GREEN_CHART}\n resultsAppLink={interactiveInsightsAppLinks.resultsAppLink}\n imageCdnUrl={config.data.imageCdnUrl}\n students={studentGroups.highScore}\n completed={studentGroups.completed}\n anonymiseUsers={anonymiseUsers}\n />\n </div>\n <div className='col-12 col-md-6'>\n <InsightHardestQuestion\n interactive={interactive.data}\n interactiveMetadata={interactiveMetadata.data}\n results={results.data}\n questionsAppLink={interactiveInsightsAppLinks.questionsAppLink}\n />\n </div>\n <div className='col-12 col-md-6'>\n <InsightEasiestQuestion\n interactive={interactive.data}\n interactiveMetadata={interactiveMetadata.data}\n results={results.data}\n questionsAppLink={interactiveInsightsAppLinks.questionsAppLink}\n />\n </div>\n </div>\n </section>\n\n <section className='mb-5'>\n <h2 className='h4'>\n <Text namespace={namespace} phrase='classPerformance' />\n </h2>\n\n <div className='row g-3'>\n <div className='col-12 col-md-6'>\n <InsightAverageScore\n students={studentGroups.completed}\n />\n </div>\n <div className='col-12 col-md-6'>\n <InsightAverageAttempts\n students={studentGroups.completed}\n />\n </div>\n <div className='col-12 col-md-6'>\n <InsightDevices\n osCount={videoViews.data?.osCount}\n />\n </div>\n <div className='col-12 col-md-6'>\n <InsightHeatmap\n engagement={aggregateEngagement.data}\n heatmapAppLink={interactiveInsightsAppLinks.heatmapAppLink}\n />\n </div>\n </div>\n </section>\n </div>\n );\n}","import { HashObject } from 'libs/common/react/interfaces';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nexport function getInteractiveInsightsAppLinks(id: string, params?: HashObject) {\n return {\n resultsAppLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_RESULTS,\n args: [id],\n params\n },\n questionsAppLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_QUESTIONS,\n args: [id],\n params\n },\n heatmapAppLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_HEATMAP,\n args: [id],\n params\n }\n };\n}","// extracted by mini-css-extract-plugin\nexport default {\"removeRecipient\":\"mCbMC\",\"recipientItem\":\"kdcb0\",\"showSpinner\":\"xH6Mu\",\"avatarContainer\":\"Zcpg3\",\"recipientDetails\":\"v5EmV\",\"recipientDetailsWithRemoveButton\":\"_V928\"};"],"names":["namespace","ZERO_COLOUR","COLOUR_SCALE","LEGEND_VALUES","getBackgroundColor","value","max","hex","getGradient","data","gradient","i","length","previousValue","currentValue","nextValue","push","join","EngagementHeatMapLegend","Math","legendSquareWidthPercentage","className","Text","phrase","map","val","idx","key","style","width","backgroundColor","EngagementHeatMap","props","heatMap","engagement","background","InsightCard","svgClassName","SvgContainer","svgName","title","subtitle","count","children","getStaticChartOptions","label","text","credits","enabled","yAxis","labels","gridLineWidth","min","tickAmount","xAxis","color","fontSize","lineWidth","legend","chart","type","height","spacingTop","plotOptions","column","dataLabels","enableMouseTracking","minPointLength","InsightChart","highcharts","options","chartData","staticChartOptions","categories","series","MAX_ITEMS","InsightStudentList","students","slice","student","index","UserRecipientItemMetadata","user","imageCdnUrl","avatarClassName","detailsClassName","showDisplayName","showSubText","anonymiseUsers","undefined","percentage","round","PercentageIndicator","src","imageUrl","dangerouslySetInnerHTML","__html","description","AppLink","appLink","appLinkText","getPhrase","LanguageService","getDeviceType","name","InsightDevices","categoriesData","defaultDevices","Phone","Computer","osCount","reduce","acc","group","deviceCategory","getCategoriesData","highestDeviceCount","ArrayHelper","getHighestDeviceCount","Object","keys","borderRadius","fontWeight","inside","overflow","crop","category","y","filter","device","toLowerCase","InsightHeatmap","engagementRate","heatmapAppLink","getInteractiveResultFilters","currentUser","currentUserId","id","currentCustomerId","customerId","dateRange","start","end","userIds","userId","classroomsAndGroups","groupId","InteractiveResultsRequests","interactiveResultSet","interactiveId","interactiveMetadataId","success","error","always","url","normalize","mark","answerId","resultId","invalidationKeys","pendingReviews","interactiveResultsReport","useFetchInteractiveResults","requestFilter","interactiveMetadata","interactive","shouldFetchResults","I","getFullHeatMap","Array","ceil","videoDuration","fill","t","groupStudents","results","scoreThreshold","groups","markingRequired","lowScore","highScore","completed","notCompleted","numInteractions","forEach","s","withSummary","summary","getStudentResultsSummary","awaitingMarking","attempts","percentCorrect","HIGH","MODERATE","sortedLowScore","sortedHighScore","getInteractionById","interactionId","find","toString","getMarkedAnswerId","answer","questionId","getMarkedStatus","studentResults","markedAnswers","result","studentResponse","answers","every","a","status","getInteractionResultsSummary","interaction","numStudents","numCorrect","answered","unanswered","correctness","correct","interactions","interactionIds","Set","answeredInteractions","has","avatar","initials","surname","getSubText","userType","role","yearGroup","defaults","InteractionCorrectness","InteractiveAnswerStatus","VideoViewRequests","individualEngagement","objectId","sharerId","queryParams","formatData","d","aggregateEngagement","views","baseKey","timeOffset","notApplicable","isMissingWordCorrect","getStudentAnswer","items","actionableItems","isCorrect","trim","isMultipleChoiceCorrect","studentAnswer","getGetStudentAnswer","attempt","wrapIsMultipleChoiceCorrect","wrapIsMarkableAnswerMarkedCorrect","item","isMarkableAnswerMarkedCorrect","IsCorrectLookup","InteractiveCorrectnessHelper","isInteractionCorrect","isCorrectFn","typeId","interactionRequiresAnswer","flattenInteractions","timepoints","getStudentResult","getStudentAttempt","getInteractions","InsightAverageAttempts","noAttempts","averageAttempts","attemptsCategory","assign","smartCount","InsightAverageScore","averageScores","averagePercentage","b","totalQuestions","averageScore","toFixed","scoreCount","scorePercentageData","floor","PERCENTAGES","score","percentageCategory","Number","getChartColour","InsightCompletedStudents","resultsAppLink","InsightEasiestQuestion","easiestQuestion","resultsSummary","sortedInteractions","layout","InteractionLabel","iconClassName","questionsAppLink","params","sortBy","InsightHardestQuestion","hardestQuestion","InsightHighScoringStudents","greenChartImageUrl","InsightLowScoringStudents","heartImageUrl","redChartImageUrl","InsightMarkingRequired","InsightNotCompletedStudents","markingRequiredStudentIds","completedStudentIds","notStartedStudents","notCompletedStudents","markingRequiredStudents","completedStudents","classroomStudents","includes","InteractiveInsightsOverviewView","SharedViewModelKeys","UserRequests","config","ConfigRequests","classroom","classroomId","ClassroomRequests","InteractiveRequests","audienceAppLinkParams","dateRangeAppLinkParams","classroomFilterOnly","classrooms","classroomGroups","videoViews","hasDataLoaded","studentGroups","studentResult","interactiveInsightsAppLinks","application","action","args","getInteractiveInsightsAppLinks","InsightsHeaderView","video","tabs","ImageUrls"],"sourceRoot":""}