@clickview/lite 0.65.0-rc.0 → 0.65.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles.json +1 -1
- package/dist/scripts/1091-5a847b529f-lite.chunk.js +2 -0
- package/dist/scripts/1091-5a847b529f-lite.chunk.js.map +1 -0
- package/dist/scripts/6798-ccca72960a-lite.chunk.js +2 -0
- package/dist/scripts/6798-ccca72960a-lite.chunk.js.map +1 -0
- package/dist/scripts/{bundle-743ea1c2f4.min.js → bundle-7b9e0a0911.min.js} +3 -3
- package/dist/scripts/{bundle-743ea1c2f4.min.js.map → bundle-7b9e0a0911.min.js.map} +1 -1
- package/package.json +1 -1
- package/dist/scripts/1091-f0f2f244d6-lite.chunk.js +0 -2
- package/dist/scripts/1091-f0f2f244d6-lite.chunk.js.map +0 -1
- package/dist/scripts/6798-436333b77b-lite.chunk.js +0 -2
- package/dist/scripts/6798-436333b77b-lite.chunk.js.map +0 -1
- /package/dist/scripts/{bundle-743ea1c2f4.min.js.LICENSE.txt → bundle-7b9e0a0911.min.js.LICENSE.txt} +0 -0
package/dist/bundles.json
CHANGED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[1091],{41196:(e,t,n)=>{n.d(t,{W:()=>o});var r=n(20354),a=n(71553),i=n(20768),s=n(31949);function o(e,t,n){var o,u=r.a.useBasicFetch(s.N.currentUser()),l=r.a.useBasicFetch(!!e&&i.b.interactiveMetadata(e)),c=r.a.useBasicFetch(!!(null===(o=l.data)||void 0===o?void 0:o.interactiveId)&&i.b.interactive(l.data.interactiveId)),d=!!u.data&&!!c.data&&!!t;return r.a.useBasicFetch(d&&a.I.interactiveResultSet(l.data.interactiveId,l.data.id,u.data,t,n))}},26025:(e,t,n)=>{n.d(t,{B:()=>i});var r=n(1048),a=n(75795),i={getAudienceAppLinkParams:function(){var e=a.O.getCurrentRoute().appLink,t=r.t.isObject(e.params)?e.params:{},n=t.users,i=t.classrooms,s=t.classroomGroups,o=function(e){var n=t[e];if(n)return Array.isArray(n)?n:[n]},u={};return n&&(u.users=o("users")),i&&(u.classrooms=o("classrooms")),s&&(u.classroomGroups=o("classroomGroups")),u},getDateRangeAppLinkParams:function(){var e=a.O.getCurrentRoute().appLink,t=r.t.isObject(e.params)?e.params:{},n=t.from,i=t.to,s=t.rangeName,o={};return n&&(o.from=n),i&&(o.to=i),s&&(o.rangeName=s),o}}},26136:(e,t,n)=>{n.d(t,{B:()=>i});var r=n(76198),a=n(64818);function i(e,t){return e?t?(0,r._8)((n="profileId"in e?e.profileId:e.id,i=+"".concat(n).concat(Math.floor((new Date).getMinutes()/5)),{dictionaries:[r.O9,r.yd],separator:" ",length:2,style:"capital",seed:i})):"profileId"in e?e.name:a.l.getFullName(e):"";var n,i}},40003:(e,t,n)=>{n.d(t,{Hb:()=>m,NG:()=>p,W5:()=>d,eO:()=>v,nG:()=>l,wO:()=>b,zn:()=>u});var r=n(23481),a=n(110),i=n(57266),s=r.T.encloseNamespace("shared.analyticsUtils");function o(e){var t=a.O.convertDateToUTC(e);return a.O.format(t,"YYYY-MM-DDTHH:mm:ss")}function u(){return new Date(2021,0,1)}function l(){return new Date}function c(e){return e.find((function(e){return!!e.default}))}function d(e,t){if(t)return e.find((function(e){return e.name===t}))}function m(){var e=u(),t=(new Date).getFullYear(),n=t===e.getFullYear();return[{name:s("today"),startDate:new Date,endDate:new Date},{name:s("thisMonth"),startDate:new Date(t,(new Date).getMonth(),1),endDate:new Date},{name:s("lastThreeMonths"),startDate:new Date(t,(new Date).getMonth()-2,1),endDate:new Date},{name:s("lastSixMonths"),startDate:new Date(t,(new Date).getMonth()-5,1),endDate:new Date},{name:s("thisYear"),startDate:new Date(t,0,1),endDate:new Date},{name:s("lastYear"),startDate:new Date(t-1,0,1),endDate:new Date(t,0,0),disabled:n,tooltip:n?s("lastYearDisabled"):""},{name:s("allTime"),startDate:a.O.subtract(new Date,5,"years"),endDate:new Date,default:!0}]}function f(e){return a.O.format(e,"YYYY-MM-DD")}function v(e){return e.name?{rangeName:e.name}:{from:f(e.startDate),to:f(e.endDate)}}function p(e,t){var n=t.to,r=t.from,s=t.rangeName,o=d(e,s);if(o)return r||n?void i.e.updateParams(v(o),{replace:!0,merge:!0,keysToRemove:["from","to"]}):o;var m=c(e);if(r&&n&&a.O.isValid(r)&&a.O.isValid(n)){var f=!0,p=a.O.convertDateToUTC(new Date(r)),b=a.O.convertDateToUTC(new Date(n));a.O.isBefore(p,u(),"day")&&(p=u(),f=!1),a.O.isAfter(b,l(),"day")&&(b=l(),f=!1),a.O.isAfter(p,b)&&(p=m.startDate,b=m.endDate,f=!1);var g={startDate:p,endDate:b,name:f?s:""};if(f)return g;i.e.updateParams(v(g),{replace:!0,merge:!0,keysToRemove:["rangeName"]})}else i.e.updateParams(v(m),{replace:!0,merge:!0,keysToRemove:["rangeName"]})}function b(e,t){var n=function(e){return o(a.O.startOf(e,"day"))},r=function(e){return o(a.O.endOf(e,"day"))},i=d(e,t.rangeName);if(i)return{start:n(f(i.startDate)),end:r(f(i.endDate))};if(t.from&&t.to)return{start:n(t.from),end:r(t.to)};var s=c(e);return{start:n(f(s.startDate)),end:r(f(s.endDate))}}},43503:(e,t,n)=>{n.r(t),n.d(t,{InteractiveStudentResultsView:()=>D});var r=n(32735),a=n(23481),i=n(20354),s=n(2948),o=n(41196),u=n(9193),l=n(26025),c=n(26136),d=n(40003),m=n(21327),f=n(9111),v=n(38143),p=n(39151),b=n(20768),g=n(26304),w=n(91286),y=n(93322);function k(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var h=a.T.encloseNamespace("shared.interactiveStudentResults");function D(e){var t,n,a,D,A,S,E=(A=(0,s.D)(v.g.ANONYMISE_USERS),S=1,function(e){if(Array.isArray(e))return e}(A)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,s,o=[],u=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(o.push(r.value),o.length!==t);u=!0);}catch(e){l=!0,a=e}finally{try{if(!u&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(l)throw a}}return o}}(A,S)||function(e,t){if(e){if("string"==typeof e)return k(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?k(e,t):void 0}}(A,S)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0];(0,y.F)();var O=i.a.useBasicFetch(b.b.interactiveMetadata(e.interactiveId)),R=i.a.useBasicFetch((null===(t=O.data)||void 0===t?void 0:t.interactiveId)&&b.b.interactive(O.data.interactiveId)),C=l.B.getDateRangeAppLinkParams(),I=(0,o.W)(e.interactiveId,(0,d.wO)((0,d.Hb)(),C)),M=i.a.useBasicFetch(p.L.config());(0,w.v)([O,I]),(0,g.b)(O);var N=(0,u.D)(null===(n=R.data)||void 0===n?void 0:n.id,null===(a=O.data)||void 0===a?void 0:a.id,e.closePopup),T=N.markedAnswers,j=N.addMarkedAnswers,F=N.submitMarkedAnswers,U=null===(D=I.data)||void 0===D?void 0:D.students.find((function(t){var n,r,a,i,s,o;return e.userId?(null===(r=null===(n=t.user)||void 0===n?void 0:n.id)||void 0===r?void 0:r.toString())===(null===(a=e.userId)||void 0===a?void 0:a.toString()):!!e.profileId&&(null===(s=null===(i=t.publicUser)||void 0===i?void 0:i.profileId)||void 0===s?void 0:s.toString())===(null===(o=e.profileId)||void 0===o?void 0:o.toString())})),B=U?h("heading",{studentName:(0,c.B)(U.user||U.publicUser,E)}):"",Y=!!R.data&&!!I.data&&!!M.data;return r.createElement(f.G,{title:B,showLoadingSpinner:!Y,closePopup:e.closePopup,size:"lg"},Y&&r.createElement(m.R,{interactive:R.data,studentResults:U,markedAnswers:T,addMarkedAnswers:j,submitMarkedAnswers:F,imageCdnUrl:M.data.imageCdnUrl,selectedInteractionId:e.interactionId,onClickClose:e.closePopup,anonymiseUsers:E,reportsStyling:e.reportsStyling}))}},21327:(e,t,n)=>{n.d(t,{R:()=>D});var r=n(32735),a=n(9570),i=n(26136),s=n(39157),o=n(44113),u=n(86572),l=n(28972),c=n(83140),d=n(80845),m=n(23481),f=n(2102),v=n(36532),p=m.T.encloseNamespace("interactives.studentResponseList");function b(e){var t=Object.keys(e.markedAnswers).length;return r.createElement("div",{className:"d-flex justify-content-end pt-3"},r.createElement("div",null,!e.showSubmitButtonSpinner&&r.createElement("button",{className:"btn btn-link",onClick:e.onClickClose},p("close")),!!e.interactionsToMark.length&&r.createElement(r.Fragment,null,e.isDemo?r.createElement(v.u,{id:"submitAnswers",title:p("demoOnly"),spanHack:!0,spanHackClassName:"d-inline-flex"},r.createElement("button",{className:"btn btn-outline-dark pointer-events-none",disabled:!t},p("submitAnswers"))):r.createElement(f.m,{variant:"outline-dark",onClick:e.onClickSubmit,disabled:!t,showSpinner:e.showSubmitButtonSpinner},p("submitAnswers")))))}var g=m.T.encloseNamespace("interactives.studentResponseList");function w(e){var t=Object.keys(e.markedAnswers).length;return r.createElement("div",{className:"d-flex justify-content-between pb-3"},r.createElement("div",{className:"d-flex"},!!e.summary.unanswered&&r.createElement("div",{className:"bg-light rounded p-2 me-2"},r.createElement("strong",{className:"me-2"},g("unanswered")),e.summary.unanswered),r.createElement("div",{className:"bg-light rounded p-2 me-2"},r.createElement("strong",{className:"me-2"},g("score")),e.summary.awaitingMarking?r.createElement("em",null,g("pending")):"".concat(Math.round(100*e.summary.percentCorrect),"%"))),!!e.interactionsToMark.length&&r.createElement(r.Fragment,null,e.isDemo?r.createElement(v.u,{id:"submitAnswers",title:g("demoOnly"),spanHack:!0},r.createElement("button",{className:"btn btn-outline-dark pointer-events-none",disabled:!t},g("submitAnswers"))):r.createElement(f.m,{variant:"outline-dark",onClick:e.onClickSubmit,disabled:!t,showSpinner:e.showSubmitButtonSpinner},g("submitAnswers"))))}const y={awaitingMarking:"MvGb5"};function k(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,s,o=[],u=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(o.push(r.value),o.length!==t);u=!0);}catch(e){l=!0,a=e}finally{try{if(!u&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(l)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return h(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?h(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function D(e){var t,n,m,f,v=k(r.useState(!1),2),p=v[0],g=v[1],h=(t=r.useRef(),n=k(r.useState(!1),2),m=n[0],f=n[1],r.useEffect((function(){t.current&&!m&&(f(!0),requestAnimationFrame((function(){return t.current.scrollIntoView({behavior:"smooth",block:"center"})})))}),[t.current,m]),t),D=(0,s.Rt)(e.interactive,e.studentResults),A=(0,d.Q)(e.interactive),S=function(e,t){return e.filter((function(e){return c.A.isInteractionCorrect(e,(0,d.j_)(t))===l.w.AwaitingMarking}))}(A,e.studentResults);function E(){g(!0),e.submitMarkedAnswers()}return r.createElement(r.Fragment,null,r.createElement(w,{summary:D,interactionsToMark:S,markedAnswers:e.markedAnswers,onClickSubmit:E,showSubmitButtonSpinner:p,isDemo:e.isDemo}),r.createElement("ul",{className:"list-unstyled"},A.map((function(t,n){var l,c=t.id.toString()===(null===(l=e.selectedInteractionId)||void 0===l?void 0:l.toString()),d=S.some((function(e){return e.id===t.id})),m=(0,i.B)(e.studentResults.user||e.studentResults.publicUser,e.anonymiseUsers),f="p-2 mb-3 rounded";return c&&(f+=" border-2 border-info shadow"),f+=d?" ".concat(y.awaitingMarking):" border",r.createElement("li",{key:n,className:f,ref:c?h:null},r.createElement("div",{className:"d-flex mb-2"},r.createElement(u.y,{interaction:t,iconClassName:"flex-shrink-0"})),e.reportsStyling?r.createElement(o.O,{interaction:t,studentResults:e.studentResults,markedStatus:(0,s.HI)(t.id,e.studentResults,e.markedAnswers),markInteraction:e.addMarkedAnswers,imageCdnUrl:e.imageCdnUrl,anonymisedUserName:m,className:"bg-light ps-2",showFeedback:!0,reportsStyling:!0,responseComponentClass:"mx-n2"}):r.createElement(a.d,{interaction:t,studentResults:e.studentResults,markedStatus:(0,s.HI)(t.id,e.studentResults,e.markedAnswers),markInteraction:e.addMarkedAnswers,imageCdnUrl:e.imageCdnUrl,anonymisedUserName:m,showFeedback:!0}))}))),r.createElement(b,{interactionsToMark:S,markedAnswers:e.markedAnswers,onClickSubmit:E,onClickClose:e.onClickClose,showSubmitButtonSpinner:p,isDemo:e.isDemo}))}},94892:(e,t,n)=>{n.d(t,{T:()=>a,i:()=>r});var r={HIGH:.75,MODERATE:.5},a={HIGH:.7,MODERATE:.7}},94644:(e,t,n)=>{n.d(t,{r:()=>c});var r=n(50242),a=n(81886),i=n(67058),s=n(14553),o=n(49267),u=n(49075),l={notFound:i.d,forbidden:{rating:s.q,yearLevel:s.q,region:o.a,privacy:s.q},badRequest:u._,internalServerError:u._};function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(e){var i;i="number"==typeof e?e:e.status;var s=Object.assign(Object.assign({},l),t);i&&a.Q.Ry.isStatusCodeError(i)&&(i!==r.o.InternalServer?i!==r.o.NotFound?i!==r.o.Forbidden?n.badRequest||a.Q.Ry.throw(new s.badRequest):n.forbidden||a.Q.Ry.throw(new s.forbidden.privacy):n.notFound||a.Q.Ry.throw(new s.notFound):n.internalServerError||a.Q.Ry.throw(new u._))}}},91286:(e,t,n)=>{n.d(t,{v:()=>s});var r=n(32735),a=n(94644);function i(e){return e.map((function(e){return e.statusCode})).join(":")}function s(e,t,n){var s=Array.isArray(e)?e:[e];(0,r.useEffect)((function(){s.forEach((function(e){(0,a.r)(e.statusCode,t,n)}))}),[i(s),t,n])}},57266:(e,t,n)=>{n.d(t,{e:()=>s});var r=n(81886),a=n(1048),i=n(75795),s={updateParams:function(e,t){var n=i.O.getCurrentRoute().appLink,s="string"==typeof n.params?r.Q.Ab.DeserializeQueryParams(n.params):n.params;t.keysToRemove&&(s=a.t.omit(s,t.keysToRemove));var o=(null==t?void 0:t.merge)?Object.assign(Object.assign({},s),e):e,u=Object.assign(Object.assign({},n),{params:o});a.t.isEqual(n,u)||r.Q.C$.trigger(u,a.t.omit(t,["merge","keysToRemove"]))}}}}]);
|
|
2
|
+
//# sourceMappingURL=1091-5a847b529f-lite.chunk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts/1091-5a847b529f-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/shared/src/apps/analytics/hooks/UseFetchInteractiveResults.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnalyticsFilterUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/DateRangeUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/interactive-student-results/InteractiveStudentResultsView.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListFooter.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListHeader.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/student-response-list.scss","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseList.tsx","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/libs/shared/src/utils/AppRouteHelper.ts"],"sourcesContent":["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 includePublicResults?: boolean\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 includePublicResults\n ));\n}","import { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nexport const AnalyticsFilterHelper = {\n getAudienceAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { users, classrooms, classroomGroups } = params;\n\n const getParam = (key: keyof AudienceQueryParams) => {\n const param = params[key];\n\n if (!param)\n return;\n\n return Array.isArray(param) ? param : [param];\n };\n\n const audienceFilters: AudienceQueryParams = {};\n\n if (users)\n audienceFilters.users = getParam('users');\n\n if (classrooms)\n audienceFilters.classrooms = getParam('classrooms');\n\n if (classroomGroups)\n audienceFilters.classroomGroups = getParam('classroomGroups');\n\n return audienceFilters;\n },\n getDateRangeAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { from, to, rangeName } = params;\n\n const dateRangeFilters: DateRangeQueryParams = {};\n\n if (from)\n dateRangeFilters.from = from;\n\n if (to)\n dateRangeFilters.to = to;\n\n if (rangeName)\n dateRangeFilters.rangeName = rangeName;\n\n return dateRangeFilters;\n }\n};","import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { User } from 'libs/shared/interfaces';\nimport { PublicInteractiveUser } from 'libs/shared/interfaces/models/interactive-results/PublicInteractiveUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\n\nfunction getUniqueNamesConfig(id: string): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: User | PublicInteractiveUser, shouldAnonymise: boolean): string {\n if (!user)\n return '';\n\n if (!shouldAnonymise)\n return 'profileId' in user ? user.name : UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig('profileId' in user ? user.profileId : user.id));\n}\n","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function convertDateToUtcDateTimeString(date: Date): string {\n const utc = DateHelper.convertDateToUTC(date);\n return DateHelper.format(utc, 'YYYY-MM-DDTHH:mm:ss');\n}\n\nexport function getMinDate(): Date {\n return new Date(2021, 0, 1);\n}\n\nexport function getMaxDate(): Date {\n return new Date();\n}\n\nexport function getDefaultDateRange(dateRangePresets: DateRange[]): DateRange {\n return dateRangePresets.find(range => !!range.default);\n}\n\nexport function getPresetRangeByName(dateRangePresetss: DateRange[], rangeName: string): DateRange | undefined {\n if (!rangeName)\n return;\n\n const presets = dateRangePresetss;\n \n return presets.find(p => p.name === rangeName);\n}\n\nexport function getGenericDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastTwelveMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 11, 1),\n endDate: new Date(),\n default: true\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n }\n ];\n}\n\nexport function getInsightsDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n },\n {\n name: getPhrase('allTime'),\n startDate: DateHelper.subtract(new Date(), 5, 'years'),\n endDate: new Date(),\n default: true\n }\n ];\n}\n\nexport function formatDateQueryParam(date: Date): string {\n return DateHelper.format(date, 'YYYY-MM-DD');\n}\n\nexport function getRouteQueryParams(dateRange: DateRange): DateRangeQueryParams {\n if (dateRange.name)\n return { rangeName: dateRange.name };\n\n return {\n from: formatDateQueryParam(dateRange.startDate),\n to: formatDateQueryParam(dateRange.endDate)\n };\n}\n\nexport function useGetDateRangeFromQueryParams(\n dateRangePresets: DateRange[],\n dateRangeQueryParams: DateRangeQueryParams\n): DateRange | null {\n const { to, from, rangeName } = dateRangeQueryParams;\n \n const presetRange = getPresetRangeByName(dateRangePresets, rangeName);\n\n if (presetRange) {\n if (!from && !to)\n return presetRange;\n\n /**\n * If a rangeName has been set, we don't use to and from so we remove them from the url params.\n */\n AppRouteHelper.updateParams(\n getRouteQueryParams(presetRange),\n { replace: true, merge: true, keysToRemove: [ 'from', 'to' ]}\n );\n return;\n }\n\n const defaultDateRange = getDefaultDateRange(dateRangePresets);\n\n /**\n * If a param is missing, or one of them isn't a valid date, short-circuit the logic below.\n */\n if (!from || !to || !DateHelper.isValid(from) || !DateHelper.isValid(to)) {\n AppRouteHelper.updateParams(\n getRouteQueryParams(defaultDateRange),\n { replace: true, merge: true, keysToRemove: ['rangeName']}\n );\n return;\n }\n\n let initialDateRangeValid = true;\n\n let startDate = DateHelper.convertDateToUTC(new Date(from));\n let endDate = DateHelper.convertDateToUTC(new Date(to));\n\n if (DateHelper.isBefore(startDate, getMinDate(), 'day')) {\n startDate = getMinDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(endDate, getMaxDate(), 'day')) {\n endDate = getMaxDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(startDate, endDate)) {\n startDate = defaultDateRange.startDate;\n endDate = defaultDateRange.endDate;\n initialDateRangeValid = false;\n }\n\n const dateRange: DateRange = { startDate, endDate, name: initialDateRangeValid ? rangeName : '' };\n\n if (initialDateRangeValid)\n return dateRange;\n\n /**\n * If one or both of the date params were invalid, we trigger a route update.\n */\n AppRouteHelper.updateParams(getRouteQueryParams(dateRange), { replace: true, merge: true, keysToRemove: ['rangeName']});\n}\n\nexport function getStartEndParams(\n dateRangePresetss: DateRange[],\n filterParams: FilterQueryParams\n): { start: string; end: string } {\n const getStartDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.startOf(date, 'day'));\n const getEndDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.endOf(date, 'day'));\n\n const presetRange = getPresetRangeByName(dateRangePresetss, filterParams.rangeName);\n\n /**\n * If the user has chosen a preset range, lookup the start and end dates as they won't be\n * in the query params.\n */\n if (presetRange)\n return {\n start: getStartDate(formatDateQueryParam(presetRange.startDate)),\n end: getEndDate(formatDateQueryParam(presetRange.endDate))\n };\n\n /**\n * If they have chosen a custom date range, use their chosen start and end dates.\n */\n if (filterParams.from && filterParams.to)\n return {\n start: getStartDate(filterParams.from),\n end: getEndDate(filterParams.to)\n };\n\n /**\n * The below should never be hit\n */\n const defaultRange = getDefaultDateRange(dateRangePresetss);\n\n return {\n start: getStartDate(formatDateQueryParam(defaultRange.startDate)),\n end: getEndDate(formatDateQueryParam(defaultRange.endDate))\n };\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { useMarkAnswers } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { AnalyticsFilterHelper } from 'libs/shared/apps/analytics/utils/AnalyticsFilterUtils';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getInsightsDateRangePresets, getStartEndParams } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { StudentResponseList } from 'libs/shared/apps/student-response-list/StudentResponseList';\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { useCannotConsumeError } from 'libs/shared/hooks/useCannotConsumeError';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useLockContentWidth } from 'libs/shared/hooks/useLockContentWidth';\nimport { Config, Interactive, InteractiveMetadata } from 'libs/shared/interfaces';\nimport { PopupViewProps } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.interactiveStudentResults';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InteractiveStudentResultsViewProps extends PopupViewProps {\n userId: string;\n interactiveId: string;\n interactionId?: string;\n reportsStyling?: boolean;\n profileId?: string;\n}\n\nexport function InteractiveStudentResultsView(props: InteractiveStudentResultsViewProps): JSX.Element {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n useLockContentWidth();\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InteractiveRequests.interactiveMetadata(props.interactiveId)\n );\n const interactive = Flight.useBasicFetch<Interactive>(interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n\n const results = useFetchInteractiveResults(\n props.interactiveId,\n getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams)\n );\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n useHandleObjectError([ interactiveMetadata, results ]);\n useCannotConsumeError(interactiveMetadata);\n\n const { markedAnswers, addMarkedAnswers, submitMarkedAnswers } = useMarkAnswers(\n interactive.data?.id,\n interactiveMetadata.data?.id,\n props.closePopup\n );\n\n const studentResults = results.data?.students.find(s => {\n if (props.userId)\n return s.user?.id?.toString() === props.userId?.toString();\n\n if (props.profileId)\n return s.publicUser?.profileId?.toString() === props.profileId?.toString();\n\n return false;\n });\n\n const popupTitle = studentResults\n ? getPhrase('heading', { studentName: anonymiseUserName(studentResults.user || studentResults.publicUser, anonymiseUsers) })\n : '';\n const dataLoaded = !!interactive.data && !!results.data && !!config.data;\n\n return (\n <Popup\n title={popupTitle}\n showLoadingSpinner={!dataLoaded}\n closePopup={props.closePopup}\n size='lg'\n >\n {dataLoaded &&\n <StudentResponseList\n interactive={interactive.data}\n studentResults={studentResults}\n markedAnswers={markedAnswers}\n addMarkedAnswers={addMarkedAnswers}\n submitMarkedAnswers={submitMarkedAnswers}\n imageCdnUrl={config.data.imageCdnUrl}\n selectedInteractionId={props.interactionId}\n onClickClose={props.closePopup}\n anonymiseUsers={anonymiseUsers}\n reportsStyling={props.reportsStyling}\n />\n }\n </Popup>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListFooterProps {\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n onClickClose: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListFooter(props: StudentResponseListFooterProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-end pt-3'>\n <div>\n {!props.showSubmitButtonSpinner &&\n <button className='btn btn-link' onClick={props.onClickClose}>\n {getPhrase('close')}\n </button>\n }\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip\n id='submitAnswers'\n title={getPhrase('demoOnly')}\n spanHack\n spanHackClassName='d-inline-flex'\n >\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n </div>\n );\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { ResultsSummary } from 'libs/shared/apps/analytics/interfaces/ResultsSummary';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListHeaderProps {\n summary: ResultsSummary;\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListHeader(props: StudentResponseListHeaderProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-between pb-3'>\n <div className='d-flex'>\n {!!props.summary.unanswered &&\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('unanswered')}</strong>\n {props.summary.unanswered}\n </div>\n }\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('score')}</strong>\n {props.summary.awaitingMarking\n ? <em>{getPhrase('pending')}</em>\n : `${Math.round(props.summary.percentCorrect * 100)}%`\n }\n </div>\n </div>\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip id='submitAnswers' title={getPhrase('demoOnly')} spanHack>\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"awaitingMarking\":\"MvGb5\"};","import React from 'react';\n\nimport { InteractionResponseItem } from 'libs/shared/apps/analytics/components/questions-list/interaction-response-item/InteractionResponseItem';\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getMarkedStatus, getStudentResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { InteractionResponse } from 'libs/shared/components/interaction-response/InteractionResponse';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, Interactive, StudentAnswer, StudentResults } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getInteractions, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\n\nimport { StudentResponseListFooter } from './StudentResponseListFooter';\nimport { StudentResponseListHeader } from './StudentResponseListHeader';\n\nimport styles from './student-response-list.scss';\n\nfunction getInteractionsToMark(\n interactions: Interaction[],\n studentResults: StudentResults\n): Interaction[] {\n return interactions.filter(i => {\n return InteractiveCorrectnessHelper.isInteractionCorrect(\n i,\n getStudentResult(studentResults)\n ) === InteractionCorrectness.AwaitingMarking;\n });\n}\n\n// eslint-disable-next-line rulesdir/require-view-title\nfunction useScrollSelectedInteractionIntoView(): React.MutableRefObject<HTMLLIElement> {\n const ref = React.useRef<HTMLLIElement>();\n const [ scrolled, setScrolled ] = React.useState(false);\n\n // Only scroll once\n React.useEffect(() => {\n if (!ref.current || scrolled)\n return;\n\n setScrolled(true);\n requestAnimationFrame(() => ref.current.scrollIntoView({ behavior: 'smooth', block: 'center' }));\n }, [ ref.current, scrolled ]);\n\n return ref;\n}\n\ninterface StudentResponseListProps {\n interactive: Interactive;\n markedAnswers: MarkedAnswerHash;\n studentResults: StudentResults;\n addMarkedAnswers: (answer: StudentAnswer[], status: InteractiveAnswerStatus) => void;\n submitMarkedAnswers: () => void;\n onClickClose: () => void;\n imageCdnUrl: string;\n selectedInteractionId?: string;\n anonymiseUsers: boolean;\n reportsStyling?: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseList(props: StudentResponseListProps): JSX.Element {\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n const selectedInteractionRef = useScrollSelectedInteractionIntoView();\n\n const summary = getStudentResultsSummary(props.interactive, props.studentResults);\n const interactions = getInteractions(props.interactive);\n const questionsToMark = getInteractionsToMark(interactions, props.studentResults);\n\n function onClickSubmit(): void {\n setShowSpinner(true);\n props.submitMarkedAnswers();\n }\n\n return (\n <>\n <StudentResponseListHeader\n summary={summary}\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n <ul className='list-unstyled'>\n {interactions.map((interaction, idx) => {\n const isSelected = interaction.id.toString() === props.selectedInteractionId?.toString();\n const markingRequired = questionsToMark.some(q => q.id === interaction.id);\n const anonymisedUserName = anonymiseUserName(\n props.studentResults.user || props.studentResults.publicUser,\n props.anonymiseUsers\n );\n\n let className = 'p-2 mb-3 rounded';\n\n if (isSelected)\n className += ' border-2 border-info shadow';\n\n if (markingRequired)\n className += ` ${styles.awaitingMarking}`;\n else\n className += ' border';\n\n return (\n <li key={idx} className={className} ref={isSelected ? selectedInteractionRef : null}>\n <div className='d-flex mb-2'>\n <InteractionLabel\n interaction={interaction}\n iconClassName='flex-shrink-0'\n />\n </div>\n {props.reportsStyling ? (\n <InteractionResponse\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n className='bg-light ps-2'\n showFeedback\n reportsStyling\n responseComponentClass='mx-n2'\n />\n ) : (\n <InteractionResponseItem\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n showFeedback\n />\n )}\n </li>\n );\n })}\n </ul>\n <StudentResponseListFooter\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n onClickClose={props.onClickClose}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n </>\n );\n}","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};\n\nexport const ScoreThresholdInsights: ScoreThresholds = {\n HIGH: 0.7,\n MODERATE: 0.7\n};","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import { Core } from 'libs/common/core';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { ContextService } from 'libs/shared/services/ContextService';\n\ninterface UpdateParamsOptions extends Core.AppLinkOptions {\n merge?: boolean;\n keysToRemove?: string[]\n}\n\nexport const AppRouteHelper = {\n /**\n * Utility to update the params on the current appRoute.\n * \n * This is built on top of ContextService rather than build into AppLink\n * as we will generally only want to update params on appRoutes, not appLinks.\n */\n updateParams(params: HashObject, options?: UpdateParamsOptions): void {\n const { appLink } = ContextService.getCurrentRoute();\n\n let currentParams = typeof(appLink.params) === 'string'\n ? Core.LocationUtils.DeserializeQueryParams(appLink.params)\n : appLink.params as HashObject;\n\n if (options.keysToRemove)\n currentParams = ObjectHelper.omit(currentParams, options.keysToRemove);\n\n const updatedParams = options?.merge\n ? { ...currentParams, ...params }\n : params;\n\n const updatedAppLink = {\n ...appLink,\n params: updatedParams\n };\n\n /**\n * This prevents us pointlessly re-triggering if we're already on the right applink.\n */\n if (ObjectHelper.isEqual(appLink, updatedAppLink))\n return;\n \n Core.AppLinkHelper.trigger(updatedAppLink, ObjectHelper.omit(options, [ 'merge', 'keysToRemove' ]));\n }\n};"],"names":["useFetchInteractiveResults","interactiveMetadataId","requestFilter","includePublicResults","currentUser","interactiveMetadata","interactive","data","interactiveId","shouldFetchResults","I","id","AnalyticsFilterHelper","getAudienceAppLinkParams","appLink","params","users","classrooms","classroomGroups","getParam","key","param","Array","isArray","audienceFilters","getDateRangeAppLinkParams","from","to","rangeName","dateRangeFilters","anonymiseUserName","user","shouldAnonymise","profileId","seed","Math","floor","Date","getMinutes","dictionaries","separator","length","style","name","getPhrase","convertDateToUtcDateTimeString","date","utc","getMinDate","getMaxDate","getDefaultDateRange","dateRangePresets","find","range","getPresetRangeByName","dateRangePresetss","p","getInsightsDateRangePresets","minDate","currentYear","getFullYear","isMinDateThisYear","startDate","endDate","getMonth","disabled","tooltip","default","formatDateQueryParam","getRouteQueryParams","dateRange","useGetDateRangeFromQueryParams","dateRangeQueryParams","presetRange","replace","merge","keysToRemove","defaultDateRange","initialDateRangeValid","getStartEndParams","filterParams","getStartDate","getEndDate","start","end","defaultRange","InteractiveStudentResultsView","props","anonymiseUsers","dateRangeAppLinkParams","results","config","closePopup","markedAnswers","addMarkedAnswers","submitMarkedAnswers","studentResults","students","s","userId","toString","publicUser","popupTitle","studentName","dataLoaded","title","showLoadingSpinner","size","imageCdnUrl","selectedInteractionId","interactionId","onClickClose","reportsStyling","LanguageService","StudentResponseListFooter","numMarkedAnswers","Object","keys","className","showSubmitButtonSpinner","onClick","interactionsToMark","isDemo","Tooltip","spanHack","spanHackClassName","SpinnerButton","variant","onClickSubmit","showSpinner","StudentResponseListHeader","summary","unanswered","awaitingMarking","round","percentCorrect","StudentResponseList","ref","scrolled","setScrolled","setShowSpinner","selectedInteractionRef","current","requestAnimationFrame","scrollIntoView","behavior","block","interactions","questionsToMark","filter","i","InteractiveCorrectnessHelper","InteractionCorrectness","getInteractionsToMark","map","interaction","idx","isSelected","markingRequired","some","q","anonymisedUserName","InteractionLabel","iconClassName","InteractionResponse","markedStatus","markInteraction","showFeedback","responseComponentClass","InteractionResponseItem","ScoreThresholdDefaults","HIGH","MODERATE","ScoreThresholdInsights","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","useEffect","forEach","AppRouteHelper","updateParams","options","currentParams","updatedParams","updatedAppLink"],"sourceRoot":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[6798],{26136:(e,t,n)=>{n.d(t,{B:()=>a});var r=n(76198),i=n(64818);function a(e,t){return e?t?(0,r._8)((n="profileId"in e?e.profileId:e.id,a=+"".concat(n).concat(Math.floor((new Date).getMinutes()/5)),{dictionaries:[r.O9,r.yd],separator:" ",length:2,style:"capital",seed:a})):"profileId"in e?e.name:i.l.getFullName(e):"";var n,a}},21327:(e,t,n)=>{n.d(t,{R:()=>S});var r=n(32735),i=n(9570),a=n(26136),s=n(39157),o=n(44113),l=n(86572),u=n(28972),c=n(83140),d=n(80845),m=n(23481),v=n(2102),f=n(36532),b=m.T.encloseNamespace("interactives.studentResponseList");function g(e){var t=Object.keys(e.markedAnswers).length;return r.createElement("div",{className:"d-flex justify-content-end pt-3"},r.createElement("div",null,!e.showSubmitButtonSpinner&&r.createElement("button",{className:"btn btn-link",onClick:e.onClickClose},b("close")),!!e.interactionsToMark.length&&r.createElement(r.Fragment,null,e.isDemo?r.createElement(f.u,{id:"submitAnswers",title:b("demoOnly"),spanHack:!0,spanHackClassName:"d-inline-flex"},r.createElement("button",{className:"btn btn-outline-dark pointer-events-none",disabled:!t},b("submitAnswers"))):r.createElement(v.m,{variant:"outline-dark",onClick:e.onClickSubmit,disabled:!t,showSpinner:e.showSubmitButtonSpinner},b("submitAnswers")))))}var p=m.T.encloseNamespace("interactives.studentResponseList");function k(e){var t=Object.keys(e.markedAnswers).length;return r.createElement("div",{className:"d-flex justify-content-between pb-3"},r.createElement("div",{className:"d-flex"},!!e.summary.unanswered&&r.createElement("div",{className:"bg-light rounded p-2 me-2"},r.createElement("strong",{className:"me-2"},p("unanswered")),e.summary.unanswered),r.createElement("div",{className:"bg-light rounded p-2 me-2"},r.createElement("strong",{className:"me-2"},p("score")),e.summary.awaitingMarking?r.createElement("em",null,p("pending")):"".concat(Math.round(100*e.summary.percentCorrect),"%"))),!!e.interactionsToMark.length&&r.createElement(r.Fragment,null,e.isDemo?r.createElement(f.u,{id:"submitAnswers",title:p("demoOnly"),spanHack:!0},r.createElement("button",{className:"btn btn-outline-dark pointer-events-none",disabled:!t},p("submitAnswers"))):r.createElement(v.m,{variant:"outline-dark",onClick:e.onClickSubmit,disabled:!t,showSpinner:e.showSubmitButtonSpinner},p("submitAnswers"))))}const y={awaitingMarking:"MvGb5"};function h(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a,s,o=[],l=!0,u=!1;try{if(a=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=a.call(n)).done)&&(o.push(r.value),o.length!==t);l=!0);}catch(e){u=!0,i=e}finally{try{if(!l&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(u)throw i}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return w(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?w(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function w(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function S(e){var t,n,m,v,f=h(r.useState(!1),2),b=f[0],p=f[1],w=(t=r.useRef(),n=h(r.useState(!1),2),m=n[0],v=n[1],r.useEffect((function(){t.current&&!m&&(v(!0),requestAnimationFrame((function(){return t.current.scrollIntoView({behavior:"smooth",block:"center"})})))}),[t.current,m]),t),S=(0,s.Rt)(e.interactive,e.studentResults),A=(0,d.Q)(e.interactive),E=function(e,t){return e.filter((function(e){return c.A.isInteractionCorrect(e,(0,d.j_)(t))===u.w.AwaitingMarking}))}(A,e.studentResults);function C(){p(!0),e.submitMarkedAnswers()}return r.createElement(r.Fragment,null,r.createElement(k,{summary:S,interactionsToMark:E,markedAnswers:e.markedAnswers,onClickSubmit:C,showSubmitButtonSpinner:b,isDemo:e.isDemo}),r.createElement("ul",{className:"list-unstyled"},A.map((function(t,n){var u,c=t.id.toString()===(null===(u=e.selectedInteractionId)||void 0===u?void 0:u.toString()),d=E.some((function(e){return e.id===t.id})),m=(0,a.B)(e.studentResults.user||e.studentResults.publicUser,e.anonymiseUsers),v="p-2 mb-3 rounded";return c&&(v+=" border-2 border-info shadow"),v+=d?" ".concat(y.awaitingMarking):" border",r.createElement("li",{key:n,className:v,ref:c?w:null},r.createElement("div",{className:"d-flex mb-2"},r.createElement(l.y,{interaction:t,iconClassName:"flex-shrink-0"})),e.reportsStyling?r.createElement(o.O,{interaction:t,studentResults:e.studentResults,markedStatus:(0,s.HI)(t.id,e.studentResults,e.markedAnswers),markInteraction:e.addMarkedAnswers,imageCdnUrl:e.imageCdnUrl,anonymisedUserName:m,className:"bg-light ps-2",showFeedback:!0,reportsStyling:!0,responseComponentClass:"mx-n2"}):r.createElement(i.d,{interaction:t,studentResults:e.studentResults,markedStatus:(0,s.HI)(t.id,e.studentResults,e.markedAnswers),markInteraction:e.addMarkedAnswers,imageCdnUrl:e.imageCdnUrl,anonymisedUserName:m,showFeedback:!0}))}))),r.createElement(g,{interactionsToMark:E,markedAnswers:e.markedAnswers,onClickSubmit:C,onClickClose:e.onClickClose,showSubmitButtonSpinner:b,isDemo:e.isDemo}))}},94892:(e,t,n)=>{n.d(t,{T:()=>i,i:()=>r});var r={HIGH:.75,MODERATE:.5},i={HIGH:.7,MODERATE:.7}},94644:(e,t,n)=>{n.d(t,{r:()=>c});var r=n(50242),i=n(81886),a=n(67058),s=n(14553),o=n(49267),l=n(49075),u={notFound:a.d,forbidden:{rating:s.q,yearLevel:s.q,region:o.a,privacy:s.q},badRequest:l._,internalServerError:l._};function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(e){var a;a="number"==typeof e?e:e.status;var s=Object.assign(Object.assign({},u),t);a&&i.Q.Ry.isStatusCodeError(a)&&(a!==r.o.InternalServer?a!==r.o.NotFound?a!==r.o.Forbidden?n.badRequest||i.Q.Ry.throw(new s.badRequest):n.forbidden||i.Q.Ry.throw(new s.forbidden.privacy):n.notFound||i.Q.Ry.throw(new s.notFound):n.internalServerError||i.Q.Ry.throw(new l._))}}},54405:(e,t,n)=>{n.d(t,{X:()=>r});var r={interactive:function(){return{url:"/mocks/insights/interactive.json",key:"demo:interactive",normalize:!1}},interactiveMetadata:function(){return{url:"/mocks/insights/interactive-metadata.json",key:"demo:interactive:metadata",normalize:!1}},interactiveResults:function(){return{url:"/mocks/insights/interactive-results.json",key:"demo:interactive:results",normalize:!1}},videoViews:function(){return{url:"/mocks/insights/video-views.json",key:"demo:video:views",normalize:!1}},users:function(){return{url:"/mocks/insights/users.json",key:"demo:users",normalize:!1}},individualHeatmap:function(){return{url:"/mocks/insights/individual-heatmap.json",key:"demo:individual:heatmap",normalize:!1}},aggregateHeatmap:function(){return{url:"/mocks/insights/aggregate-heatmap.json",key:"demo:aggregate:heatmap",normalize:!1}}}},91286:(e,t,n)=>{n.d(t,{v:()=>s});var r=n(32735),i=n(94644);function a(e){return e.map((function(e){return e.statusCode})).join(":")}function s(e,t,n){var s=Array.isArray(e)?e:[e];(0,r.useEffect)((function(){s.forEach((function(e){(0,i.r)(e.statusCode,t,n)}))}),[a(s),t,n])}},29818:(e,t,n)=>{n.r(t),n.d(t,{InteractiveStudentResultsDemoView:()=>y});var r=n(32735),i=n(23481),a=n(20354),s=n(2948),o=n(9193),l=n(26136),u=n(21327),c=n(9111),d=n(38143),m=n(39151),v=n(54405),f=n(26304),b=n(91286),g=n(93322);function p(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var k=i.T.encloseNamespace("shared.interactiveStudentResults");function y(e){var t,n,i,y,h,w=(y=(0,s.D)(d.g.ANONYMISE_USERS),h=1,function(e){if(Array.isArray(e))return e}(y)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a,s,o=[],l=!0,u=!1;try{if(a=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=a.call(n)).done)&&(o.push(r.value),o.length!==t);l=!0);}catch(e){u=!0,i=e}finally{try{if(!l&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(u)throw i}}return o}}(y,h)||function(e,t){if(e){if("string"==typeof e)return p(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?p(e,t):void 0}}(y,h)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0];(0,g.F)();var S=a.a.useBasicFetch(v.X.interactiveMetadata()),A=a.a.useBasicFetch(v.X.interactive()),E=a.a.useBasicFetch(v.X.interactiveResults()),C=a.a.useBasicFetch(m.L.config());(0,b.v)([S,E]),(0,f.b)(S);var R=(0,o.D)(null===(t=A.data)||void 0===t?void 0:t.id,null===(n=S.data)||void 0===n?void 0:n.id,e.closePopup),I=R.markedAnswers,M=R.addMarkedAnswers,N=R.submitMarkedAnswers,j=null===(i=E.data)||void 0===i?void 0:i.students.find((function(t){var n,r,i,a,s,o;return e.userId?(null===(r=null===(n=t.user)||void 0===n?void 0:n.id)||void 0===r?void 0:r.toString())===(null===(i=e.userId)||void 0===i?void 0:i.toString()):!!e.profileId&&(null===(s=null===(a=t.publicUser)||void 0===a?void 0:a.profileId)||void 0===s?void 0:s.toString())===(null===(o=e.profileId)||void 0===o?void 0:o.toString())})),F=j?k("heading",{studentName:(0,l.B)(j.user||j.publicUser,w)}):"",O=!!A.data&&!!E.data&&!!C.data;return r.createElement(c.G,{title:F,showLoadingSpinner:!O,closePopup:e.closePopup,size:"lg"},O&&r.createElement(u.R,{interactive:A.data,studentResults:j,markedAnswers:I,addMarkedAnswers:M,submitMarkedAnswers:N,imageCdnUrl:C.data.imageCdnUrl,selectedInteractionId:e.interactionId,onClickClose:e.closePopup,anonymiseUsers:w,reportsStyling:e.reportsStyling,isDemo:!0}))}}}]);
|
|
2
|
+
//# sourceMappingURL=6798-ccca72960a-lite.chunk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts/6798-ccca72960a-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListFooter.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListHeader.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/student-response-list.scss","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseList.tsx","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/flight-requests/InsightsDemoRequests.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/projects/lite/src/apps/insights/views/demo/interactive-student-results/InteractiveStudentResultsDemoView.tsx"],"sourcesContent":["import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { User } from 'libs/shared/interfaces';\nimport { PublicInteractiveUser } from 'libs/shared/interfaces/models/interactive-results/PublicInteractiveUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\n\nfunction getUniqueNamesConfig(id: string): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: User | PublicInteractiveUser, shouldAnonymise: boolean): string {\n if (!user)\n return '';\n\n if (!shouldAnonymise)\n return 'profileId' in user ? user.name : UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig('profileId' in user ? user.profileId : user.id));\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListFooterProps {\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n onClickClose: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListFooter(props: StudentResponseListFooterProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-end pt-3'>\n <div>\n {!props.showSubmitButtonSpinner &&\n <button className='btn btn-link' onClick={props.onClickClose}>\n {getPhrase('close')}\n </button>\n }\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip\n id='submitAnswers'\n title={getPhrase('demoOnly')}\n spanHack\n spanHackClassName='d-inline-flex'\n >\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n </div>\n );\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { ResultsSummary } from 'libs/shared/apps/analytics/interfaces/ResultsSummary';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListHeaderProps {\n summary: ResultsSummary;\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListHeader(props: StudentResponseListHeaderProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-between pb-3'>\n <div className='d-flex'>\n {!!props.summary.unanswered &&\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('unanswered')}</strong>\n {props.summary.unanswered}\n </div>\n }\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('score')}</strong>\n {props.summary.awaitingMarking\n ? <em>{getPhrase('pending')}</em>\n : `${Math.round(props.summary.percentCorrect * 100)}%`\n }\n </div>\n </div>\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip id='submitAnswers' title={getPhrase('demoOnly')} spanHack>\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"awaitingMarking\":\"MvGb5\"};","import React from 'react';\n\nimport { InteractionResponseItem } from 'libs/shared/apps/analytics/components/questions-list/interaction-response-item/InteractionResponseItem';\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getMarkedStatus, getStudentResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { InteractionResponse } from 'libs/shared/components/interaction-response/InteractionResponse';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, Interactive, StudentAnswer, StudentResults } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getInteractions, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\n\nimport { StudentResponseListFooter } from './StudentResponseListFooter';\nimport { StudentResponseListHeader } from './StudentResponseListHeader';\n\nimport styles from './student-response-list.scss';\n\nfunction getInteractionsToMark(\n interactions: Interaction[],\n studentResults: StudentResults\n): Interaction[] {\n return interactions.filter(i => {\n return InteractiveCorrectnessHelper.isInteractionCorrect(\n i,\n getStudentResult(studentResults)\n ) === InteractionCorrectness.AwaitingMarking;\n });\n}\n\n// eslint-disable-next-line rulesdir/require-view-title\nfunction useScrollSelectedInteractionIntoView(): React.MutableRefObject<HTMLLIElement> {\n const ref = React.useRef<HTMLLIElement>();\n const [ scrolled, setScrolled ] = React.useState(false);\n\n // Only scroll once\n React.useEffect(() => {\n if (!ref.current || scrolled)\n return;\n\n setScrolled(true);\n requestAnimationFrame(() => ref.current.scrollIntoView({ behavior: 'smooth', block: 'center' }));\n }, [ ref.current, scrolled ]);\n\n return ref;\n}\n\ninterface StudentResponseListProps {\n interactive: Interactive;\n markedAnswers: MarkedAnswerHash;\n studentResults: StudentResults;\n addMarkedAnswers: (answer: StudentAnswer[], status: InteractiveAnswerStatus) => void;\n submitMarkedAnswers: () => void;\n onClickClose: () => void;\n imageCdnUrl: string;\n selectedInteractionId?: string;\n anonymiseUsers: boolean;\n reportsStyling?: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseList(props: StudentResponseListProps): JSX.Element {\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n const selectedInteractionRef = useScrollSelectedInteractionIntoView();\n\n const summary = getStudentResultsSummary(props.interactive, props.studentResults);\n const interactions = getInteractions(props.interactive);\n const questionsToMark = getInteractionsToMark(interactions, props.studentResults);\n\n function onClickSubmit(): void {\n setShowSpinner(true);\n props.submitMarkedAnswers();\n }\n\n return (\n <>\n <StudentResponseListHeader\n summary={summary}\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n <ul className='list-unstyled'>\n {interactions.map((interaction, idx) => {\n const isSelected = interaction.id.toString() === props.selectedInteractionId?.toString();\n const markingRequired = questionsToMark.some(q => q.id === interaction.id);\n const anonymisedUserName = anonymiseUserName(\n props.studentResults.user || props.studentResults.publicUser,\n props.anonymiseUsers\n );\n\n let className = 'p-2 mb-3 rounded';\n\n if (isSelected)\n className += ' border-2 border-info shadow';\n\n if (markingRequired)\n className += ` ${styles.awaitingMarking}`;\n else\n className += ' border';\n\n return (\n <li key={idx} className={className} ref={isSelected ? selectedInteractionRef : null}>\n <div className='d-flex mb-2'>\n <InteractionLabel\n interaction={interaction}\n iconClassName='flex-shrink-0'\n />\n </div>\n {props.reportsStyling ? (\n <InteractionResponse\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n className='bg-light ps-2'\n showFeedback\n reportsStyling\n responseComponentClass='mx-n2'\n />\n ) : (\n <InteractionResponseItem\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n showFeedback\n />\n )}\n </li>\n );\n })}\n </ul>\n <StudentResponseListFooter\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n onClickClose={props.onClickClose}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n </>\n );\n}","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};\n\nexport const ScoreThresholdInsights: ScoreThresholds = {\n HIGH: 0.7,\n MODERATE: 0.7\n};","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { Flight } from 'libs/common/react/index';\n\nexport const InsightsDemoRequests = {\n interactive(): Flight.Request {\n return {\n url: `/mocks/insights/interactive.json`,\n key: `demo:interactive`,\n normalize: false\n };\n },\n\n interactiveMetadata(): Flight.Request {\n return {\n url: `/mocks/insights/interactive-metadata.json`,\n key: `demo:interactive:metadata`,\n normalize: false\n };\n },\n\n interactiveResults(): Flight.Request {\n return {\n url: `/mocks/insights/interactive-results.json`,\n key: `demo:interactive:results`,\n normalize: false\n };\n },\n\n videoViews(): Flight.Request {\n return {\n url: `/mocks/insights/video-views.json`,\n key: `demo:video:views`,\n normalize: false\n };\n },\n\n users(): Flight.Request {\n return {\n url: `/mocks/insights/users.json`,\n key: `demo:users`,\n normalize: false\n };\n },\n\n individualHeatmap(): Flight.Request {\n return {\n url: `/mocks/insights/individual-heatmap.json`,\n key: `demo:individual:heatmap`,\n normalize: false\n };\n },\n\n aggregateHeatmap(): Flight.Request {\n return {\n url: `/mocks/insights/aggregate-heatmap.json`,\n key: `demo:aggregate:heatmap`,\n normalize: false\n };\n }\n};","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { useMarkAnswers } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { StudentResponseList } from 'libs/shared/apps/student-response-list/StudentResponseList';\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InsightsDemoRequests } from 'libs/shared/flight-requests/InsightsDemoRequests';\nimport { useCannotConsumeError } from 'libs/shared/hooks/useCannotConsumeError';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useLockContentWidth } from 'libs/shared/hooks/useLockContentWidth';\nimport { Config, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { PopupViewProps } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.interactiveStudentResults';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InteractiveStudentResultsViewProps extends PopupViewProps {\n userId: string;\n interactiveId: string;\n interactionId?: string;\n reportsStyling?: boolean;\n profileId?: string;\n}\n\nexport function InteractiveStudentResultsDemoView(props: InteractiveStudentResultsViewProps): JSX.Element {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n useLockContentWidth();\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InsightsDemoRequests.interactiveMetadata()\n );\n const interactive = Flight.useBasicFetch<Interactive>(InsightsDemoRequests.interactive());\n\n const results = Flight.useBasicFetch<InteractiveResultSet>(InsightsDemoRequests.interactiveResults());\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n useHandleObjectError([ interactiveMetadata, results ]);\n useCannotConsumeError(interactiveMetadata);\n\n const { markedAnswers, addMarkedAnswers, submitMarkedAnswers } = useMarkAnswers(\n interactive.data?.id,\n interactiveMetadata.data?.id,\n props.closePopup\n );\n\n const studentResults = results.data?.students.find(s => {\n if (props.userId)\n return s.user?.id?.toString() === props.userId?.toString();\n\n if (props.profileId)\n return s.publicUser?.profileId?.toString() === props.profileId?.toString();\n\n return false;\n });\n\n const popupTitle = studentResults\n ? getPhrase('heading', { studentName: anonymiseUserName(studentResults.user || studentResults.publicUser, anonymiseUsers) })\n : '';\n const dataLoaded = !!interactive.data && !!results.data && !!config.data;\n\n return (\n <Popup\n title={popupTitle}\n showLoadingSpinner={!dataLoaded}\n closePopup={props.closePopup}\n size='lg'\n >\n {dataLoaded &&\n <StudentResponseList\n interactive={interactive.data}\n studentResults={studentResults}\n markedAnswers={markedAnswers}\n addMarkedAnswers={addMarkedAnswers}\n submitMarkedAnswers={submitMarkedAnswers}\n imageCdnUrl={config.data.imageCdnUrl}\n selectedInteractionId={props.interactionId}\n onClickClose={props.closePopup}\n anonymiseUsers={anonymiseUsers}\n reportsStyling={props.reportsStyling}\n isDemo\n />\n }\n </Popup>\n );\n}"],"names":["anonymiseUserName","user","shouldAnonymise","id","profileId","seed","Math","floor","Date","getMinutes","dictionaries","separator","length","style","name","getPhrase","LanguageService","StudentResponseListFooter","props","numMarkedAnswers","Object","keys","markedAnswers","className","showSubmitButtonSpinner","onClick","onClickClose","interactionsToMark","isDemo","Tooltip","title","spanHack","spanHackClassName","disabled","SpinnerButton","variant","onClickSubmit","showSpinner","StudentResponseListHeader","summary","unanswered","awaitingMarking","round","percentCorrect","StudentResponseList","ref","scrolled","setScrolled","setShowSpinner","selectedInteractionRef","current","requestAnimationFrame","scrollIntoView","behavior","block","interactive","studentResults","interactions","questionsToMark","filter","i","InteractiveCorrectnessHelper","InteractionCorrectness","getInteractionsToMark","submitMarkedAnswers","map","interaction","idx","isSelected","toString","selectedInteractionId","markingRequired","some","q","anonymisedUserName","publicUser","anonymiseUsers","key","InteractionLabel","iconClassName","reportsStyling","InteractionResponse","markedStatus","markInteraction","addMarkedAnswers","imageCdnUrl","showFeedback","responseComponentClass","InteractionResponseItem","ScoreThresholdDefaults","HIGH","MODERATE","ScoreThresholdInsights","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","InsightsDemoRequests","url","normalize","interactiveMetadata","interactiveResults","videoViews","users","individualHeatmap","aggregateHeatmap","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","Array","isArray","useEffect","forEach","InteractiveStudentResultsDemoView","results","config","data","closePopup","students","find","s","userId","popupTitle","studentName","dataLoaded","showLoadingSpinner","size","interactionId"],"sourceRoot":""}
|