Improved error handling when upgrading content.
parent
a38a0f1253
commit
2011e856c0
|
@ -2,18 +2,18 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
|
|
||||||
(function ($) {
|
(function ($) {
|
||||||
var info, $container, librariesCache = {};
|
var info, $container, librariesCache = {};
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// Get library info
|
// Get library info
|
||||||
info = H5PIntegration.getLibraryInfo();
|
info = H5PIntegration.getLibraryInfo();
|
||||||
|
|
||||||
// Get and reset container
|
// Get and reset container
|
||||||
$container = $('#h5p-admin-container').html('<p>' + info.message + '</p>');
|
$container = $('#h5p-admin-container').html('<p>' + info.message + '</p>');
|
||||||
|
|
||||||
// Make it possible to select version
|
// Make it possible to select version
|
||||||
var $version = $(getVersionSelect(info.versions)).appendTo($container);
|
var $version = $(getVersionSelect(info.versions)).appendTo($container);
|
||||||
|
|
||||||
// Add "go" button
|
// Add "go" button
|
||||||
$('<button/>', {
|
$('<button/>', {
|
||||||
class: 'h5p-admin-upgrade-button',
|
class: 'h5p-admin-upgrade-button',
|
||||||
|
@ -23,11 +23,11 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
new ContentUpgrade($version.val());
|
new ContentUpgrade($version.val());
|
||||||
}
|
}
|
||||||
}).appendTo($container);
|
}).appendTo($container);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate html for version select.
|
* Generate html for version select.
|
||||||
*
|
*
|
||||||
* @param {Object} versions
|
* @param {Object} versions
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
@ -41,18 +41,18 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private. Helps process each property on the given object asynchronously in serial order.
|
* Private. Helps process each property on the given object asynchronously in serial order.
|
||||||
*
|
*
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
* @param {Function} process
|
* @param {Function} process
|
||||||
* @param {Function} finished
|
* @param {Function} finished
|
||||||
*/
|
*/
|
||||||
var asyncSerial = function (obj, process, finished) {
|
var asyncSerial = function (obj, process, finished) {
|
||||||
var id, isArray = obj instanceof Array;
|
var id, isArray = obj instanceof Array;
|
||||||
|
|
||||||
// Keep track of each property that belongs to this object.
|
// Keep track of each property that belongs to this object.
|
||||||
if (!isArray) {
|
if (!isArray) {
|
||||||
var ids = [];
|
var ids = [];
|
||||||
for (id in obj) {
|
for (id in obj) {
|
||||||
|
@ -61,9 +61,9 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var i = -1; // Keeps track of the current property
|
var i = -1; // Keeps track of the current property
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private. Process the next property
|
* Private. Process the next property
|
||||||
*/
|
*/
|
||||||
|
@ -71,10 +71,10 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
id = isArray ? i : ids[i];
|
id = isArray ? i : ids[i];
|
||||||
process(id, obj[id], check);
|
process(id, obj[id], check);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private. Check if we're done or have an error.
|
* Private. Check if we're done or have an error.
|
||||||
*
|
*
|
||||||
* @param {String} err
|
* @param {String} err
|
||||||
*/
|
*/
|
||||||
var check = function (err) {
|
var check = function (err) {
|
||||||
|
@ -89,13 +89,13 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
check(); // Start
|
check(); // Start
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make it easy to keep track of version details.
|
* Make it easy to keep track of version details.
|
||||||
*
|
*
|
||||||
* @param {String} version
|
* @param {String} version
|
||||||
* @param {Number} libraryId
|
* @param {Number} libraryId
|
||||||
* @returns {_L1.Version}
|
* @returns {_L1.Version}
|
||||||
|
@ -103,19 +103,19 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
function Version(version, libraryId) {
|
function Version(version, libraryId) {
|
||||||
if (libraryId !== undefined) {
|
if (libraryId !== undefined) {
|
||||||
version = info.versions[libraryId];
|
version = info.versions[libraryId];
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
this.libraryId = libraryId;
|
this.libraryId = libraryId;
|
||||||
}
|
}
|
||||||
var versionSplit = version.split('.', 3);
|
var versionSplit = version.split('.', 3);
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
this.major = versionSplit[0];
|
this.major = versionSplit[0];
|
||||||
this.minor = versionSplit[1];
|
this.minor = versionSplit[1];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public. Custom string for this object.
|
* Public. Custom string for this object.
|
||||||
*
|
*
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
this.toString = function () {
|
this.toString = function () {
|
||||||
|
@ -125,17 +125,17 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a throbber in the status field.
|
* Displays a throbber in the status field.
|
||||||
*
|
*
|
||||||
* @param {String} msg
|
* @param {String} msg
|
||||||
* @returns {_L1.Throbber}
|
* @returns {_L1.Throbber}
|
||||||
*/
|
*/
|
||||||
function Throbber(msg) {
|
function Throbber(msg) {
|
||||||
var $throbber = H5PUtils.throbber(msg);
|
var $throbber = H5PUtils.throbber(msg);
|
||||||
$container.html('').append($throbber);
|
$container.html('').append($throbber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes it possible to set the progress.
|
* Makes it possible to set the progress.
|
||||||
*
|
*
|
||||||
* @param {String} progress
|
* @param {String} progress
|
||||||
*/
|
*/
|
||||||
this.setProgress = function (progress) {
|
this.setProgress = function (progress) {
|
||||||
|
@ -145,16 +145,16 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a new content upgrade.
|
* Start a new content upgrade.
|
||||||
*
|
*
|
||||||
* @param {Number} libraryId
|
* @param {Number} libraryId
|
||||||
* @returns {_L1.ContentUpgrade}
|
* @returns {_L1.ContentUpgrade}
|
||||||
*/
|
*/
|
||||||
function ContentUpgrade(libraryId) {
|
function ContentUpgrade(libraryId) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// Get selected version
|
// Get selected version
|
||||||
self.version = new Version(null, libraryId);
|
self.version = new Version(null, libraryId);
|
||||||
|
|
||||||
// Create throbber with loading text and progress
|
// Create throbber with loading text and progress
|
||||||
self.throbber = new Throbber(info.inProgress.replace('%ver', self.version));
|
self.throbber = new Throbber(info.inProgress.replace('%ver', self.version));
|
||||||
|
|
||||||
|
@ -164,36 +164,36 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
token: info.token
|
token: info.token
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next batch and start processing it.
|
* Get the next batch and start processing it.
|
||||||
*
|
*
|
||||||
* @param {Object} outData
|
* @param {Object} outData
|
||||||
*/
|
*/
|
||||||
ContentUpgrade.prototype.nextBatch = function (outData) {
|
ContentUpgrade.prototype.nextBatch = function (outData) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
$.post(info.infoUrl, outData, function (inData) {
|
$.post(info.infoUrl, outData, function (inData) {
|
||||||
if (!(inData instanceof Object)) {
|
if (!(inData instanceof Object)) {
|
||||||
// Print errors from backend
|
// Print errors from backend
|
||||||
return self.setStatus(inData);
|
return self.setStatus(inData);
|
||||||
}
|
}
|
||||||
if (inData.left === 0) {
|
if (inData.left === 0) {
|
||||||
// Nothing left to process
|
// Nothing left to process
|
||||||
return self.setStatus(info.done);
|
return self.setStatus(info.done);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.left = inData.left;
|
self.left = inData.left;
|
||||||
self.token = inData.token;
|
self.token = inData.token;
|
||||||
|
|
||||||
// Start processing
|
// Start processing
|
||||||
self.processBatch(inData.params);
|
self.processBatch(inData.params);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current status message.
|
* Set current status message.
|
||||||
*
|
*
|
||||||
* @param {String} msg
|
* @param {String} msg
|
||||||
*/
|
*/
|
||||||
ContentUpgrade.prototype.setStatus = function (msg) {
|
ContentUpgrade.prototype.setStatus = function (msg) {
|
||||||
|
@ -202,28 +202,37 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the given parameters.
|
* Process the given parameters.
|
||||||
*
|
*
|
||||||
* @param {Object} parameters
|
* @param {Object} parameters
|
||||||
*/
|
*/
|
||||||
ContentUpgrade.prototype.processBatch = function (parameters) {
|
ContentUpgrade.prototype.processBatch = function (parameters) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var upgraded = {}; // Track upgraded params
|
var upgraded = {}; // Track upgraded params
|
||||||
|
|
||||||
var current = 0; // Track progress
|
var current = 0; // Track progress
|
||||||
asyncSerial(parameters, function (id, params, next) {
|
asyncSerial(parameters, function (id, params, next) {
|
||||||
|
try {
|
||||||
// Make params possible to work with
|
// Make params possible to work with
|
||||||
params = JSON.parse(params);
|
params = JSON.parse(params);
|
||||||
|
if (!(params instanceof Object)) {
|
||||||
|
throw true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (event) {
|
||||||
|
return next(info.errorContent.replace('%id', id) + ' ' + info.errorParamsBroken);
|
||||||
|
}
|
||||||
|
|
||||||
// Upgrade this content.
|
// Upgrade this content.
|
||||||
self.upgrade(info.library.name, new Version(info.library.version), self.version, params, function (err, params) {
|
self.upgrade(info.library.name, new Version(info.library.version), self.version, params, function (err, params) {
|
||||||
if (!err) {
|
if (err) {
|
||||||
upgraded[id] = JSON.stringify(params);
|
return next(info.errorContent.replace('%id', id) + ' ' + err);
|
||||||
|
|
||||||
current++;
|
|
||||||
self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %');
|
|
||||||
}
|
}
|
||||||
next(err);
|
|
||||||
|
upgraded[id] = JSON.stringify(params);
|
||||||
|
|
||||||
|
current++;
|
||||||
|
self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %');
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
|
@ -240,10 +249,10 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upgade the given content.
|
* Upgade the given content.
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {Version} oldVersion
|
* @param {Version} oldVersion
|
||||||
* @param {Version} newVersion
|
* @param {Version} newVersion
|
||||||
|
@ -253,19 +262,19 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
*/
|
*/
|
||||||
ContentUpgrade.prototype.upgrade = function (name, oldVersion, newVersion, params, next) {
|
ContentUpgrade.prototype.upgrade = function (name, oldVersion, newVersion, params, next) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// Load library details and upgrade routines
|
// Load library details and upgrade routines
|
||||||
self.loadLibrary(name, newVersion, function (err, library) {
|
self.loadLibrary(name, newVersion, function (err, library) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run upgrade routines on params
|
// Run upgrade routines on params
|
||||||
self.processParams(library, oldVersion, newVersion, params, function (err, params) {
|
self.processParams(library, oldVersion, newVersion, params, function (err, params) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if any of the sub-libraries need upgrading
|
// Check if any of the sub-libraries need upgrading
|
||||||
asyncSerial(library.semantics, function (index, field, next) {
|
asyncSerial(library.semantics, function (index, field, next) {
|
||||||
self.processField(field, params[field.name], function (err, upgradedParams) {
|
self.processField(field, params[field.name], function (err, upgradedParams) {
|
||||||
|
@ -280,24 +289,24 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load library data needed for content upgrade.
|
* Load library data needed for content upgrade.
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {Version} version
|
* @param {Version} version
|
||||||
* @param {Function} next
|
* @param {Function} next
|
||||||
*/
|
*/
|
||||||
ContentUpgrade.prototype.loadLibrary = function (name, version, next) {
|
ContentUpgrade.prototype.loadLibrary = function (name, version, next) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var key = name + '/' + version.major + '/' + version.minor;
|
var key = name + '/' + version.major + '/' + version.minor;
|
||||||
if (librariesCache[key] !== undefined) {
|
if (librariesCache[key] !== undefined) {
|
||||||
// Library has been loaded before. Return cache.
|
// Library has been loaded before. Return cache.
|
||||||
next(null, librariesCache[key]);
|
next(null, librariesCache[key]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
cache: true,
|
cache: true,
|
||||||
|
@ -306,7 +315,7 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
next(info.errorData.replace('%lib', name + ' ' + version));
|
next(info.errorData.replace('%lib', name + ' ' + version));
|
||||||
}).done(function (library) {
|
}).done(function (library) {
|
||||||
librariesCache[key] = library;
|
librariesCache[key] = library;
|
||||||
|
|
||||||
if (library.upgradesScript) {
|
if (library.upgradesScript) {
|
||||||
self.loadScript(library.upgradesScript, function (err) {
|
self.loadScript(library.upgradesScript, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -320,10 +329,10 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load script with upgrade hooks.
|
* Load script with upgrade hooks.
|
||||||
*
|
*
|
||||||
* @param {String} url
|
* @param {String} url
|
||||||
* @param {Function} next
|
* @param {Function} next
|
||||||
*/
|
*/
|
||||||
|
@ -338,10 +347,10 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run upgrade hooks on params.
|
* Run upgrade hooks on params.
|
||||||
*
|
*
|
||||||
* @param {Object} library
|
* @param {Object} library
|
||||||
* @param {Version} oldVersion
|
* @param {Version} oldVersion
|
||||||
* @param {Version} newVersion
|
* @param {Version} newVersion
|
||||||
|
@ -354,7 +363,7 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
// Upgrades script should be loaded so the upgrades should be here.
|
// Upgrades script should be loaded so the upgrades should be here.
|
||||||
return next(info.errorScript.replace('%lib', library.name + ' ' + newVersion));
|
return next(info.errorScript.replace('%lib', library.name + ' ' + newVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
// No upgrades script. Move on
|
// No upgrades script. Move on
|
||||||
return next(null, params);
|
return next(null, params);
|
||||||
}
|
}
|
||||||
|
@ -362,7 +371,7 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
// Run upgrade hooks. Start by going through major versions
|
// Run upgrade hooks. Start by going through major versions
|
||||||
asyncSerial(H5PUpgrades[library.name], function (major, minors, nextMajor) {
|
asyncSerial(H5PUpgrades[library.name], function (major, minors, nextMajor) {
|
||||||
if (major < oldVersion.major || major > newVersion.major) {
|
if (major < oldVersion.major || major > newVersion.major) {
|
||||||
// Older than the current version or newer than the selected
|
// Older than the current version or newer than the selected
|
||||||
nextMajor();
|
nextMajor();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -374,14 +383,16 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We found an upgrade hook, run it
|
// We found an upgrade hook, run it
|
||||||
if (upgrade.contentUpgrade !== undefined && typeof upgrade.contentUpgrade === 'function') {
|
var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade);
|
||||||
upgrade.contentUpgrade(params, function (err, upgradedParams) {
|
|
||||||
|
try {
|
||||||
|
unnecessaryWrapper(params, function (err, upgradedParams) {
|
||||||
params = upgradedParams;
|
params = upgradedParams;
|
||||||
nextMinor(err);
|
nextMinor(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
catch (err) {
|
||||||
nextMinor(info.errorScript.replace('%lib', library.name + ' ' + newVersion));
|
next(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, nextMajor);
|
}, nextMajor);
|
||||||
|
@ -390,27 +401,27 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
next(err, params);
|
next(err, params);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process parameter fields to find and upgrade sub-libraries.
|
* Process parameter fields to find and upgrade sub-libraries.
|
||||||
*
|
*
|
||||||
* @param {Object} field
|
* @param {Object} field
|
||||||
* @param {Object} params
|
* @param {Object} params
|
||||||
* @param {Function} next
|
* @param {Function} next
|
||||||
*/
|
*/
|
||||||
ContentUpgrade.prototype.processField = function (field, params, next) {
|
ContentUpgrade.prototype.processField = function (field, params, next) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (params === undefined) {
|
if (params === undefined) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (field.type) {
|
switch (field.type) {
|
||||||
case 'library':
|
case 'library':
|
||||||
if (params.library === undefined || params.params === undefined) {
|
if (params.library === undefined || params.params === undefined) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for available upgrades
|
// Look for available upgrades
|
||||||
var usedLib = params.library.split(' ', 2);
|
var usedLib = params.library.split(' ', 2);
|
||||||
for (var i = 0; i < field.options.length; i++) {
|
for (var i = 0; i < field.options.length; i++) {
|
||||||
|
@ -419,14 +430,14 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
if (availableLib[1] === usedLib[1]) {
|
if (availableLib[1] === usedLib[1]) {
|
||||||
return next(); // Same version
|
return next(); // Same version
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have different versions
|
// We have different versions
|
||||||
var usedVer = new Version(usedLib[1]);
|
var usedVer = new Version(usedLib[1]);
|
||||||
var availableVer = new Version(availableLib[1]);
|
var availableVer = new Version(availableLib[1]);
|
||||||
if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) {
|
if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) {
|
||||||
return next(); // Larger or same version that's available
|
return next(); // Larger or same version that's available
|
||||||
}
|
}
|
||||||
|
|
||||||
// A newer version is available, upgrade params
|
// A newer version is available, upgrade params
|
||||||
return self.upgrade(availableLib[0], usedVer, availableVer, params.params, function (err, upgraded) {
|
return self.upgrade(availableLib[0], usedVer, availableVer, params.params, function (err, upgraded) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
@ -484,4 +495,4 @@ var H5PUpgrades = H5PUpgrades || {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})(H5P.jQuery);
|
})(H5P.jQuery);
|
||||||
|
|
Loading…
Reference in New Issue