Skip to content

Commit

Permalink
[FEATURE] Add support for user to provide download Url (#76)
Browse files Browse the repository at this point in the history
* feat: add support for download url option

* docs: add support for download url option

* test: replace extracted H5P files with a task to unzip during tests

* test: H5P player download option tests
  • Loading branch information
murage authored Apr 23, 2021
1 parent 1ec9101 commit 40c8954
Show file tree
Hide file tree
Showing 224 changed files with 258 additions and 24,615 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The player can be set up either by directly calling the already built scripts an

const el = document.getElementById('h5p-container');
const options = {
h5pJsonPath: '/h5p-folder';
h5pJsonPath: '/h5p-folder',
frameJs: '/assets/frame.bundle.js',
frameCss: '/assets/styles/h5p.css',
}
Expand Down Expand Up @@ -89,8 +89,9 @@ The standalone H5P player constructor accepts two arguments.
`frame` |false| A boolean on whether to show frame and buttons below H5P
`copyright` |false| A boolean on whether display copyright button
`embed` |false| A boolean on whether display embed button
`export` |false| A boolean on whether display a download button
`export` |false| A boolean on whether display a download button.
`icon` |false| A boolean on whether display H5P icon
`downloadUrl` |false| A path or a url that returns zipped h5p for download. The link is used by H5P `export` button

**Note:**
- One can use absolute URL for `frameCss`, `frameJs`, and for other path options(`h5pJsonPath`,`librariesPath`, & `librariesPath`)
Expand All @@ -115,7 +116,8 @@ const options = {
copyright: true,
embed: false,
'export': false,
icon: true
icon: true,
downloadUrl: '/path/to/exercise-one.h5p'
};


Expand Down
25 changes: 25 additions & 0 deletions cypress/integration/advance-options.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
describe('single', () => {
it('should display h5p', () => {

cy.visit('test/advance-options.html');

cy.get('.h5p-iframe').should(iframe => {
expect(iframe.contents().find('.h5p-content')).to.exist;

iframe.contents().find('.h5p-true-false-answer').click();

iframe.contents().find('.h5p-question-check-answer').click();

expect(iframe.contents().find('.h5p-joubelui-score-bar-star')).to.exist;

expect(iframe.contents().find('.h5p-actions').find('.h5p-export')).to.exist;

iframe.contents()
.find('.h5p-actions')
.find('.h5p-export')
.click();

expect(iframe.contents().find('.h5p-download-button')).to.exist;
});
});
});
69 changes: 67 additions & 2 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,73 @@

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const fs = require('fs');
const path = require('path');
const unzipper = require("unzipper");

module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
const workspace = 'test/';
const h5pFile = 'h5p-test.h5p';
const extractFolder = 'full_workspace/'
const librariesFolder = 'libraries/'
const contentFolder = 'h5p/'


on('task', {
'unzip:h5p': async () => {
await fs.createReadStream(`${workspace}${h5pFile}`)
.pipe(unzipper.Extract({path: `${workspace}${extractFolder}`}))
.promise();
return true;
},
'copy:libraries': () => {
const H5PLibraries = ['Drop-1.0', 'FontAwesome-4.5', 'H5P.FontIcons-1.0', 'H5P.JoubelUI-1.3',
'H5P.Question-1.4', 'H5P.Transition-1.0', 'H5P.TrueFalse-1.6', 'H5PEditor.RadioGroup-1.1',
'H5PEditor.ShowWhen-1.0', 'Tether-1.0']; //reading from H5P.json is most dynamic approach

H5PLibraries.map((folder) => {
recursiveCopy(`${workspace}${extractFolder}${folder}/`, `${workspace}${librariesFolder}${folder}`)
});

return true;
},
'copy:content': () => {
recursiveCopy(`${workspace}${extractFolder}content/`, `${workspace}${contentFolder}content`)
return true;
},
'copy:h5pjson': () => {
fs.copyFileSync(`${workspace}${extractFolder}h5p.json`, `${workspace}${contentFolder}h5p.json`);
return true;
},
'clean': () => {
fs.rmdirSync(`${workspace}${extractFolder}`, {recursive: true});
fs.rmdirSync(`${workspace}${librariesFolder}`, {recursive: true});
fs.rmdirSync(`${workspace}${contentFolder}`, {recursive: true});

return true;
}
});

function recursiveCopy(src, dest) {
const exists = fs.existsSync(src);
if (!exists) {
return;
}
const stats = fs.statSync(src);
const isDirectory = stats.isDirectory();

if (isDirectory) {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest, {recursive: true});
}
fs.readdirSync(src).forEach((item) => {
recursiveCopy(path.join(src, item), path.join(dest, item));
});
} else {
fs.copyFileSync(src, dest);
}
}

}
13 changes: 11 additions & 2 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,14 @@
// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
before( () =>{

cy.task('unzip:h5p') // Extract .h5p for tests
.task('copy:libraries') // copy libraries
.task('copy:content') // copy content
.task('copy:h5pjson'); // copy H5P.json file to content folder
});

