Merge branch 'MDL-83243_main' of https://github.com/sam-smucker/sam_moodle
This commit is contained in:
Vendored
+1
-1
@@ -5,6 +5,6 @@
|
||||
* @copyright 2019 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("core/network",["jquery","core/ajax","core/config","core/notification","core/str"],(function($,Ajax,Config,Notification,Str){var started=!1,warningDisplayed=!1,keepAliveFrequency=0,requestTimeout=0,keepAliveMessage=!1,sessionTimeout=!1,checkFrequency=1e3*Math.min(Config.sessiontimeout/10,600),warningLimit=Config.sessiontimeoutwarning>0?1e3*Config.sessiontimeoutwarning:2*checkFrequency,firstWait=Config.sessiontimeoutwarning>0?Math.min(1e3*(Config.sessiontimeout-Config.sessiontimeoutwarning),5*checkFrequency):5*checkFrequency,timeoutSessionExpired=function(modal){sessionTimeout=!0,warningDisplayed=!1,closeModal(modal),displaySessionExpired()},closeModal=function(modal){modal.destroy()},displaySessionExpired=function(){return Ajax.call([{methodname:"core_session_time_remaining",args:{}}],!0,!0,!0)[0].then((function(args){return!(1e3*args.timeremaining>warningLimit)&&Str.get_strings([{key:"sessionexpired",component:"error"},{key:"sessionerroruser",component:"error"},{key:"loginagain",component:"moodle"},{key:"cancel",component:"moodle"}]).then((function(strings){return Notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){return location.reload(),!0})),!0})).catch(Notification.exception)}))},touchSession=function(){return sessionTimeout?displaySessionExpired():Ajax.call([{methodname:"core_session_touch",args:{}}],!0,!0,!1,requestTimeout)[0].then((function(){return keepAliveFrequency>0&&setTimeout(touchSession,keepAliveFrequency),!0})).catch((function(){Notification.alert("",keepAliveMessage)}))},checkSession=function(){return sessionTimeout=!1,Ajax.call([{methodname:"core_session_time_remaining",args:{}}],!0,!0,!0)[0].then((function(args){return!(args.userid<=0)&&(args.timeremaining<=0?displaySessionExpired():(1e3*args.timeremaining<=warningLimit&&!warningDisplayed?(warningDisplayed=!0,Str.get_strings([{key:"norecentactivity",component:"moodle"},{key:"sessiontimeoutsoon",component:"moodle"},{key:"extendsession",component:"moodle"},{key:"cancel",component:"moodle"}]).then((function(strings){return Notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){return touchSession(),warningDisplayed=!1,setTimeout(checkSession,firstWait),!0}),(function(){setTimeout(checkSession,checkFrequency)}))})).then((modal=>{setTimeout(timeoutSessionExpired,1e3*args.timeremaining,modal)})).catch(Notification.exception)):setTimeout(checkSession,checkFrequency),!0))}))},start=function(){keepAliveFrequency>0?setTimeout(touchSession,keepAliveFrequency):setTimeout(checkSession,firstWait)};const isMoodleIframe=function(){if(window.parent===window)return!1;let parentUrl;try{parentUrl=window.parent.location.href}catch(e){return!1}return parentUrl.startsWith(M.cfg.wwwroot)};return{keepalive:async function(freq,timeout,identifier,component){started?window.console.warn("Ignoring session keep-alive. The core/network module was already initialised."):(started=!0,isMoodleIframe()?window.console.warn("Ignoring session keep-alive in this iframe inside another Moodle page."):(window.console.log("Starting Moodle session keep-alive."),keepAliveFrequency=1e3*freq,keepAliveMessage=await Str.get_string(identifier,component),requestTimeout=1e3*timeout,start()))},init:function(){started||(started=!0,isMoodleIframe()?window.console.log("Not starting Moodle session timeout warning in this iframe."):(window.console.log("Starting Moodle session timeout warning."),start()))}}}));
|
||||
define("core/network",["jquery","core/ajax","core/config","core/notification","core/str","core/modal_save_cancel","core/modal_events","core/network_events"],(function($,Ajax,Config,Notification,Str,SaveCancelModal,ModalEvents,NetworkEvents){var started=!1,warningDisplayed=!1,keepAliveFrequency=0,requestTimeout=0,keepAliveMessage=!1,sessionTimeout=!1,checkFrequency=1e3*Math.min(Config.sessiontimeout/10,600),warningLimit=Config.sessiontimeoutwarning>0?1e3*Config.sessiontimeoutwarning:2*checkFrequency,firstWait=Config.sessiontimeoutwarning>0?Math.min(1e3*(Config.sessiontimeout-Config.sessiontimeoutwarning),5*checkFrequency):5*checkFrequency,alertModal=null,redirectUrl=null,connectionRetries=0,timeoutSessionExpired=function(modal){sessionTimeout=!0,warningDisplayed=!1,closeModal(modal),displaySessionExpired()},closeModal=function(modal){modal.destroy()},displaySessionExpired=function(){return Ajax.call([{methodname:"core_session_time_remaining",args:{}}],!0,!0,!0)[0].then((function(args){return!(1e3*args.timeremaining>warningLimit)&&Str.get_strings([{key:"sessionexpired",component:"error"},{key:"sessionerroruser",component:"error"},{key:"loginagain",component:"moodle"},{key:"cancel",component:"moodle"}]).then((function(strings){return Notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){return location.reload(),!0})),!0})).catch(Notification.exception)}))},touchSession=function(){return sessionTimeout?displaySessionExpired():Ajax.call([{methodname:"core_session_touch",args:{}}],!0,!0,!1,requestTimeout)[0].then((function(){return window.dispatchEvent(new CustomEvent(NetworkEvents.sessionTouched)),!0})).catch((function(){window.dispatchEvent(new CustomEvent(NetworkEvents.unstableConnection))}))},checkSession=function(){return sessionTimeout=!1,Ajax.call([{methodname:"core_session_time_remaining",args:{}}],!0,!0,!0)[0].then((function(args){return!(args.userid<=0)&&(args.timeremaining<=0?displaySessionExpired():(1e3*args.timeremaining<=warningLimit&&!warningDisplayed?(warningDisplayed=!0,Str.get_strings([{key:"norecentactivity",component:"moodle"},{key:"sessiontimeoutsoon",component:"moodle"},{key:"extendsession",component:"moodle"},{key:"cancel",component:"moodle"}]).then((function(strings){return Notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){return touchSession(),warningDisplayed=!1,setTimeout(checkSession,firstWait),!0}),(function(){setTimeout(checkSession,checkFrequency)}))})).then((modal=>{setTimeout(timeoutSessionExpired,1e3*args.timeremaining,modal)})).catch(Notification.exception)):setTimeout(checkSession,checkFrequency),!0))}))},start=function(){keepAliveFrequency>0?setTimeout(touchSession,keepAliveFrequency):setTimeout(checkSession,firstWait)};const isMoodleIframe=function(){if(window.parent===window)return!1;let parentUrl;try{parentUrl=window.parent.location.href}catch(e){return!1}return parentUrl.startsWith(M.cfg.wwwroot)};var leavePage=function(){"string"!=typeof redirectUrl?window.location.reload():window.location.replace(redirectUrl)},handleUnstableConnection=function(){if(connectionRetries<1)return alertModal.show(),setTimeout(touchSession,keepAliveFrequency),void connectionRetries++;null!==alertModal&&(alertModal.getRoot().find('[data-action="cancel"]').hide(),alertModal.show().then((function(){return alertModal.getRoot().on(ModalEvents.hidden,leavePage),!0})).catch(Notification.exception))},handleSessionTouched=function(){keepAliveFrequency>0&&(setTimeout(touchSession,keepAliveFrequency),connectionRetries=0)};return{keepalive:async function(freq,timeout,identifier,component){let redirect=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;if(started)window.console.warn("Ignoring session keep-alive. The core/network module was already initialised.");else if(started=!0,isMoodleIframe())window.console.warn("Ignoring session keep-alive in this iframe inside another Moodle page.");else{window.console.log("Starting Moodle session keep-alive."),keepAliveFrequency=1e3*freq,keepAliveMessage=await Str.get_string(identifier,component),requestTimeout=1e3*timeout,redirectUrl=redirect;var strings=await Str.get_strings([{key:"unstablenetwork",component:"mod_scorm"},{key:"leavepage",component:"mod_scorm"},{key:"refresh",component:"moodle"}]);(alertModal=await SaveCancelModal.create({title:strings[0],body:keepAliveMessage,buttons:{save:"string"==typeof redirectUrl?strings[1]:strings[2]},removeOnClose:!1,show:!1})).getRoot().on(ModalEvents.save,leavePage),window.addEventListener(NetworkEvents.sessionTouched,handleSessionTouched),window.addEventListener(NetworkEvents.unstableConnection,handleUnstableConnection),start()}},init:function(){started||(started=!0,isMoodleIframe()?window.console.log("Not starting Moodle session timeout warning in this iframe."):(window.console.log("Starting Moodle session timeout warning."),start()))}}}));
|
||||
|
||||
//# sourceMappingURL=network.min.js.map
|
||||
File diff suppressed because one or more lines are too long
+3
@@ -0,0 +1,3 @@
|
||||
define("core/network_events",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={sessionTouched:"network:sessiontouched",unstableConnection:"network:unstableconnection"},_exports.default}));
|
||||
|
||||
//# sourceMappingURL=network_events.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"network_events.min.js","sources":["../src/network_events.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Contains the events fired by the networking module.\n *\n * @module core/network_events\n * @copyright 2025 Sam Smucker <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n sessionTouched: 'network:sessiontouched',\n unstableConnection: 'network:unstableconnection',\n};\n"],"names":["sessionTouched","unstableConnection"],"mappings":"qKAsBe,CACXA,eAAgB,yBAChBC,mBAAoB"}
|
||||
@@ -20,8 +20,26 @@
|
||||
* @copyright 2019 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
|
||||
function($, Ajax, Config, Notification, Str) {
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/config',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/modal_save_cancel',
|
||||
'core/modal_events',
|
||||
'core/network_events',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
Ajax,
|
||||
Config,
|
||||
Notification,
|
||||
Str,
|
||||
SaveCancelModal,
|
||||
ModalEvents,
|
||||
NetworkEvents,
|
||||
) {
|
||||
|
||||
var started = false;
|
||||
var warningDisplayed = false;
|
||||
@@ -36,6 +54,12 @@ define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
|
||||
// First wait is minimum of remaining time or half of the session timeout.
|
||||
var firstWait = (Config.sessiontimeoutwarning > 0) ?
|
||||
Math.min((Config.sessiontimeout - Config.sessiontimeoutwarning) * 1000, checkFrequency * 5) : checkFrequency * 5;
|
||||
// Modal to display when the connection is unstable.
|
||||
var alertModal = null;
|
||||
// URL to redirect to if network is unstable.
|
||||
var redirectUrl = null;
|
||||
// Number of times we have tried to touch the session after a network request failure.
|
||||
var connectionRetries = 0;
|
||||
/**
|
||||
* The session time has expired - we can't extend it now.
|
||||
* @param {Modal} modal
|
||||
@@ -109,12 +133,10 @@ define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
|
||||
return displaySessionExpired();
|
||||
} else {
|
||||
return Ajax.call([request], true, true, false, requestTimeout)[0].then(function() {
|
||||
if (keepAliveFrequency > 0) {
|
||||
setTimeout(touchSession, keepAliveFrequency);
|
||||
}
|
||||
window.dispatchEvent(new CustomEvent(NetworkEvents.sessionTouched));
|
||||
return true;
|
||||
}).catch(function() {
|
||||
Notification.alert('', keepAliveMessage);
|
||||
window.dispatchEvent(new CustomEvent(NetworkEvents.unstableConnection));
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -231,6 +253,56 @@ define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
|
||||
start();
|
||||
};
|
||||
|
||||
/**
|
||||
* Leave the page, either by redirecting or reloading.
|
||||
*/
|
||||
var leavePage = function() {
|
||||
if (typeof redirectUrl === 'string') {
|
||||
window.location.replace(redirectUrl);
|
||||
return;
|
||||
}
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
/**
|
||||
* When the network connection is unstable show the user an alert.
|
||||
* If the unstable connection persists, force the user to exit the
|
||||
* current page.
|
||||
*/
|
||||
var handleUnstableConnection = function() {
|
||||
// Show the alert modal warning the user that their
|
||||
// connection is unstable but allow them to continue
|
||||
// interacting with the page if they choose.
|
||||
if (connectionRetries < 1) {
|
||||
alertModal.show();
|
||||
setTimeout(touchSession, keepAliveFrequency);
|
||||
connectionRetries++;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have failed to touch the session twice in a row,
|
||||
// show the alert modal (if not already visible) but remove
|
||||
// any option for the user to continue on this page.
|
||||
if (alertModal !== null) {
|
||||
alertModal.getRoot().find('[data-action="cancel"]').hide();
|
||||
alertModal.show().then(function() {
|
||||
alertModal.getRoot().on(ModalEvents.hidden, leavePage);
|
||||
return true;
|
||||
}).catch(Notification.exception);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* When the session is touched, set a timeout to touch it again
|
||||
* and reset the number of failed connection retries.
|
||||
*/
|
||||
var handleSessionTouched = function() {
|
||||
if (keepAliveFrequency > 0) {
|
||||
setTimeout(touchSession, keepAliveFrequency);
|
||||
connectionRetries = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Start polling with more specific values for the frequency, timeout and message.
|
||||
*
|
||||
@@ -238,8 +310,9 @@ define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
|
||||
* @param {number} timeout The time to wait for each request to the server.
|
||||
* @param {string} identifier The string identifier for the message to show if session is going to time out.
|
||||
* @param {string} component The string component for the message to show if session is going to time out.
|
||||
* @param {string|null} redirect A url to redirect to in case of a lost connection to the server.
|
||||
*/
|
||||
var keepalive = async function(freq, timeout, identifier, component) {
|
||||
var keepalive = async function(freq, timeout, identifier, component, redirect = null) {
|
||||
// We only allow one concurrent instance of this checker.
|
||||
if (started) {
|
||||
window.console.warn('Ignoring session keep-alive. The core/network module was already initialised.');
|
||||
@@ -257,6 +330,31 @@ define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
|
||||
keepAliveFrequency = freq * 1000;
|
||||
keepAliveMessage = await Str.get_string(identifier, component);
|
||||
requestTimeout = timeout * 1000;
|
||||
redirectUrl = redirect;
|
||||
|
||||
var strings = await Str.get_strings([
|
||||
{key: 'unstablenetwork', component: 'mod_scorm'},
|
||||
{key: 'leavepage', component: 'mod_scorm'},
|
||||
{key: 'refresh', component: 'moodle'},
|
||||
]);
|
||||
|
||||
alertModal = await SaveCancelModal.create({
|
||||
title: strings[0],
|
||||
body: keepAliveMessage,
|
||||
buttons: {
|
||||
save: typeof redirectUrl === 'string' ? strings[1] : strings[2],
|
||||
},
|
||||
removeOnClose: false,
|
||||
show: false
|
||||
});
|
||||
|
||||
// The save button is renamed and will redirect the user or
|
||||
// reload the page when clicked.
|
||||
alertModal.getRoot().on(ModalEvents.save, leavePage);
|
||||
|
||||
window.addEventListener(NetworkEvents.sessionTouched, handleSessionTouched);
|
||||
window.addEventListener(NetworkEvents.unstableConnection, handleUnstableConnection);
|
||||
|
||||
start();
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contains the events fired by the networking module.
|
||||
*
|
||||
* @module core/network_events
|
||||
* @copyright 2025 Sam Smucker <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
export default {
|
||||
sessionTouched: 'network:sessiontouched',
|
||||
unstableConnection: 'network:unstableconnection',
|
||||
};
|
||||
@@ -1209,9 +1209,16 @@ class manager {
|
||||
* @param string $component The string component for the message to show on failure.
|
||||
* @param int $frequency The update frequency in seconds.
|
||||
* @param int $timeout The timeout of each request in seconds.
|
||||
* @throws \coding_exception IF the frequency is longer than the session lifetime.
|
||||
* @param \moodle_url|string|null $redirect A URL to redirect to if connection is lost.
|
||||
* @throws \coding_exception If the frequency is longer than the session lifetime.
|
||||
*/
|
||||
public static function keepalive($identifier = 'sessionerroruser', $component = 'error', $frequency = null, $timeout = 0) {
|
||||
public static function keepalive(
|
||||
$identifier = 'sessionerroruser',
|
||||
$component = 'error',
|
||||
$frequency = null,
|
||||
$timeout = 0,
|
||||
$redirect = null
|
||||
) {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
if ($frequency) {
|
||||
@@ -1224,11 +1231,16 @@ class manager {
|
||||
$frequency = $CFG->sessiontimeout / 10;
|
||||
}
|
||||
|
||||
if ($redirect instanceof \moodle_url) {
|
||||
$redirect = $redirect->out();
|
||||
}
|
||||
|
||||
$PAGE->requires->js_call_amd('core/network', 'keepalive', array(
|
||||
$frequency,
|
||||
$timeout,
|
||||
$identifier,
|
||||
$component
|
||||
$component,
|
||||
$redirect,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Networking steps definitions
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2025 Sam Smucker <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../behat/behat_base.php');
|
||||
|
||||
/**
|
||||
* Steps definitions to trigger Javascript events in the network AMD module.
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2025 Sam Smucker <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_networking extends behat_base {
|
||||
/**
|
||||
* Trigger a custom Javascript event indicating network instability.
|
||||
*
|
||||
* @When my network is unstable
|
||||
*/
|
||||
public function my_network_is_unstable() {
|
||||
$this->getSession()
|
||||
->getDriver()
|
||||
->evaluateScript("window.dispatchEvent(new CustomEvent('network:unstableconnection'));");
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a custom Javascript event indicating that the session has been touched.
|
||||
*
|
||||
* @When the session is touched
|
||||
*/
|
||||
public function the_session_is_touched() {
|
||||
$this->getSession()
|
||||
->getDriver()
|
||||
->evaluateScript("window.dispatchEvent(new CustomEvent('network:sessiontouched'));");
|
||||
}
|
||||
}
|
||||
@@ -263,6 +263,7 @@ $string['lastattempt'] = 'Last completed attempt';
|
||||
$string['lastattemptlock'] = 'Lock after final attempt';
|
||||
$string['lastattemptlock_help'] = 'If enabled, a student is prevented from launching the SCORM player after using up all their allocated attempts.';
|
||||
$string['lastattemptlockdesc'] = 'If enabled, a student is prevented from launching the SCORM player after using up all their allocated attempts.';
|
||||
$string['leavepage'] = 'Leave page';
|
||||
$string['location'] = 'Show the location bar';
|
||||
$string['max'] = 'Max score';
|
||||
$string['maximumattempts'] = 'Number of attempts';
|
||||
@@ -299,8 +300,8 @@ There are 3 options:
|
||||
$string['navdesc'] = 'This setting specifies whether to show or hide navigation buttons and their position.';
|
||||
$string['navpositionleft'] = 'Position of navigation buttons from left in pixels.';
|
||||
$string['navpositiontop'] = 'Position of navigation buttons from top in pixels.';
|
||||
$string['networkdropped'] = 'The SCORM player has determined that your Internet connection is unreliable or has been interrupted. If you continue in this SCORM activity, your progress may not be saved.<br />
|
||||
You should exit the activity now, and return when you have a dependable Internet connection.';
|
||||
$string['networkdropped'] = 'It looks like you have an unstable internet connection or your session has timed out. Your progress may not be saved. Please exit and relaunch this activity.';
|
||||
$string['networkdroppedmobile'] = 'It looks like you have an unstable internet connection or your session has timed out. Your progress may not be saved. Please exit and relaunch this activity. You may wish to return to this activity in the mobile app for a more stable connection.';
|
||||
$string['newattempt'] = 'Start a new attempt';
|
||||
$string['next'] = 'Continue';
|
||||
$string['noactivity'] = 'Nothing to report';
|
||||
@@ -439,6 +440,7 @@ $string['typeexternal'] = 'External SCORM manifest';
|
||||
$string['typelocal'] = 'Uploaded package';
|
||||
$string['typelocalsync'] = 'Downloaded package';
|
||||
$string['undercontent'] = 'Under content';
|
||||
$string['unstablenetwork'] = 'Unstable network';
|
||||
$string['unziperror'] = 'An error occurs during package unzip';
|
||||
$string['updatefreq'] = 'Auto-update frequency';
|
||||
$string['updatefreq_error'] = 'Auto-update frequency can only be set when the package file is hosted externally';
|
||||
|
||||
@@ -309,7 +309,9 @@ if (file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.php'))
|
||||
}
|
||||
|
||||
// Add the keepalive system to keep checking for a connection.
|
||||
\core\session\manager::keepalive('networkdropped', 'mod_scorm', 30, 10);
|
||||
$redirecturl = new moodle_url('/mod/scorm/view.php', ['id' => $cm->id]);
|
||||
$stringname = get_config('core', 'enablemobilewebservice') ? 'networkdroppedmobile' : 'networkdropped';
|
||||
\core\session\manager::keepalive($stringname, 'mod_scorm', 30, 10, $redirecturl);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
@mod @mod_scorm
|
||||
Feature: Unstable network
|
||||
In order to avoid losing progress in a SCORM package
|
||||
As a learner
|
||||
I need to be notified if my network is unstable
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | course | name | popup |
|
||||
| scorm | C1 | Same window SCORM | 0 |
|
||||
| scorm | C1 | New window SCORM | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: The unstable network modal renders on the SCORM player page when network is unstable
|
||||
When I am on the "Same window SCORM" "scorm activity" page logged in as "student1"
|
||||
And I press "Enter"
|
||||
And my network is unstable
|
||||
Then I should see "It looks like you have an unstable internet connection or your session has timed out"
|
||||
And I should see "Cancel" in the "Unstable network" "dialogue"
|
||||
|
||||
@javascript
|
||||
Scenario: The unstable network modal can be closed without a redirect the first time it is shown
|
||||
When I am on the "Same window SCORM" "scorm activity" page logged in as "student1"
|
||||
And I press "Enter"
|
||||
And my network is unstable
|
||||
And I click on "Cancel" "button" in the "Unstable network" "dialogue"
|
||||
Then I should not see "It looks like you have an unstable internet connection or your session has timed out"
|
||||
And I should not see "Enter"
|
||||
|
||||
@javascript
|
||||
Scenario: The unstable network modal cannot be closed without a redirect the second time it is shown
|
||||
When I am on the "Same window SCORM" "scorm activity" page logged in as "student1"
|
||||
And I press "Enter"
|
||||
And my network is unstable
|
||||
And my network is unstable
|
||||
Then I should not see "Cancel" in the "Unstable network" "dialogue"
|
||||
And I click on "Leave page" "button" in the "Unstable network" "dialogue"
|
||||
And I should see "Enter"
|
||||
|
||||
@javascript
|
||||
Scenario: Unstable network must be detected twice consecutively before a user must leave the SCORM activity
|
||||
When I am on the "Same window SCORM" "scorm activity" page logged in as "student1"
|
||||
And I press "Enter"
|
||||
And my network is unstable
|
||||
And I click on "Cancel" "button" in the "Unstable network" "dialogue"
|
||||
And the session is touched
|
||||
And my network is unstable
|
||||
Then I should see "Cancel" in the "Unstable network" "dialogue"
|
||||
And my network is unstable
|
||||
And I should not see "Cancel" in the "Unstable network" "dialogue"
|
||||
|
||||
@javascript @_switch_window
|
||||
Scenario: Unstable network modal redirects correctly when SCORM opens in new window
|
||||
When I am on the "New window SCORM" "scorm activity" page logged in as "student1"
|
||||
And I press "Enter"
|
||||
And I switch to a second window
|
||||
And my network is unstable
|
||||
And I click on "Leave page" "button" in the "Unstable network" "dialogue"
|
||||
Then I should see "Enter"
|
||||
And I should see "New window SCORM"
|
||||
Reference in New Issue
Block a user