Skip to content

Commit

Permalink
feat(client+server): added SCORM mastery score
Browse files Browse the repository at this point in the history
  • Loading branch information
sr258 committed Apr 5, 2021
1 parent ec5b495 commit 6952d5b
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 76 deletions.
9 changes: 6 additions & 3 deletions client/src/state/H5PEditor/H5PApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ export function loadPlayerContent(
return superagent.get(`/api/v1/h5p/${contentId}/play`);
}

export function exportAsHtml(
export function exportContent(
contentId: string,
includeReporter: boolean,
format: 'bundle' | 'external' | 'scorm'
format: 'bundle' | 'external' | 'scorm',
options: { masteryScore?: string }
): Promise<superagent.Response> {
return superagent.get(
`/api/v1/h5p/${contentId}/html?includeReporter=${includeReporter}&format=${format}`
`/api/v1/h5p/${contentId}/export?includeReporter=${includeReporter}&format=${format}${
options.masteryScore ? `&masteryScore=${options.masteryScore}` : ''
}`
);
}

Expand Down
10 changes: 8 additions & 2 deletions client/src/state/H5PEditor/H5PEditorActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ export function cancelExportH5P() {

export function exportH5P(
includeReporter: boolean,
format: 'bundle' | 'external' | 'scorm'
format: 'bundle' | 'external' | 'scorm',
options: { masteryScore?: string }
): any {
return async (dispatch: any) => {
try {
Expand All @@ -141,7 +142,12 @@ export function exportH5P(
});

try {
await api.exportAsHtml(data.contentId, includeReporter, format);
await api.exportContent(
data.contentId,
includeReporter,
format,
options
);

// TOOD: chang tracking
dispatch(
Expand Down
193 changes: 125 additions & 68 deletions client/src/views/components/H5PEditorExportDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import RadioGroup from '@material-ui/core/RadioGroup';
import Switch from '@material-ui/core/Switch';

import { actions, IState } from '../../state';
import { FormHelperText } from '@material-ui/core';
import { Box, FormHelperText, TextField } from '@material-ui/core';

export default function H5PEditorExportDialog() {
// const { open, yesCallback, noCallback } = props;
Expand All @@ -28,6 +28,9 @@ export default function H5PEditorExportDialog() {
'bundle' | 'external' | 'scorm'
>('bundle');
const [includeReporter, setIncludeReporter] = useState<boolean>(true);
const [masteryScore, setMasteryScore] = useState<string>('70');
const [masteryScoreError, setMasteryScoreError] = useState<string>();
const [isValid, setIsValid] = useState<boolean>(true);

const dispatch = useDispatch();
// const { t } = useTranslation();
Expand All @@ -44,77 +47,124 @@ export default function H5PEditorExportDialog() {
Export settings
</DialogTitle>
<DialogContent>
<FormControl>
<FormLabel>Format</FormLabel>
<RadioGroup
name="exportformat"
value={formatChoice}
onChange={(e, val) => setFormatChoice(val as any)}
>
<FormControlLabel
value="bundle"
control={<Radio />}
label="All-in-one HTML file"
/>
{formatChoice === 'bundle' && (
<FormHelperText>
The file can grow too big for some computers
if you include lots of media files.
</FormHelperText>
)}
<Box paddingBottom={4}>
<FormControl>
<FormLabel>Format</FormLabel>
<RadioGroup
name="exportformat"
value={formatChoice}
onChange={(e, val) =>
setFormatChoice(val as any)
}
>
<FormControlLabel
value="bundle"
control={<Radio />}
label="All-in-one HTML file"
/>
{formatChoice === 'bundle' && (
<FormHelperText>
The file can grow too big for some
computers if you include lots of media
files.
</FormHelperText>
)}
<FormControlLabel
value="external"
control={<Radio />}
label="One HTML file and several media files"
/>
{formatChoice === 'external' && (
<FormHelperText>
You will be asked for a name for the
HTML file in the next step. The media
files will be put into folders that
start with the same name as the file.
</FormHelperText>
)}
<FormControlLabel
value="scorm"
control={<Radio />}
label="SCORM package"
/>
{formatChoice === 'scorm' && (
<Box marginLeft={2}>
<TextField
label="Mastery score (in %)"
value={masteryScore}
error={
masteryScoreError !== undefined
}
helperText={masteryScoreError}
onChange={(event) => {
const parsed = Number.parseFloat(
event.target.value
);
if (isNaN(parsed)) {
setMasteryScoreError(
'Entered value is not a number'
);
setIsValid(false);
} else if (
parsed < 0 ||
parsed > 100
) {
setMasteryScoreError(
'The value must be between 0 and 100'
);
setIsValid(false);
} else {
setMasteryScoreError(
undefined
);
setIsValid(true);
}
setMasteryScore(
event.target.value
);
}}
/>
</Box>
)}
</RadioGroup>
</FormControl>
</Box>
<Box>
<FormControl>
<FormLabel>Reporter</FormLabel>
<FormHelperText>
If you add the reporter, students can save a
file with their progress and send it to you.
<a
href="https://lumieducation.gitbook.io/lumi/analytics/reporter"
target="_blank"
rel="noreferrer"
>
Learn more about it here.
</a>
</FormHelperText>
<FormControlLabel
value="external"
control={<Radio />}
label="One HTML file and several media files"
control={<Switch />}
checked={
formatChoice === 'scorm'
? false
: includeReporter
}
onChange={(e, checked) =>
setIncludeReporter(checked)
}
disabled={formatChoice === 'scorm'}
name="includeReporter"
label="Include reporter"
/>
{formatChoice === 'external' && (
{formatChoice === 'scorm' && (
<FormHelperText>
You will be asked for a name for the HTML
file in the next step. The media files will
be put into folders that start with the same
name as the file.
The reporter cannot be added to SCORM
packages.
</FormHelperText>
)}
<FormControlLabel
value="scorm"
control={<Radio />}
label="SCORM package"
/>
</RadioGroup>
</FormControl>
<FormControl>
<FormLabel>Reporter</FormLabel>
<FormHelperText>
If you add the reporter, students can save a file
with their progress and send it to you.{' '}
<a
href="https://lumieducation.gitbook.io/lumi/analytics/reporter"
target="_blank"
rel="noreferrer"
>
Learn more about it here.
</a>
</FormHelperText>
<FormControlLabel
control={<Switch />}
checked={
formatChoice === 'scorm'
? false
: includeReporter
}
onChange={(e, checked) =>
setIncludeReporter(checked)
}
disabled={formatChoice === 'scorm'}
name="includeReporter"
label="Include reporter"
/>
{formatChoice === 'scorm' && (
<FormHelperText>
The reporter cannot be added to SCORM packages.
</FormHelperText>
)}
</FormControl>
</FormControl>
</Box>
</DialogContent>
<DialogActions>
<Button
Expand All @@ -133,10 +183,17 @@ export default function H5PEditorExportDialog() {
formatChoice !== 'scorm'
? includeReporter
: false,
formatChoice
formatChoice,
{
masteryScore:
formatChoice === 'scorm'
? masteryScore
: undefined
}
)
)
}
disabled={formatChoice === 'scorm' && !isValid}
>
Export now
</Button>
Expand Down
1 change: 0 additions & 1 deletion scorm-client/h5p-adaptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ var onCompleted = function (result) {
};

H5P.externalDispatcher.on('xAPI', function (event) {
console.log('xAPI event: ' + JSON.stringify(event));
if (event.data.statement.result) {
onCompleted(event.data.statement.result);
}
Expand Down
9 changes: 7 additions & 2 deletions server/src/routes/h5pRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,11 @@ export default function (
req: express.Request<
{ contentId: string },
any,
{ scormOptions: { masteryScore: number } },
any,
{
format: 'bundle' | 'external' | 'scorm';
includeReporter: string;
masteryScore: string;
}
> & { user: H5P.IUser },
res
Expand Down Expand Up @@ -189,7 +190,11 @@ export default function (
path,
req.params.contentId,
req.user,
req.body.scormOptions
{
masteryScore: Number.parseFloat(
req.query.masteryScore
)
}
);
}
} catch (error) {
Expand Down

0 comments on commit 6952d5b

Please sign in to comment.