after(()=>{
cy.task('clean'); //we need to clean up after ourselves
})
2 changes: 1 addition & 1 deletion dist/main.bundle.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"husky": "^6.0.0",
"imports-loader": "^2.0.0",
"semantic-release": "^17.4.2",
"unzipper": "^0.10.11",
"webpack": "^5.32.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
Expand Down Expand Up @@ -62,4 +63,4 @@
"url": "https://github.com/tunapanda/h5p-standalone/issues"
},
"homepage": "https://github.com/tunapanda/h5p-standalone#readme"
}
}
48 changes: 37 additions & 11 deletions src/js/h5p-standalone.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,33 @@ export default class H5PStandalone {
export: options.export
};

const h5pStylesBundle = urlPath(options.frameCss);
const h5pScriptsBundle = urlPath(options.frameJs);
const contentOptions = {
displayOptions
};

if(options.downloadUrl){
contentOptions.exportUrl = urlPath(options.downloadUrl);
}

const generalIntegrationOptions ={
preventH5PInit: options.preventH5PInit?options.preventH5PInit:false,
};

// The following behaviour may change in future
if(options.frameJs){
generalIntegrationOptions.coreScripts = [urlPath(options.frameJs)]
}else{
generalIntegrationOptions.coreScripts = ['./frame.bundle.js']
}
// The following behaviour may change in future
if(options.frameCss){
generalIntegrationOptions.coreStyles =[urlPath(options.frameCss)];
}else{
generalIntegrationOptions.coreStyles =[urlPath('./styles/h5p.css')];
}

this.initElement(el);
return this.initH5P(h5pStylesBundle, h5pScriptsBundle, displayOptions, options.preventH5PInit);
return this.initH5P(generalIntegrationOptions, contentOptions);
}

initElement(el) {
Expand Down Expand Up @@ -92,7 +114,7 @@ export default class H5PStandalone {
iframe.contentWindow['jQuery'] ={}
}

async initH5P(frameCss = './styles/h5p.css', frameJs = './frame.bundle.js', displayOptions, preventH5PInit) {
async initH5P(generalIntegrationOptions,contentOptions) {
this.h5p = await this.getJSON(`${this.h5pJsonPath}/h5p.json`);

const content = await this.getJSON(`${this.contentUrl}/content.json`);
Expand All @@ -104,26 +126,30 @@ export default class H5PStandalone {

const { styles, scripts } = this.sortDependencies(dependencies);

H5PIntegration.urlLibraries = this.path;
H5PIntegration.urlLibraries = this.librariesPath ;
H5PIntegration.contents = H5PIntegration.contents ? H5PIntegration.contents : {};

H5PIntegration.core = {
styles: [frameCss],
scripts: [frameJs]
styles: generalIntegrationOptions.coreStyles,
scripts: generalIntegrationOptions.coreScripts
};

H5PIntegration.contents[`cid-${this.id}`] = {
library: `${this.mainLibrary.machineName} ${this.mainLibrary.majorVersion}.${this.mainLibrary.minorVersion}`,
jsonContent: JSON.stringify(content),
styles: styles,
scripts: scripts,
displayOptions: displayOptions,
contentUrl: this.contentUrl
displayOptions: contentOptions.displayOptions,
contentUrl: this.contentUrl,
};

// if (!preventH5PInit) {
if(contentOptions.exportUrl){
H5PIntegration.contents[`cid-${this.id}`].exportUrl = contentOptions.exportUrl;
}

if (!generalIntegrationOptions.preventH5PInit) {
H5P.init();
// }
}
}

getJSON(url) {
Expand Down
29 changes: 29 additions & 0 deletions test/advance-options.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<html>

<head>
<link type="text/css" rel="stylesheet" media="all" href="/dist/styles/h5p.css" />
<meta charset="utf-8" />
<script type="text/javascript" src="/dist/main.bundle.js"></script>
</head>

<body>
<div id="h5p-container"></div>

<script type="text/javascript">
const {
H5P
} = H5PStandalone;
new H5P(document.getElementById('h5p-container'), {
h5pJsonPath: 'full_workspace',
frameJs: '/dist/frame.bundle.js',
frameCss: '/dist/styles/h5p.css',
frame: true,
copyright: true,
embed: false,
export: true,
downloadUrl: 'test.h5p'
});
</script>
</body>

</html>

This file was deleted.

Loading

0 comments on commit 40c8954

Please sign in to comment.