diff --git a/docs/components/pie-author/readme.md b/docs/components/pie-author/readme.md index 724378f..c8869d8 100644 --- a/docs/components/pie-author/readme.md +++ b/docs/components/pie-author/readme.md @@ -26,6 +26,7 @@ The class `pie-loading` will be added to the element while assets are being load | `disableBundler` | `disable-bundler` | Allows disabling of the default behaviour which is to look up and load the JS bundle that define the Custom Elements used by the item config. This if for advanced use cases when using the pie-player in a container that is managing loading of Custom Elements and Controllers. | `boolean` | `false` | | `imageSupport` | -- | external providers can set this if they need to upload the assets to the cloud etc. by default we use data urls | `ExternalImageSupport` | `new DataURLImageSupport()` | | `isInsidePieApiAuthor` | `is-inside-pie-api-author` | If pie-author is used inside pie-api-author component. Do not set it manually. | `boolean` | `false` | +| `reFetchBundle` | `re-fetch-bundle` | used to automatically re-fetch the bundle (in case we get a 503) | `boolean` | `false` | | `uploadSoundSupport` | -- | external providers can set this if they need to upload the assets to the cloud etc. by default we use data urls | `ExternalUploadSoundSupport` | `new DataURLUploadSoundSupport()` | | `version` | `version` | | `string` | `VERSION` | diff --git a/docs/components/pie-player/readme.md b/docs/components/pie-player/readme.md index 281ab0f..5b52d1b 100644 --- a/docs/components/pie-player/readme.md +++ b/docs/components/pie-player/readme.md @@ -24,6 +24,7 @@ The class `pie-loading` will be added to the element while assets are being load | `disableBundler` | `disable-bundler` | Allows disabling of the default behaviour which is to look up and load the JS bundle that define the Custom Elements used by the item config. This if for advanced use cases when using the pie-player in a container that is managing loading of Custom Elements and Controllers. | `boolean` | `false` | | `env` | -- | Describes runtime environment for the player. | `{ mode: String \| Mode; role: String \| Role; partialScoring?: boolean; }` | `{mode: "gather", role: "student"}` | | `hosted` | `hosted` | Indicates if player running in the context of a PIE hosting system. Do not modify the default value for this property if you are not implementing a PIE host. If true, the host is responsible for all model updates. | `boolean` | `false` | +| `reFetchBundle` | `re-fetch-bundle` | used to automatically re-fetch the bundle (in case we get a 503) | `boolean` | `false` | | `renderStimulus` | `render-stimulus` | If the item contains a stimulus, the player will render it by default. Set this property to false to not render stimulus. | `boolean` | `true` | | `session` | -- | The Pie Session | `{ id: string; data: any[]; }` | `{id: "", data: []}` | | `showBottomBorder` | `show-bottom-border` | In evaluate mode, add a bottom border to visually separate each item in the case of a multi-item | `boolean` | `false` | diff --git a/package.json b/package.json index 545420f..ae9cd95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pie-framework/pie-player-components", - "version": "2.11.4", + "version": "2.11.4-beta.3", "description": "Pie Player Components", "module": "dist/index.mjs", "main": "dist/index.js", @@ -35,7 +35,8 @@ "yalc": "yalc push", "commit": "git-cz", "semantic-release": "semantic-release", - "pretest": "if [ -f set-version.sh ]; then ./set-version.sh $npm_package_version; else echo \"skip post-install\"; fi" + "pretest": "if [ -f set-version.sh ]; then ./set-version.sh $npm_package_version; else echo \"skip post-install\"; fi", + "full": "git clean -xdf . && yarn install && yarn pretest && yarn build && yarn demo" }, "dependencies": { "@material/select": "^2.2.0", @@ -44,7 +45,7 @@ "@material/tab-bar": "^2.2.0", "@pie-framework/pie-configure-events": "^1.4.1", "@pie-framework/pie-player-events": "^0.1.0", - "@pie-lib/pie-toolbox-math-rendering-module": "1.9.3", + "@pie-lib/pie-toolbox-math-rendering-module": "1.21.0-beta.0", "async-retry": "^1.2.3", "lodash": "^4.17.15", "parse-package-name": "^0.1.0" diff --git a/src/components.d.ts b/src/components.d.ts index 4868e2e..614c627 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -88,6 +88,10 @@ export namespace Components { */ 'isInsidePieApiAuthor'?: boolean; /** + * used to automatically re-fetch the bundle (in case we get a 503) + */ + 'reFetchBundle'?: boolean; + /** * external providers can set this if they need to upload the assets to the cloud etc. by default we use data urls */ 'uploadSoundSupport': ExternalUploadSoundSupport; @@ -130,6 +134,10 @@ export namespace Components { 'hosted'?: boolean; 'provideScore': () => Promise; /** + * used to automatically re-fetch the bundle (in case we get a 503) + */ + 'reFetchBundle'?: boolean; + /** * If the item contains a stimulus, the player will render it by default. Set this property to false to not render stimulus. */ 'renderStimulus': boolean; @@ -275,6 +283,10 @@ declare namespace LocalJSX { */ 'onModelUpdated'?: (event: CustomEvent) => void; /** + * used to automatically re-fetch the bundle (in case we get a 503) + */ + 'reFetchBundle'?: boolean; + /** * external providers can set this if they need to upload the assets to the cloud etc. by default we use data urls */ 'uploadSoundSupport'?: ExternalUploadSoundSupport; @@ -331,6 +343,10 @@ declare namespace LocalJSX { */ 'onSession-changed'?: (event: CustomEvent) => void; /** + * used to automatically re-fetch the bundle (in case we get a 503) + */ + 'reFetchBundle'?: boolean; + /** * If the item contains a stimulus, the player will render it by default. Set this property to false to not render stimulus. */ 'renderStimulus'?: boolean; diff --git a/src/components/pie-author/pie-author.tsx b/src/components/pie-author/pie-author.tsx index ff15916..e88676b 100644 --- a/src/components/pie-author/pie-author.tsx +++ b/src/components/pie-author/pie-author.tsx @@ -10,7 +10,7 @@ import { h } from "@stencil/core"; -import { _dll_pie_lib__pie_toolbox_math_rendering_accessible } from "@pie-lib/pie-toolbox-math-rendering-module/module"; +import { _dll_pie_lib__pie_toolbox_math_rendering, _dll_pie_lib__pie_toolbox_math_rendering_accessible } from "@pie-lib/pie-toolbox-math-rendering-module/module"; import {PieContent, ItemConfig, PieElement, PieModel, PieController} from "../../interface"; import { @@ -173,6 +173,11 @@ export class Author { */ @Prop() canWatchConfigSettings: boolean = false; + /** + * used to automatically re-fetch the bundle (in case we get a 503) + */ + @Prop() reFetchBundle?: boolean = false; + @Method() async validateModels() { if (!this.pieContentModel || !this.pieContentModel.models) { @@ -647,14 +652,15 @@ export class Author { doc: this.doc, endpoints, useCdn: false, - forceBundleUrl + forceBundleUrl, + reFetchBundle: this.reFetchBundle }); } } private renderMath() { setTimeout(() => { - _dll_pie_lib__pie_toolbox_math_rendering_accessible.renderMath(this.el); + _dll_pie_lib__pie_toolbox_math_rendering.renderMath(this.el); }, 50); } diff --git a/src/components/pie-player/pie-player.tsx b/src/components/pie-player/pie-player.tsx index e076391..0eeb9c8 100644 --- a/src/components/pie-player/pie-player.tsx +++ b/src/components/pie-player/pie-player.tsx @@ -1,5 +1,6 @@ import {SessionChangedEvent} from "@pie-framework/pie-player-events"; import { + _dll_pie_lib__pie_toolbox_math_rendering, _dll_pie_lib__pie_toolbox_math_rendering_accessible } from "@pie-lib/pie-toolbox-math-rendering-module/module"; import { @@ -122,6 +123,11 @@ export class Player { */ @Prop() showBottomBorder: boolean = false; + /** + * used to automatically re-fetch the bundle (in case we get a 503) + */ + @Prop() reFetchBundle?: boolean = false; + @Watch("addCorrectResponse") watchAddCorrectResponse(newValue, oldValue) { if (newValue !== oldValue) { @@ -223,7 +229,8 @@ export class Player { endpoints: endpoints, bundle: this.hosted ? BundleType.player : BundleType.clientPlayer, useCdn: false, - forceBundleUrl + forceBundleUrl, + reFetchBundle: this.reFetchBundle }); } } catch (err) { @@ -391,7 +398,7 @@ export class Player { private renderMath() { setTimeout(() => { - _dll_pie_lib__pie_toolbox_math_rendering_accessible.renderMath(this.el); + _dll_pie_lib__pie_toolbox_math_rendering.renderMath(this.el); }, 50); } diff --git a/src/demo/dib-and-passage-aws.html b/src/demo/dib-and-passage-aws.html new file mode 100644 index 0000000..1526753 --- /dev/null +++ b/src/demo/dib-and-passage-aws.html @@ -0,0 +1,180 @@ + + + + + + Item Player + + + + + + + + + + + + + diff --git a/src/demo/dib-and-passage-gcp.html b/src/demo/dib-and-passage-gcp.html new file mode 100644 index 0000000..1526753 --- /dev/null +++ b/src/demo/dib-and-passage-gcp.html @@ -0,0 +1,180 @@ + + + + + + Item Player + + + + + + + + + + + + + diff --git a/src/demo/mp-and-passage-aws.html b/src/demo/mp-and-passage-aws.html new file mode 100644 index 0000000..567dc1e --- /dev/null +++ b/src/demo/mp-and-passage-aws.html @@ -0,0 +1,180 @@ + + + + + + Item Player + + + + + + + + + + + + + diff --git a/src/demo/player-ibx-ATD-fast.html b/src/demo/player-ibx-ATD-fast.html new file mode 100644 index 0000000..db51c1b --- /dev/null +++ b/src/demo/player-ibx-ATD-fast.html @@ -0,0 +1,5544 @@ + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/demo/player-ibx-ATD.html b/src/demo/player-ibx-ATD.html new file mode 100644 index 0000000..ccdb96d --- /dev/null +++ b/src/demo/player-ibx-ATD.html @@ -0,0 +1,4949 @@ + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/demo/player.html b/src/demo/player.html index 7b3a86d..763bd61 100644 --- a/src/demo/player.html +++ b/src/demo/player.html @@ -2,6 +2,20 @@ + + + + MathJax Example + + + + + + + + + + + + diff --git a/src/pie-loader.ts b/src/pie-loader.ts index b12f9f6..ac2d35a 100644 --- a/src/pie-loader.ts +++ b/src/pie-loader.ts @@ -7,6 +7,11 @@ import { import { PieItemElement, PieContent } from "./interface"; import pickBy from "lodash/pickBy"; import { emptyConfigure } from "./components/empty-configure"; + +window["pieHelpers"] = { + loadingScripts: {} +} + /** * TODO: Clean up: PD-761 */ @@ -173,9 +178,7 @@ export class PieLoader { /** * - * @param {Object} elements elements to load from pie cloud service - * @param {HTMLDocument} doc - the document to load the scripts - * @param {string} base_url - default base url for cloud service + * @param options */ public loadCloudPies = async (options: { content: PieContent; @@ -184,6 +187,7 @@ export class PieLoader { bundle?: BundleType; useCdn: boolean; forceBundleUrl: boolean; + reFetchBundle: boolean; }) => { if (!options.endpoints) { options.endpoints = this.endpoints; @@ -205,21 +209,28 @@ export class PieLoader { ); let scriptUrl = this.getScriptsUrl(options, piesToLoad); + if (!scriptUrl) { console.error("No script urls found for elements."); return; } + // These scripts are actually being added to headers ONLY when the fetch below (in loadScript) returns a value + // However, if we have multiple players that are supposed to load the same bundle on the same page, + // this means that we'll make that fetch request multiple times, which slows down the page const loadedScripts = [...head.getElementsByTagName("script")]; - if ( - loadedScripts.find(s => { - return s.src === scriptUrl; - }) - ) { + // That's why we're using this little helper to store the ones that are in the process of loading as well + const alreadyLoadingScript = window["pieHelpers"] && window["pieHelpers"].loadingScripts[scriptUrl]; + + if (loadedScripts.find(s => (s.src === scriptUrl)) || alreadyLoadingScript) { return; } + if (window["pieHelpers"] && !window["pieHelpers"].loadingScripts[scriptUrl]) { + window["pieHelpers"].loadingScripts[scriptUrl] = true; + } + const script = options.doc.createElement("script"); const onloadFn = (_pies => { @@ -275,46 +286,54 @@ export class PieLoader { }; })(piesToLoad); - const loadScript = async () => { - try { - const response = await withRetry( - async (currentDelay: number) => { - const res = await fetch(scriptUrl); - // if the request fails with 503 retry it - if (res.status === 503) { - console.warn( - `Service unavailable (503), retrying in ${currentDelay / 1000 || + if (options.reFetchBundle) { + const loadScript = async () => { + try { + const response = await withRetry( + async (currentDelay: number) => { + const res = await fetch(scriptUrl); + // if the request fails with 503 retry it + if (res.status === 503) { + console.warn( + `Service unavailable (503), retrying in ${currentDelay / 1000 || 1} seconds...` - ); - - throw new Error("Unavailable, retrying"); - } - - return res; - }, - 20, - 1000, - 30000 - ); - - // if the request is successful inject the response as a script tag - // to avoid doing the same call twice - if (response.status === 200) { - script.onload = onloadFn; - script.src = scriptUrl; - head.appendChild(script); - } else { - console.error("Failed to load script, status code:", response.status); + ); + + throw new Error("Unavailable, retrying"); + } + + return res; + }, + 20, + 1000, + 30000 + ); + + // if the request is successful inject the response as a script tag + // to avoid doing the same call twice + if (response.status === 200) { + script.onload = onloadFn; + script.src = scriptUrl; + head.appendChild(script); + + delete window["pieHelpers"].loadingScripts[scriptUrl]; + } else { + console.error("Failed to load script, status code:", response.status); + } + } catch (error) { + console.error( + "Network error occurred while trying to load script:", + error + ); } - } catch (error) { - console.error( - "Network error occurred while trying to load script:", - error - ); - } - }; + }; - await loadScript(); + await loadScript(); + } else { + script.onload = onloadFn; + script.src = scriptUrl; + head.appendChild(script); + } }; /** diff --git a/yarn.lock b/yarn.lock index 1c4b199..b230009 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1054,10 +1054,10 @@ resolved "https://registry.yarnpkg.com/@pie-framework/pie-player-events/-/pie-player-events-0.1.0.tgz#0150904118fd604559982ab658967811c053ffe3" integrity sha512-6H1tlRGmcZ3Wt+8HMqu5KugVcwwyNrMylfI5rIpvOSt0T82QDmjRj+2sPgQG5zos/w6MtwUqn/QZ+8Rq2EXSOA== -"@pie-lib/pie-toolbox-math-rendering-module@1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@pie-lib/pie-toolbox-math-rendering-module/-/pie-toolbox-math-rendering-module-1.9.3.tgz#d7a8e537045c95b7f7766e5afb09957a2caefa26" - integrity sha512-MnAnXMoWJIvxyMEifI0zAM00F+9VRpzreB7mDOL6NpH2tb59wjm9KTZMAOux8yGZ0ikWPYlKAj96uuh7krPv+A== +"@pie-lib/pie-toolbox-math-rendering-module@1.21.0-beta.0": + version "1.21.0-beta.0" + resolved "https://registry.yarnpkg.com/@pie-lib/pie-toolbox-math-rendering-module/-/pie-toolbox-math-rendering-module-1.21.0-beta.0.tgz#e675d898ebea837fd96eb23b939d5fa6bafae2ec" + integrity sha512-rkj6EtNZo2fEOcV8soGtOeOnbxtmjJSHFJfVuiEV5sJtf5/Kjc1J2WJU7fE1tkAPumhcSW5Zq6k5ETj5k4+p5w== "@release-it/conventional-changelog@^1.0.0": version "1.1.4"