From 580681ce3ca4e458390ed4642361ece150dcdd60 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 24 May 2019 10:21:21 +0100 Subject: [PATCH 01/15] Cross-framework import support --- frontend/src/modules/frameworkImport/index.js | 2 +- .../frameworkImport/less/frameworkImport.less | 56 ++++ .../templates/frameworkImport.hbs | 17 +- .../frameworkImportPluginHeadingView.hbs | 20 ++ .../templates/frameworkImportPluginView.hbs | 16 ++ .../templates/frameworkImportSidebar.hbs | 2 +- .../views/frameworkImportPluginHeadingView.js | 12 + .../views/frameworkImportPluginView.js | 21 ++ .../views/frameworkImportSidebarView.js | 12 +- .../views/frameworkImportView.js | 112 +++++++- lib/outputmanager.js | 2 +- plugins/output/adapt/helpers.js | 95 +++++-- plugins/output/adapt/importsource.js | 220 ++++------------ plugins/output/adapt/importsourcecheck.js | 243 ++++++++++++++++++ plugins/output/adapt/index.js | 1 + routes/import/index.js | 18 +- routes/lang/en-application.json | 16 ++ 17 files changed, 655 insertions(+), 210 deletions(-) create mode 100644 frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs create mode 100644 frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs create mode 100644 frontend/src/modules/frameworkImport/views/frameworkImportPluginHeadingView.js create mode 100644 frontend/src/modules/frameworkImport/views/frameworkImportPluginView.js create mode 100644 plugins/output/adapt/importsourcecheck.js diff --git a/frontend/src/modules/frameworkImport/index.js b/frontend/src/modules/frameworkImport/index.js index 0f9dd05280..0f552fa46a 100644 --- a/frontend/src/modules/frameworkImport/index.js +++ b/frontend/src/modules/frameworkImport/index.js @@ -12,7 +12,7 @@ define(function(require) { Origin.permissions.addRoute('frameworkImport', data.featurePermissions); }); - Origin.on('router:frameworkImport', function(location, subLocation, action) { + Origin.on('router:frameworkImport', function() { Origin.contentPane.setView(FrameworkImportView, { model: new Backbone.Model({ globalData: data }) }); Origin.sidebar.addView(new FrameworkImportSidebarView().$el); }); diff --git a/frontend/src/modules/frameworkImport/less/frameworkImport.less b/frontend/src/modules/frameworkImport/less/frameworkImport.less index ccab821093..3e645b195f 100644 --- a/frontend/src/modules/frameworkImport/less/frameworkImport.less +++ b/frontend/src/modules/frameworkImport/less/frameworkImport.less @@ -1,5 +1,8 @@ @import 'colours'; @import 'sharedStyles'; +@framework-import-red: #ff3343; +@framework-import-amber: #ffa340; +@framework-import-green: @secondary-color; .frameworkImport .inner { .form-container-style; @@ -26,6 +29,15 @@ } } + .col-row { + display: flex; + align-items: center; + } + + .tb-row .tb-col-inner { + padding: 0; + } + li { margin-left: 0; list-style: none; @@ -43,4 +55,48 @@ padding-bottom: 5px; } } + + &.import-summary { + .title { + font-style: italic; + padding-bottom: 10px; + color: @primary-color; + + &.red { + color: @framework-import-red; + } + + &.amber { + color: @framework-import-amber; + } + + &.green { + color: @framework-import-green; + } + } + .description { + font-weight: 600; + } + } + + &.plugin-list { + .status { + padding: 10px 0; + border-radius: 3px; + color: white; + font-weight: 600; + } + + &.red .status { + background-color: @framework-import-red; + } + + &.amber .status { + background-color: @framework-import-amber; + } + + &.green .status { + background-color: @framework-import-green; + } + } } diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs index 991bbaeed0..3a3a21d4f1 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs @@ -1,5 +1,5 @@ -
-
+
+
+ + \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs new file mode 100644 index 0000000000..ca80643bbe --- /dev/null +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs @@ -0,0 +1,20 @@ +
+ +
+

{{t 'app.name'}}

+
+ +
+

{{t 'app.currentversion'}}

+
+ +
+

{{t 'app.newversion'}}

+
+ +
+

{{t 'app.status'}}

+
+ +
+
    \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs new file mode 100644 index 0000000000..706e8f672e --- /dev/null +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs @@ -0,0 +1,16 @@ +
    +
    +
    + {{displayName}} +
    +
    + {{currentVersion}} +
    +
    + {{newVersion}} +
    +
    + {{status}} +
    +
    +
    \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportSidebar.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportSidebar.hbs index 347ad4e24b..3685c98744 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportSidebar.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportSidebar.hbs @@ -1,6 +1,6 @@
    - - - +
    \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs index ca80643bbe..ae8b901490 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs @@ -1,15 +1,15 @@
    -
    +

    {{t 'app.name'}}

    -
    -

    {{t 'app.currentversion'}}

    +
    +

    {{t 'app.importversion'}}

    -
    -

    {{t 'app.newversion'}}

    +
    +

    {{t 'app.atversion'}}

    diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs index 706e8f672e..db5752334f 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs @@ -1,13 +1,13 @@
    -
    -
    +
    +
    {{displayName}}
    -
    - {{currentVersion}} +
    + {{importVersion}}
    -
    - {{newVersion}} +
    + {{authoringToolVersion}}
    {{status}} diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index db83948f0a..8092afbf66 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -78,20 +78,6 @@ define(function(require){ this.sidebarView.$('.framework-import-sidebar-save-button').removeClass('show-details'); var $details = this.$('#import_details'); var $framework_versions = $details.find('.framework-versions'); - var categoryMap = { - 'green': { - summary: 'app.plugingreensummary', - label: 'app.plugingreenlabel' - }, - 'amber': { - summary: 'app.pluginambersummary', - label: 'app.pluginamberlabel' - }, - 'red': { - summary: 'app.pluginredsummary', - label: 'app.pluginredlabel' - } - }; if (_.isEmpty(data.pluginVersions.red)) { $('.framework-import-sidebar-save-button').addClass('save'); @@ -111,27 +97,8 @@ define(function(require){ // Can/Cannot be imported summary this.displaySummary(data); - // Plugin tables - for (var category in data.pluginVersions) { - if (category === 'white') continue; - if (_.isEmpty(data.pluginVersions[category])) continue; - - var $category_display = $details.find('.plugin-list.' + category); - $category_display.text(Origin.l10n.t(categoryMap[category].summary)); - $category_display.append(new FrameworkImportPluginHeadingView().$el); - $category_display.removeClass('display-none'); - - // Sort plugins alphabetically - var pluginArray = Object.values(data.pluginVersions[category]); - pluginArray = pluginArray.sort(function(a, b) { - return a.displayName.localeCompare(b.displayName); - }); - - pluginArray.forEach(function(plugin) { - plugin.status = Origin.l10n.t(categoryMap[category].label); - $category_display.find('.frameworkImportPlugin-plugins').append(new FrameworkImportPluginView({ data: plugin }).$el); - }); - } + // Plugin list + this.displayPluginList(data); $details.removeClass('display-none'); }, @@ -150,10 +117,11 @@ define(function(require){ $summary_title.text(Origin.l10n.t('app.coursecanbeimported')); - if (!_.isEmpty(data.pluginVersions.amber) || !_.isEmpty(data.pluginVersions.green)) { + var greenExists = !(_.isEmpty(data.pluginVersions['green-install']) && _.isEmpty(data.pluginVersions['green-update'])); + if (!_.isEmpty(data.pluginVersions.amber) || greenExists) { $summary_title.addClass('amber'); $summary_description.text(Origin.l10n.t('app.coursecanbeimporteddesc')); - if (!_.isEmpty(data.pluginVersions.green) && _.isEmpty(data.pluginVersions.amber)) { + if (greenExists && _.isEmpty(data.pluginVersions.amber)) { $summary_title.removeClass('amber').addClass('green'); } return; @@ -163,6 +131,48 @@ define(function(require){ return; }, + displayPluginList: function(data) { + var $plugin_list = this.$('#import_details').find('.plugin-list'); + var categoryMap = { + 'green-install': { + label: 'app.plugingreeninstalllabel' + }, + 'green-update': { + label: 'app.plugingreenupdatelabel' + }, + 'amber': { + label: 'app.pluginamberlabel' + }, + 'red': { + label: 'app.pluginredlabel' + } + }; + var categories = ['red', 'amber', 'green-update', 'green-install']; + + $plugin_list.append(new FrameworkImportPluginHeadingView().$el); + + for (i = 0; i < categories.length; i++) { + var categoryData = data.pluginVersions[categories[i]]; + if (categories[i] === 'white') continue; + if (_.isEmpty(categoryData)) continue; + + // Sort plugins alphabetically + var pluginArray = Object.values(categoryData); + pluginArray = pluginArray.sort(function(a, b) { + return a.displayName.localeCompare(b.displayName); + }); + + pluginArray.forEach(function(plugin) { + plugin.status = Origin.l10n.t(categoryMap[categories[i]].label); + plugin.category = categories[i]; + $plugin_list.find('.frameworkImportPlugin-plugins').append(new FrameworkImportPluginView({ data: plugin }).$el); + }); + + $plugin_list.removeClass('display-none'); + $plugin_list.find('.key-field.'+ categories[i]).removeClass('display-none'); + } + }, + goBack: function() { Origin.router.navigateToHome(); }, @@ -214,6 +224,8 @@ define(function(require){ }, completeImport: function() { + this.sidebarView.updateButton('.framework-import-sidebar-save-button', Origin.l10n.t('app.importing')); + this.$('form.frameworkImportDetails').ajaxSubmit({ error: _.bind(this.onAjaxError, this), success: _.bind(this.onFormSubmitSuccess, this) diff --git a/plugins/output/adapt/helpers.js b/plugins/output/adapt/helpers.js index bc92c8a2f7..def9c0419e 100644 --- a/plugins/output/adapt/helpers.js +++ b/plugins/output/adapt/helpers.js @@ -247,9 +247,9 @@ function getPluginFrameworkVersionCategory(serverFrameworkVersion, pluginMetaDat if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { includePrerelease: true })) { - return cb(null, {category: 'green', newVersion: pluginMetaData.version}); + return cb(null, {category: 'green-install', authoringToolVersion: app.polyglot.t('app.none')}); } - cb(null, {category: 'red', newVersion: app.polyglot.t('app.na')}); + cb(null, {category: 'red', authoringToolVersion: app.polyglot.t('app.none')}); } else { // A version is already installed so could be: // White - same version installed as in course @@ -259,14 +259,14 @@ function getPluginFrameworkVersionCategory(serverFrameworkVersion, pluginMetaDat var serverPluginVersion = semver.clean(serverPlugin.version); var isServerVersionLatest = semver.compare(serverPluginVersion, pluginMetaData.version); if (isServerVersionLatest === 0) { - return cb(null, {category: 'white', newVersion: app.polyglot.t('app.na')}); + return cb(null, {category: 'white', authoringToolVersion: app.polyglot.t('app.none')}); } if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { includePrerelease: true }) && isServerVersionLatest < 0) { - return cb(null, {category: 'green', newVersion: pluginMetaData.version}); + return cb(null, {category: 'green-update', authoringToolVersion: serverPluginVersion}); } - cb(null, {category: 'amber', newVersion: serverPluginVersion}); + cb(null, {category: 'amber', authoringToolVersion: serverPluginVersion}); } } ], function(error, category) { diff --git a/plugins/output/adapt/importsourcecheck.js b/plugins/output/adapt/importsourcecheck.js index ef5dc485f2..438ca60ca3 100644 --- a/plugins/output/adapt/importsourcecheck.js +++ b/plugins/output/adapt/importsourcecheck.js @@ -44,7 +44,8 @@ function ImportSourceCheck(req, done) { frameworkVersions: {}, pluginVersions : { white: {}, - green: {}, + 'green-install': {}, + 'green-update': {}, amber: {}, red: {} } @@ -213,7 +214,7 @@ function ImportSourceCheck(req, done) { fs.readJSON(path.join(pluginData.location, Constants.Filenames.Bower), function(error, data) { if (error) return callback(error); helpers.getPluginFrameworkVersionCategory(details.frameworkVersions.installed, data, pluginData.type, function (error, result) { - details.pluginVersions[result.category][data.name] = { currentVersion: data.version, displayName: data.displayName, newVersion: result.newVersion }; + details.pluginVersions[result.category][data.name] = { importVersion: data.version, displayName: data.displayName, authoringToolVersion: result.authoringToolVersion }; pluginData.name = data.name; cb2(); }); diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 38c290bfba..ebe6d0b78b 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -337,7 +337,7 @@ "app.emaillogotext": "ADAPT", "app.emailfooter": "Sent by Adapt Learning.", "app.importing": "Importing...", - "app.na": "N/A", + "app.none": "None", "app.importframeworkfileuploaded": "File has been uploaded", "app.importerrortitle": "Course import failed", "app.importcoursesuccess": "Course imported successfully!", @@ -358,15 +358,17 @@ "app.coursecanbeimporteddesc": "One of more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", "app.coursecannotbeimported": "Course cannot be imported", "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course is not compatible with the version of the Framework that is used by this Authoring Tool. Please remove or update these plugins and try again.", - "app.currentversion": "Current Version", - "app.newversion": "New Version", + "app.importversion": "Import Version", + "app.atversion": "Authoring Tool Version", "app.status": "Status", - "app.plugingreensummary": "The following plugins will be installed or updated in the authoring tool.", - "app.plugingreenlabel": "Compatible", - "app.pluginambersummary": "The following plugins are not supported in this authoring tool. Compatible versions of these plugins have already been installed so your course will be updated to use the compatible versions.", - "app.pluginamberlabel": "Outdated", - "app.pluginredsummary": "The following plugins are not supported in this authoring tool. You must remove or update these plugins before you can continue with the import.", - "app.pluginredlabel": "Incompatible", + "app.plugingreeninstalllabel": "Install", + "app.plugingreenupdatelabel": "Update", + "app.pluginamberlabel": "Use installed version", + "app.pluginredlabel": "Action Needed", + "app.plugingreeninstallkey": "These plugins will be installed into the Authoring Tool during import.", + "app.plugingreenupdatekey": "These plugins will be updated in the Authoring Tool during import.", + "app.pluginamberkey": "The version of these plugins included in this import is either not compatible with this Authoring Tool, or a newer version is already installed. The imported course will use the existing version.", + "app.pluginredkey": "These plugins are not supported in this authoring tool. You must remove or update these plugins before you can continue with the import.", "app.errorfetchingdata": "An error occured fetching data. Please try refreshing your page.", "app.backtoassets": "Back to assets", "app.newasset": "New Asset", From ea184c5ba1ddab12eee0109ec6d3f5e2576032fd Mon Sep 17 00:00:00 2001 From: nicola Date: Mon, 22 Jul 2019 16:31:20 +0100 Subject: [PATCH 03/15] Add valid semver version check --- plugins/output/adapt/helpers.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/output/adapt/helpers.js b/plugins/output/adapt/helpers.js index def9c0419e..04e834b0c1 100644 --- a/plugins/output/adapt/helpers.js +++ b/plugins/output/adapt/helpers.js @@ -240,10 +240,14 @@ function getPluginFrameworkVersionCategory(serverFrameworkVersion, pluginMetaDat db.retrieve(contentPlugin.bowerConfig.type, { name: pluginMetaData.name }, { jsonOnly: true }, cb); }, function categorisePlugin(records, cb) { + var importPluginVersionValid = semver.valid(pluginMetaData.version); if (records.length === 0) { // Not already installed so could be: - // Red - this plugin is not compatible + // Red - this plugin is not compatible or the version is invalid // Green - this plugin is compatible and will be installed + if (!importPluginVersionValid) { + return cb(null, {category: 'red', authoringToolVersion: app.polyglot.t('app.none')}); + } if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { includePrerelease: true })) { @@ -253,10 +257,14 @@ function getPluginFrameworkVersionCategory(serverFrameworkVersion, pluginMetaDat } else { // A version is already installed so could be: // White - same version installed as in course + // Red - invalid version // Amber - newer version installed and will be used in the course instead // Green - older version installed so this newer version will be upgraded in the AT var serverPlugin = records[0]; var serverPluginVersion = semver.clean(serverPlugin.version); + if (!importPluginVersionValid) { + return cb(null, {category: 'red', authoringToolVersion: serverPluginVersion}); + } var isServerVersionLatest = semver.compare(serverPluginVersion, pluginMetaData.version); if (isServerVersionLatest === 0) { return cb(null, {category: 'white', authoringToolVersion: app.polyglot.t('app.none')}); From 3fbf6ad086f0c7b1fcb173b2e26081021ecbe376 Mon Sep 17 00:00:00 2001 From: nicola Date: Wed, 24 Jul 2019 09:47:00 +0100 Subject: [PATCH 04/15] Text updates and add server plugin valid check --- .../frameworkImport/less/frameworkImport.less | 1 - .../frameworkImportPluginHeadingView.hbs | 8 +- .../templates/frameworkImportPluginView.hbs | 6 +- .../views/frameworkImportView.js | 2 +- plugins/output/adapt/helpers.js | 94 +++++++++---------- routes/lang/en-application.json | 18 ++-- 6 files changed, 64 insertions(+), 65 deletions(-) diff --git a/frontend/src/modules/frameworkImport/less/frameworkImport.less b/frontend/src/modules/frameworkImport/less/frameworkImport.less index d750499647..d352b074ec 100644 --- a/frontend/src/modules/frameworkImport/less/frameworkImport.less +++ b/frontend/src/modules/frameworkImport/less/frameworkImport.less @@ -58,7 +58,6 @@ &.import-summary { .title { - font-style: italic; padding-bottom: 10px; color: @primary-color; diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs index ae8b901490..bd11c07e78 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs @@ -1,19 +1,19 @@
    -
    +

    {{t 'app.name'}}

    -
    +

    {{t 'app.importversion'}}

    -
    +

    {{t 'app.atversion'}}

    -

    {{t 'app.status'}}

    +

    {{t 'app.action'}}

    diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs index db5752334f..1c9857b865 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs @@ -1,12 +1,12 @@
    -
    +
    {{displayName}}
    -
    +
    {{importVersion}}
    -
    +
    {{authoringToolVersion}}
    diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 8092afbf66..1f9d96b20e 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -87,7 +87,7 @@ define(function(require){ // Framework versions panel if (data.frameworkVersions.imported !== data.frameworkVersions.installed) { - $framework_versions.text(Origin.l10n.t('app.importframeworkversions', { + $framework_versions.html(Origin.l10n.t('app.importframeworkversions', { importVersion: data.frameworkVersions.imported, installedVersion: data.frameworkVersions.installed })); diff --git a/plugins/output/adapt/helpers.js b/plugins/output/adapt/helpers.js index 04e834b0c1..004981a4ab 100644 --- a/plugins/output/adapt/helpers.js +++ b/plugins/output/adapt/helpers.js @@ -229,54 +229,54 @@ function getPluginFrameworkVersionCategory(serverFrameworkVersion, pluginMetaDat var contentPlugin; async.waterfall([ - function getContentPlugin(cb) { - origin.contentmanager.getContentPlugin(type, cb); - }, - function getDB(plugin, cb) { - contentPlugin = plugin; - database.getDatabase(cb); - }, - function retrievePluginDoc(db, cb) { - db.retrieve(contentPlugin.bowerConfig.type, { name: pluginMetaData.name }, { jsonOnly: true }, cb); - }, - function categorisePlugin(records, cb) { - var importPluginVersionValid = semver.valid(pluginMetaData.version); - if (records.length === 0) { - // Not already installed so could be: - // Red - this plugin is not compatible or the version is invalid - // Green - this plugin is compatible and will be installed - if (!importPluginVersionValid) { - return cb(null, {category: 'red', authoringToolVersion: app.polyglot.t('app.none')}); - } - if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { - includePrerelease: true - })) { - return cb(null, {category: 'green-install', authoringToolVersion: app.polyglot.t('app.none')}); - } - cb(null, {category: 'red', authoringToolVersion: app.polyglot.t('app.none')}); - } else { - // A version is already installed so could be: - // White - same version installed as in course - // Red - invalid version - // Amber - newer version installed and will be used in the course instead - // Green - older version installed so this newer version will be upgraded in the AT - var serverPlugin = records[0]; - var serverPluginVersion = semver.clean(serverPlugin.version); - if (!importPluginVersionValid) { - return cb(null, {category: 'red', authoringToolVersion: serverPluginVersion}); - } - var isServerVersionLatest = semver.compare(serverPluginVersion, pluginMetaData.version); - if (isServerVersionLatest === 0) { - return cb(null, {category: 'white', authoringToolVersion: app.polyglot.t('app.none')}); - } - if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { - includePrerelease: true - }) && isServerVersionLatest < 0) { - return cb(null, {category: 'green-update', authoringToolVersion: serverPluginVersion}); - } - cb(null, {category: 'amber', authoringToolVersion: serverPluginVersion}); - } + function getContentPlugin(cb) { + origin.contentmanager.getContentPlugin(type, cb); + }, + function getDB(plugin, cb) { + contentPlugin = plugin; + database.getDatabase(cb); + }, + function retrievePluginDoc(db, cb) { + db.retrieve(contentPlugin.bowerConfig.type, { name: pluginMetaData.name }, { jsonOnly: true }, cb); + }, + function categorisePlugin(records, cb) { + var importPluginVersionValid = semver.valid(pluginMetaData.version); + if (records.length === 0) { + // Not already installed so could be: + // Red - this plugin is not compatible or the version is invalid + // Green - this plugin is compatible and will be installed + if (!importPluginVersionValid) { + return cb(null, {category: 'red', authoringToolVersion: app.polyglot.t('app.none')}); + } + if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { + includePrerelease: true + })) { + return cb(null, {category: 'green-install', authoringToolVersion: app.polyglot.t('app.none')}); + } + return cb(null, {category: 'red', authoringToolVersion: app.polyglot.t('app.none')}); + } + + // A version is already installed so could be: + // White - same version installed as in course + // Red - invalid version + // Amber - newer version installed and will be used in the course instead + // Green - older version installed so this newer version will be upgraded in the AT + var serverPlugin = records[0]; + if (!importPluginVersionValid || !semver.valid(serverPlugin.version)) { + return cb(null, {category: 'red', authoringToolVersion: serverPlugin.version}); + } + var serverPluginVersion = semver.clean(serverPlugin.version); + var isServerVersionLatest = semver.compare(serverPluginVersion, pluginMetaData.version); + if (isServerVersionLatest === 0) { + return cb(null, {category: 'white', authoringToolVersion: app.polyglot.t('app.none')}); } + if (semver.satisfies(serverFrameworkVersion, pluginFrameworkVersion, { + includePrerelease: true + }) && isServerVersionLatest < 0) { + return cb(null, {category: 'green-update', authoringToolVersion: serverPluginVersion}); + } + cb(null, {category: 'amber', authoringToolVersion: serverPluginVersion}); + } ], function(error, category) { return callback(error, category); }); diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index ebe6d0b78b..1d9252e2f1 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -352,23 +352,23 @@ "app.importassetfolderstitle": "Asset Folders", "app.importassetfoldersplaceholder": "assets, images, video, audio", "app.importinvalidpackage": "Encountered an unexpected file structure. Please check you have uploaded a valid export package and try again.", - "app.importframeworkversions": "This course was built with Framework %{importVersion}, this Authoring Tool has Framework %{installedVersion} installed. If you proceed with this import then your course will use Framework %{installedVersion} and should be tested.", + "app.importframeworkversions": "Import framework version: %{importVersion}
    Installed framework version: %{installedVersion}

    If you proceed with this import then your course will use framework %{installedVersion} and should be tested.", "app.coursecanbeimported": "Course can be imported", - "app.coursecanbeimportedwhitedesc": "All of the plugins and the Framework version used in this course are identical to that in this Authoring Tool.", + "app.coursecanbeimportedwhitedesc": "All of the plugins and the framework version used in this course are identical to that in this authoring tool.", "app.coursecanbeimporteddesc": "One of more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", "app.coursecannotbeimported": "Course cannot be imported", - "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course is not compatible with the version of the Framework that is used by this Authoring Tool. Please remove or update these plugins and try again.", + "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course are not compatible with the version of the framework that is used by this authoring tool. Please remove or update these plugins and try again.", "app.importversion": "Import Version", - "app.atversion": "Authoring Tool Version", - "app.status": "Status", + "app.atversion": "Installed Version", + "app.action": "Action", "app.plugingreeninstalllabel": "Install", "app.plugingreenupdatelabel": "Update", "app.pluginamberlabel": "Use installed version", "app.pluginredlabel": "Action Needed", - "app.plugingreeninstallkey": "These plugins will be installed into the Authoring Tool during import.", - "app.plugingreenupdatekey": "These plugins will be updated in the Authoring Tool during import.", - "app.pluginamberkey": "The version of these plugins included in this import is either not compatible with this Authoring Tool, or a newer version is already installed. The imported course will use the existing version.", - "app.pluginredkey": "These plugins are not supported in this authoring tool. You must remove or update these plugins before you can continue with the import.", + "app.plugingreeninstallkey": "This plugin will be installed into the authoring tool during import.", + "app.plugingreenupdatekey": "This plugin will be updated in the authoring tool during import.", + "app.pluginamberkey": "The version of this plugin included in this import is either not compatible with this authoring tool, or a newer version is already installed. The imported course will use the existing version.", + "app.pluginredkey": "This plugin is not supported in this authoring tool. You must remove or update this plugin before you can continue with the import.", "app.errorfetchingdata": "An error occured fetching data. Please try refreshing your page.", "app.backtoassets": "Back to assets", "app.newasset": "New Asset", From c7401a323c33f042e1f1d5265f11e956aa56c768 Mon Sep 17 00:00:00 2001 From: canstudios-nicolaw Date: Thu, 25 Jul 2019 15:51:26 +0100 Subject: [PATCH 05/15] Apply suggestions from code review Co-Authored-By: tomgreenfield --- .../src/modules/frameworkImport/less/frameworkImport.less | 8 ++++---- routes/lang/en-application.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/modules/frameworkImport/less/frameworkImport.less b/frontend/src/modules/frameworkImport/less/frameworkImport.less index d352b074ec..af58950275 100644 --- a/frontend/src/modules/frameworkImport/less/frameworkImport.less +++ b/frontend/src/modules/frameworkImport/less/frameworkImport.less @@ -74,7 +74,7 @@ } } .description { - font-weight: 600; + font-weight: @font-weight-bold; } } @@ -91,7 +91,7 @@ } .at-version { - font-weight: 600; + font-weight: @font-weight-bold; } } @@ -101,12 +101,12 @@ } .import-version { - font-weight: 600; + font-weight: @font-weight-bold; } } .status, .key { - font-weight: 600; + font-weight: @font-weight-bold; } .key-field { diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 1d9252e2f1..9ad48e459a 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -354,7 +354,7 @@ "app.importinvalidpackage": "Encountered an unexpected file structure. Please check you have uploaded a valid export package and try again.", "app.importframeworkversions": "Import framework version: %{importVersion}
    Installed framework version: %{installedVersion}

    If you proceed with this import then your course will use framework %{installedVersion} and should be tested.", "app.coursecanbeimported": "Course can be imported", - "app.coursecanbeimportedwhitedesc": "All of the plugins and the framework version used in this course are identical to that in this authoring tool.", + "app.coursecanbeimportedwhitedesc": "All of the plugins and the framework version used in this course are identical to those in this authoring tool.", "app.coursecanbeimporteddesc": "One of more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", "app.coursecannotbeimported": "Course cannot be imported", "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course are not compatible with the version of the framework that is used by this authoring tool. Please remove or update these plugins and try again.", From fe54d981303759e0fca5d6e4e0c57b393c30de10 Mon Sep 17 00:00:00 2001 From: canstudios-nicolaw Date: Thu, 25 Jul 2019 16:21:43 +0100 Subject: [PATCH 06/15] Apply suggestions from code review Co-Authored-By: tomgreenfield --- .../src/modules/frameworkImport/views/frameworkImportView.js | 2 +- plugins/output/adapt/importsourcecheck.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 1f9d96b20e..9528202c75 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -151,7 +151,7 @@ define(function(require){ $plugin_list.append(new FrameworkImportPluginHeadingView().$el); - for (i = 0; i < categories.length; i++) { + for (var i = 0, j = categories.length; i < j; i++) { var categoryData = data.pluginVersions[categories[i]]; if (categories[i] === 'white') continue; if (_.isEmpty(categoryData)) continue; diff --git a/plugins/output/adapt/importsourcecheck.js b/plugins/output/adapt/importsourcecheck.js index 438ca60ca3..4c00db7d22 100644 --- a/plugins/output/adapt/importsourcecheck.js +++ b/plugins/output/adapt/importsourcecheck.js @@ -167,7 +167,7 @@ function ImportSourceCheck(req, done) { var assetFolderError = false; var missingFolders = []; importInfo['assetFolders'] = cleanFormAssetDirs; - for (index = 0; index < importInfo['assetFolders'].length; ++index) { + for (var i = 0, j = importInfo['assetFolders'].length; i < j; ++i) { var assetFolderPath = path.join(COURSE_JSON_PATH , COURSE_LANG, importInfo['assetFolders'][index]); if (!fs.existsSync(assetFolderPath)) { assetFolderError = true; From ce4cc59624ecd83f4e8ec77b29e8eb8bf17c97d7 Mon Sep 17 00:00:00 2001 From: nicola Date: Thu, 25 Jul 2019 16:25:41 +0100 Subject: [PATCH 07/15] Tweaks in response to PR comments --- .../views/frameworkImportView.js | 32 +++++++++---------- plugins/output/adapt/importsourcecheck.js | 4 +-- routes/lang/en-application.json | 1 + 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 1f9d96b20e..9dacb6cddb 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -12,8 +12,10 @@ define(function(require){ preRender: function() { Origin.trigger('location:title:update', { title: Origin.l10n.t('app.frameworkimporttitle') }); - this.listenTo(Origin, 'frameworkImport:showDetails', this.showDetails); - this.listenTo(Origin, 'frameworkImport:completeImport', this.completeImport); + this.listenTo(Origin, { + 'frameworkImport:showDetails': this.showDetails, + 'frameworkImport:completeImport': this.completeImport + }); }, postRender: function() { @@ -66,8 +68,8 @@ define(function(require){ $('.progress-percent').html(percentVal); }, - error: _.bind(this.onAjaxError, this), - success: _.bind(this.displayDetails, this) + error: this.onAjaxError.bind(this), + success: this.displayDetails.bind(this) }); return false; @@ -77,7 +79,7 @@ define(function(require){ this.$('#import_upload').addClass('display-none'); this.sidebarView.$('.framework-import-sidebar-save-button').removeClass('show-details'); var $details = this.$('#import_details'); - var $framework_versions = $details.find('.framework-versions'); + var $frameworkVersions = $details.find('.framework-versions'); if (_.isEmpty(data.pluginVersions.red)) { $('.framework-import-sidebar-save-button').addClass('save'); @@ -87,11 +89,10 @@ define(function(require){ // Framework versions panel if (data.frameworkVersions.imported !== data.frameworkVersions.installed) { - $framework_versions.html(Origin.l10n.t('app.importframeworkversions', { + $frameworkVersions.html(Origin.l10n.t('app.importframeworkversions', { importVersion: data.frameworkVersions.imported, installedVersion: data.frameworkVersions.installed - })); - $framework_versions.removeClass('display-none'); + })).removeClass('display-none'); } // Can/Cannot be imported summary @@ -118,17 +119,16 @@ define(function(require){ $summary_title.text(Origin.l10n.t('app.coursecanbeimported')); var greenExists = !(_.isEmpty(data.pluginVersions['green-install']) && _.isEmpty(data.pluginVersions['green-update'])); - if (!_.isEmpty(data.pluginVersions.amber) || greenExists) { - $summary_title.addClass('amber'); - $summary_description.text(Origin.l10n.t('app.coursecanbeimporteddesc')); - if (greenExists && _.isEmpty(data.pluginVersions.amber)) { - $summary_title.removeClass('amber').addClass('green'); - } + if (_.isEmpty(data.pluginVersions.amber) && !greenExists) { + $summary_description.text(Origin.l10n.t('app.coursecanbeimportedwhitedesc')); return; } - $summary_description.text(Origin.l10n.t('app.coursecanbeimportedwhitedesc')); - return; + $summary_title.addClass('amber'); + $summary_description.text(Origin.l10n.t('app.coursecanbeimporteddesc')); + if (greenExists && _.isEmpty(data.pluginVersions.amber)) { + $summary_title.removeClass('amber').addClass('green'); + } }, displayPluginList: function(data) { diff --git a/plugins/output/adapt/importsourcecheck.js b/plugins/output/adapt/importsourcecheck.js index 438ca60ca3..55d0a9cc7f 100644 --- a/plugins/output/adapt/importsourcecheck.js +++ b/plugins/output/adapt/importsourcecheck.js @@ -154,7 +154,7 @@ function ImportSourceCheck(req, done) { async.eachSeries(Object.keys(contentMap), function(type, cb2) { var jsonPath = path.join(COURSE_JSON_PATH, (type !== 'config') ? COURSE_LANG : '', `${contentMap[type] || type}.json`); if (!fs.existsSync(jsonPath)) { - return cb2(error); + return cb2(new Error(app.polyglot.t('app.errorloadfiles'))); } cb2(); }, cb); @@ -212,7 +212,7 @@ function ImportSourceCheck(req, done) { async.each(plugindata.pluginIncludes, function (pluginData, cb2) { fs.readJSON(path.join(pluginData.location, Constants.Filenames.Bower), function(error, data) { - if (error) return callback(error); + if (error) return cb2(error); helpers.getPluginFrameworkVersionCategory(details.frameworkVersions.installed, data, pluginData.type, function (error, result) { details.pluginVersions[result.category][data.name] = { importVersion: data.version, displayName: data.displayName, authoringToolVersion: result.authoringToolVersion }; pluginData.name = data.name; diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 1d9252e2f1..e3ebb15e56 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -398,6 +398,7 @@ "app.component": "component", "app.addedDefault": "Add to new courses by default?", "app.errorloadconfig": "Failed to load configuration settings for %{course}", + "app.errorloadfiles": "Failed to load content files", "app.colourLabel": "Colour Label", "app.colourLabelTitle": "Colour Label", "app.colourLabelIntro": "The colours are only applied in the authoring tool and will not affect the generated course. The settings are synced with all users in the authoring tool.", From ceb7b7c1f81a996ed6c0473cd758fa6b393e8f15 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 26 Jul 2019 09:26:58 +0100 Subject: [PATCH 08/15] Convert indentation to 2 space --- .../templates/frameworkImport.hbs | 92 ++-- .../frameworkImportPluginHeadingView.hbs | 24 +- .../templates/frameworkImportPluginView.hbs | 26 +- .../views/frameworkImportPluginHeadingView.js | 14 +- .../views/frameworkImportPluginView.js | 30 +- .../views/frameworkImportView.js | 8 +- plugins/output/adapt/importsourcecheck.js | 416 +++++++++--------- 7 files changed, 305 insertions(+), 305 deletions(-) diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs index fde88116d7..ba98b8d65f 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs @@ -1,58 +1,58 @@
    -
    -
    - -
    - {{t 'app.importframeworkinstruction'}} -
    - {{#if path}} -
    - {{t 'app.importframeworkfileuploaded'}} -
    - {{else}} - - {{maxUploadSize}} -
    -
    -
    0%
    -
    +
    +
    + +
    + {{t 'app.importframeworkinstruction'}} +
    + {{#if path}} +
    + {{t 'app.importframeworkfileuploaded'}} +
    + {{else}} + + {{maxUploadSize}} +
    +
    +
    0%
    - {{/if}}
    -
    - -
    - {{t 'app.importassetfoldersinstruction'}} -
    -
    - -
    + {{/if}} +
    +
    + +
    + {{t 'app.importassetfoldersinstruction'}}
    -
    - - +
    +
    -
    +
    + + +
    + +
    \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs index bd11c07e78..93df22ecf5 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginHeadingView.hbs @@ -1,20 +1,20 @@
    -
    -

    {{t 'app.name'}}

    -
    +
    +

    {{t 'app.name'}}

    +
    -
    -

    {{t 'app.importversion'}}

    -
    +
    +

    {{t 'app.importversion'}}

    +
    -
    -

    {{t 'app.atversion'}}

    -
    +
    +

    {{t 'app.atversion'}}

    +
    -
    -

    {{t 'app.action'}}

    -
    +
    +

    {{t 'app.action'}}

    +
      \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs index 1c9857b865..debb2de04b 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImportPluginView.hbs @@ -1,16 +1,16 @@
      -
      -
      - {{displayName}} -
      -
      - {{importVersion}} -
      -
      - {{authoringToolVersion}} -
      -
      - {{status}} -
      +
      +
      + {{displayName}}
      +
      + {{importVersion}} +
      +
      + {{authoringToolVersion}} +
      +
      + {{status}} +
      +
      \ No newline at end of file diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportPluginHeadingView.js b/frontend/src/modules/frameworkImport/views/frameworkImportPluginHeadingView.js index 22566f59b9..ff66254382 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportPluginHeadingView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportPluginHeadingView.js @@ -1,12 +1,12 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require){ - var OriginView = require('core/views/originView'); + var OriginView = require('core/views/originView'); - var FrameworkImportPluginHeadingView = OriginView.extend({ - tagName: 'div' - }, { - template: 'frameworkImportPluginHeadingView' - }); + var FrameworkImportPluginHeadingView = OriginView.extend({ + tagName: 'div' + }, { + template: 'frameworkImportPluginHeadingView' + }); - return FrameworkImportPluginHeadingView; + return FrameworkImportPluginHeadingView; }); diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportPluginView.js b/frontend/src/modules/frameworkImport/views/frameworkImportPluginView.js index a2ce3ed010..ba14a6693a 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportPluginView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportPluginView.js @@ -1,21 +1,21 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require){ - var OriginView = require('core/views/originView'); + var OriginView = require('core/views/originView'); - var FrameworkImportPluginView = OriginView.extend({ - tagName: 'div', - initialize: function(options) { - this.options = options; - this.render(); - }, + var FrameworkImportPluginView = OriginView.extend({ + tagName: 'div', + initialize: function(options) { + this.options = options; + this.render(); + }, - render: function() { - var template = Handlebars.templates[this.constructor.template]; - this.$el.html(template(this.options.data)); - } - }, { - template: 'frameworkImportPluginView' - }); + render: function() { + var template = Handlebars.templates[this.constructor.template]; + this.$el.html(template(this.options.data)); + } + }, { + template: 'frameworkImportPluginView' + }); - return FrameworkImportPluginView; + return FrameworkImportPluginView; }); diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 66f3af4015..4cfae51ea5 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -89,10 +89,10 @@ define(function(require){ // Framework versions panel if (data.frameworkVersions.imported !== data.frameworkVersions.installed) { - $frameworkVersions.html(Origin.l10n.t('app.importframeworkversions', { - importVersion: data.frameworkVersions.imported, - installedVersion: data.frameworkVersions.installed - })).removeClass('display-none'); + $frameworkVersions.html(Origin.l10n.t('app.importframeworkversions', { + importVersion: data.frameworkVersions.imported, + installedVersion: data.frameworkVersions.installed + })).removeClass('display-none'); } // Can/Cannot be imported summary diff --git a/plugins/output/adapt/importsourcecheck.js b/plugins/output/adapt/importsourcecheck.js index 48027b13de..6941f944bf 100644 --- a/plugins/output/adapt/importsourcecheck.js +++ b/plugins/output/adapt/importsourcecheck.js @@ -12,228 +12,228 @@ const logger = require("../../../lib/logger"); const path = require("path"); function ImportSourceCheck(req, done) { - var contentMap = { - course: 'course', - config: 'config', - contentobject: 'contentObjects', - article: 'articles', - block: 'blocks', - component: 'components' - }; - var plugindata = { - pluginTypes: [ - { type: 'component', folder: 'components' }, - { type: 'extension', folder: 'extensions', attribute: '_extensions' }, - { type: 'menu', folder: 'menu', attribute: 'menuSettings' }, - { type: 'theme', folder: 'theme', attribute: 'themeSettings' } - ], - pluginIncludes: [], - theme: [], - menu: [] - }; - var userId = app.usermanager.getCurrentUser()._id; - var tenantId = app.usermanager.getCurrentUser().tenant._id; - var unzipFolder = tenantId + '_' + userId + '_unzipped'; - var COURSE_ROOT_FOLDER = path.join(configuration.tempDir, configuration.getConfig('masterTenantID'), Constants.Folders.Framework, Constants.Folders.AllCourses, tenantId, unzipFolder); - var COURSE_LANG; - var COURSE_JSON_PATH = path.join(COURSE_ROOT_FOLDER, Constants.Folders.Source, Constants.Folders.Course); - var IMPORT_INFO_FILE = 'importInfo.json'; - var importInfo = {}; - var cleanFormAssetDirs; - var details = { - frameworkVersions: {}, - pluginVersions : { - white: {}, - 'green-install': {}, - 'green-update': {}, - amber: {}, - red: {} - } - }; + var contentMap = { + course: 'course', + config: 'config', + contentobject: 'contentObjects', + article: 'articles', + block: 'blocks', + component: 'components' + }; + var plugindata = { + pluginTypes: [ + { type: 'component', folder: 'components' }, + { type: 'extension', folder: 'extensions', attribute: '_extensions' }, + { type: 'menu', folder: 'menu', attribute: 'menuSettings' }, + { type: 'theme', folder: 'theme', attribute: 'themeSettings' } + ], + pluginIncludes: [], + theme: [], + menu: [] + }; + var userId = app.usermanager.getCurrentUser()._id; + var tenantId = app.usermanager.getCurrentUser().tenant._id; + var unzipFolder = tenantId + '_' + userId + '_unzipped'; + var COURSE_ROOT_FOLDER = path.join(configuration.tempDir, configuration.getConfig('masterTenantID'), Constants.Folders.Framework, Constants.Folders.AllCourses, tenantId, unzipFolder); + var COURSE_LANG; + var COURSE_JSON_PATH = path.join(COURSE_ROOT_FOLDER, Constants.Folders.Source, Constants.Folders.Course); + var IMPORT_INFO_FILE = 'importInfo.json'; + var importInfo = {}; + var cleanFormAssetDirs; + var details = { + frameworkVersions: {}, + pluginVersions : { + white: {}, + 'green-install': {}, + 'green-update': {}, + amber: {}, + red: {} + } + }; - /** - * Main process - * All functions delegated below for readability - */ - async.series([ - prepareImport, - findLanguages, - validateCoursePackage, - createImportMetaData - ], (importErr) => { - if (!_.isEmpty(details.pluginVersions.red) || importErr) { - // There are red plugins so no import possible, clean up now - helpers.cleanUpImport(importInfo['cleanupDirs'], function() { - done(importErr, details); - }); - return; - } + /** + * Main process + * All functions delegated below for readability + */ + async.series([ + prepareImport, + findLanguages, + validateCoursePackage, + createImportMetaData + ], (importErr) => { + if (!_.isEmpty(details.pluginVersions.red) || importErr) { + // There are red plugins so no import possible, clean up now + helpers.cleanUpImport(importInfo['cleanupDirs'], function() { done(importErr, details); - }); - - function prepareImport(cb) { - async.parallel([ - function(cb2) { - database.getDatabase(cb2); - }, - function(cb2) { - const form = new IncomingForm(); - form.maxFileSize = configuration.getConfig('maxFileUploadSize'); - // parse the form - form.parse(req, function (error, fields, files) { - if(error) { - if (form.bytesExpected > form.maxFileSize) { - return cb2(new Error(app.polyglot.t('app.uploadsizeerror', { - max: bytes.format(form.maxFileSize), - size: bytes.format(form.bytesExpected) - }))); - } - return cb2(error); - } - var formAssetDirs = (fields.formAssetFolders && fields.formAssetFolders.length) ? fields.formAssetFolders.split(',') : []; - importInfo['formTags'] = (fields.tags && fields.tags.length) ? fields.tags.split(',') : []; - cleanFormAssetDirs = formAssetDirs.map(item => item.trim()); + }); + return; + } + done(importErr, details); + }); - // clear any previous import files - fs.emptyDir(COURSE_ROOT_FOLDER, function(error) { - if(error) return cb2(error); - // upzip the uploaded file - logger.log('info', 'unzipping'); - logger.log('info', COURSE_ROOT_FOLDER); - logger.log('info', files.file.path) - helpers.unzip(files.file.path, COURSE_ROOT_FOLDER, function(error) { - if(error) return cb2(error); - importInfo['cleanupDirs'] = [files.file.path, COURSE_ROOT_FOLDER]; - cb2(); - }); - }); - }); + function prepareImport(cb) { + async.parallel([ + function(cb2) { + database.getDatabase(cb2); + }, + function(cb2) { + const form = new IncomingForm(); + form.maxFileSize = configuration.getConfig('maxFileUploadSize'); + // parse the form + form.parse(req, function (error, fields, files) { + if(error) { + if (form.bytesExpected > form.maxFileSize) { + return cb2(new Error(app.polyglot.t('app.uploadsizeerror', { + max: bytes.format(form.maxFileSize), + size: bytes.format(form.bytesExpected) + }))); } - ], cb); - } + return cb2(error); + } + var formAssetDirs = (fields.formAssetFolders && fields.formAssetFolders.length) ? fields.formAssetFolders.split(',') : []; + importInfo['formTags'] = (fields.tags && fields.tags.length) ? fields.tags.split(',') : []; + cleanFormAssetDirs = formAssetDirs.map(item => item.trim()); - function findLanguages(cb) { - var courseLangs = []; - fs.readdir(COURSE_JSON_PATH, function (error, files) { - if (error) { - return cb(new Error(app.polyglot.t('app.importinvalidpackage'))); + // clear any previous import files + fs.emptyDir(COURSE_ROOT_FOLDER, function(error) { + if(error) return cb2(error); + // upzip the uploaded file + logger.log('info', 'unzipping'); + logger.log('info', COURSE_ROOT_FOLDER); + logger.log('info', files.file.path) + helpers.unzip(files.file.path, COURSE_ROOT_FOLDER, function(error) { + if(error) return cb2(error); + importInfo['cleanupDirs'] = [files.file.path, COURSE_ROOT_FOLDER]; + cb2(); + }); + }); + }); + } + ], cb); + } + + function findLanguages(cb) { + var courseLangs = []; + fs.readdir(COURSE_JSON_PATH, function (error, files) { + if (error) { + return cb(new Error(app.polyglot.t('app.importinvalidpackage'))); + } + files.map(function (file) { + return path.join(COURSE_JSON_PATH, file); + }).filter(function (file) { + return fs.statSync(file).isDirectory(); + }).forEach(function (file) { + courseLangs.push(path.basename(file)); + }); + COURSE_LANG = courseLangs[0] ? courseLangs[0] : 'en'; + importInfo['COURSE_LANG'] = COURSE_LANG; + cb(); + }); + } + + /** + * Checks course for any potential incompatibilities + */ + function validateCoursePackage(done) { + // - Check framework version compatibility + // - Check we have all relevant json files using contentMap + // - Check assets + // - Check plugin versions + async.auto({ + checkFramework: function(cb) { + fs.readJson(path.join(COURSE_ROOT_FOLDER, 'package.json'), function(error, versionJson) { + if(error) return cb(error); + helpers.checkFrameworkVersion(versionJson, function(error, data) { + if(error) return cb(error); + details.frameworkVersions = data; + cb(); + }); + }); + }, + checkContentJson: ['checkFramework', function(results, cb) { + async.eachSeries(Object.keys(contentMap), function(type, cb2) { + var jsonPath = path.join(COURSE_JSON_PATH, (type !== 'config') ? COURSE_LANG : '', `${contentMap[type] || type}.json`); + if (!fs.existsSync(jsonPath)) { + return cb2(new Error(app.polyglot.t('app.errorloadfiles'))); + } + cb2(); + }, cb); + }], + checkAssetFolders: ['checkContentJson', function(results, cb) { + if (!cleanFormAssetDirs.length) { + importInfo['assetFolders'] = Constants.Folders.ImportAssets; + return cb(); + } + var assetFolderError = false; + var missingFolders = []; + importInfo['assetFolders'] = cleanFormAssetDirs; + for (var i = 0, j = importInfo['assetFolders'].length; i < j; ++i) { + var assetFolderPath = path.join(COURSE_JSON_PATH , COURSE_LANG, importInfo['assetFolders'][index]); + if (!fs.existsSync(assetFolderPath)) { + assetFolderError = true; + missingFolders.push(importInfo['assetFolders'][index]); + } + } + // if a user input folder is missing log error and abort early + if (assetFolderError) { + var folderError = 'Cannot find asset folder/s ' + missingFolders.toString() + ' in framework import.'; + return cb(folderError); + } + cb(); + }], + checkPlugins: ['checkAssetFolders', function(results, cb) { + async.each(plugindata.pluginTypes, function iterator(pluginType, doneMapIterator) { + var srcDir = path.join(COURSE_ROOT_FOLDER, Constants.Folders.Source, pluginType.folder); + + if (!fs.existsSync(srcDir)) { + logger.log('info', 'No plugins found.'); + return doneMapIterator(); + } + fs.readdir(srcDir, function (err, files) { + if (err) { + return doneMapIterator(err); } files.map(function (file) { - return path.join(COURSE_JSON_PATH, file); + return path.join(srcDir, file); }).filter(function (file) { - return fs.statSync(file).isDirectory(); + return fs.statSync(file).isDirectory(); }).forEach(function (file) { - courseLangs.push(path.basename(file)); + var data = _.extend(_.clone(pluginType), { location: file }); + plugindata.pluginIncludes.push(data); }); - COURSE_LANG = courseLangs[0] ? courseLangs[0] : 'en'; - importInfo['COURSE_LANG'] = COURSE_LANG; - cb(); - }); - } - - /** - * Checks course for any potential incompatibilities - */ - function validateCoursePackage(done) { - // - Check framework version compatibility - // - Check we have all relevant json files using contentMap - // - Check assets - // - Check plugin versions - async.auto({ - checkFramework: function(cb) { - fs.readJson(path.join(COURSE_ROOT_FOLDER, 'package.json'), function(error, versionJson) { - if(error) return cb(error); - helpers.checkFrameworkVersion(versionJson, function(error, data) { - if(error) return cb(error); - details.frameworkVersions = data; - cb(); - }); - }); - }, - checkContentJson: ['checkFramework', function(results, cb) { - async.eachSeries(Object.keys(contentMap), function(type, cb2) { - var jsonPath = path.join(COURSE_JSON_PATH, (type !== 'config') ? COURSE_LANG : '', `${contentMap[type] || type}.json`); - if (!fs.existsSync(jsonPath)) { - return cb2(new Error(app.polyglot.t('app.errorloadfiles'))); - } - cb2(); - }, cb); - }], - checkAssetFolders: ['checkContentJson', function(results, cb) { - if (!cleanFormAssetDirs.length) { - importInfo['assetFolders'] = Constants.Folders.ImportAssets; - return cb(); - } - var assetFolderError = false; - var missingFolders = []; - importInfo['assetFolders'] = cleanFormAssetDirs; - for (var i = 0, j = importInfo['assetFolders'].length; i < j; ++i) { - var assetFolderPath = path.join(COURSE_JSON_PATH , COURSE_LANG, importInfo['assetFolders'][index]); - if (!fs.existsSync(assetFolderPath)) { - assetFolderError = true; - missingFolders.push(importInfo['assetFolders'][index]); - } - } - // if a user input folder is missing log error and abort early - if (assetFolderError) { - var folderError = 'Cannot find asset folder/s ' + missingFolders.toString() + ' in framework import.'; - return cb(folderError); - } - cb(); - }], - checkPlugins: ['checkAssetFolders', function(results, cb) { - async.each(plugindata.pluginTypes, function iterator(pluginType, doneMapIterator) { - var srcDir = path.join(COURSE_ROOT_FOLDER, Constants.Folders.Source, pluginType.folder); + doneMapIterator(); + }); + }, function(err) { + if(err) { + return done(err); + } - if (!fs.existsSync(srcDir)) { - logger.log('info', 'No plugins found.'); - return doneMapIterator(); - } - fs.readdir(srcDir, function (err, files) { - if (err) { - return doneMapIterator(err); - } - files.map(function (file) { - return path.join(srcDir, file); - }).filter(function (file) { - return fs.statSync(file).isDirectory(); - }).forEach(function (file) { - var data = _.extend(_.clone(pluginType), { location: file }); - plugindata.pluginIncludes.push(data); - }); - doneMapIterator(); - }); - }, function(err) { - if(err) { - return done(err); - } + importInfo['pluginIncludes'] = plugindata.pluginIncludes; - importInfo['pluginIncludes'] = plugindata.pluginIncludes; - - async.each(plugindata.pluginIncludes, function (pluginData, cb2) { - fs.readJSON(path.join(pluginData.location, Constants.Filenames.Bower), function(error, data) { - if (error) return cb2(error); - helpers.getPluginFrameworkVersionCategory(details.frameworkVersions.installed, data, pluginData.type, function (error, result) { - details.pluginVersions[result.category][data.name] = { importVersion: data.version, displayName: data.displayName, authoringToolVersion: result.authoringToolVersion }; - pluginData.name = data.name; - cb2(); - }); - }); - }, function () { - importInfo['details'] = details; - cb(); - }); - }); - }] - }, done); - } - - function createImportMetaData(cb) { - fs.outputFile(path.join(COURSE_ROOT_FOLDER, IMPORT_INFO_FILE), JSON.stringify(importInfo), function (error) { - if (error) return cb(error); + async.each(plugindata.pluginIncludes, function (pluginData, cb2) { + fs.readJSON(path.join(pluginData.location, Constants.Filenames.Bower), function(error, data) { + if (error) return cb2(error); + helpers.getPluginFrameworkVersionCategory(details.frameworkVersions.installed, data, pluginData.type, function (error, result) { + details.pluginVersions[result.category][data.name] = { importVersion: data.version, displayName: data.displayName, authoringToolVersion: result.authoringToolVersion }; + pluginData.name = data.name; + cb2(); + }); + }); + }, function () { + importInfo['details'] = details; cb(); + }); }); - } + }] + }, done); + } + + function createImportMetaData(cb) { + fs.outputFile(path.join(COURSE_ROOT_FOLDER, IMPORT_INFO_FILE), JSON.stringify(importInfo), function (error) { + if (error) return cb(error); + cb(); + }); + } } /** From 301f0a57d19ecdce016ee5470b6ba327a7a6af31 Mon Sep 17 00:00:00 2001 From: nicola Date: Mon, 29 Jul 2019 09:52:22 +0100 Subject: [PATCH 09/15] Native bind, fix loop reference, indentation --- .../frameworkImport/views/frameworkImportView.js | 8 ++++---- plugins/output/adapt/importsourcecheck.js | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 4cfae51ea5..7700949ccd 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -22,8 +22,8 @@ define(function(require){ // tagging this.$('#tags_control').tagsInput({ autocomplete_url: 'api/autocomplete/tag', - onAddTag: _.bind(this.onAddTag, this), - onRemoveTag: _.bind(this.onRemoveTag, this), + onAddTag: this.onAddTag.bind(this), + onRemoveTag: this.onRemoveTag.bind(this), 'minChars' : 3, 'maxChars' : 30 }); @@ -227,8 +227,8 @@ define(function(require){ this.sidebarView.updateButton('.framework-import-sidebar-save-button', Origin.l10n.t('app.importing')); this.$('form.frameworkImportDetails').ajaxSubmit({ - error: _.bind(this.onAjaxError, this), - success: _.bind(this.onFormSubmitSuccess, this) + error: this.onAjaxError.bind(this), + success: this.onFormSubmitSuccess.bind(this) }); } }, { diff --git a/plugins/output/adapt/importsourcecheck.js b/plugins/output/adapt/importsourcecheck.js index 6941f944bf..6e9edc8088 100644 --- a/plugins/output/adapt/importsourcecheck.js +++ b/plugins/output/adapt/importsourcecheck.js @@ -103,9 +103,9 @@ function ImportSourceCheck(req, done) { logger.log('info', files.file.path) helpers.unzip(files.file.path, COURSE_ROOT_FOLDER, function(error) { if(error) return cb2(error); - importInfo['cleanupDirs'] = [files.file.path, COURSE_ROOT_FOLDER]; - cb2(); - }); + importInfo['cleanupDirs'] = [files.file.path, COURSE_ROOT_FOLDER]; + cb2(); + }); }); }); } @@ -168,10 +168,11 @@ function ImportSourceCheck(req, done) { var missingFolders = []; importInfo['assetFolders'] = cleanFormAssetDirs; for (var i = 0, j = importInfo['assetFolders'].length; i < j; ++i) { - var assetFolderPath = path.join(COURSE_JSON_PATH , COURSE_LANG, importInfo['assetFolders'][index]); + var assetFolder = importInfo.assetFolders[i]; + var assetFolderPath = path.join(COURSE_JSON_PATH , COURSE_LANG, assetFolder); if (!fs.existsSync(assetFolderPath)) { assetFolderError = true; - missingFolders.push(importInfo['assetFolders'][index]); + missingFolders.push(assetFolder); } } // if a user input folder is missing log error and abort early From cd3e4e2a4b5cc8ca2ae941256897908823987364 Mon Sep 17 00:00:00 2001 From: nicola Date: Tue, 30 Jul 2019 10:01:13 +0100 Subject: [PATCH 10/15] Prevent framework downgrade --- .../frameworkImport/views/frameworkImportView.js | 14 ++++++++++---- plugins/output/adapt/importsourcecheck.js | 5 +++++ routes/lang/en-application.json | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 7700949ccd..10b3fa4aa9 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -81,14 +81,14 @@ define(function(require){ var $details = this.$('#import_details'); var $frameworkVersions = $details.find('.framework-versions'); - if (_.isEmpty(data.pluginVersions.red)) { + if (_.isEmpty(data.pluginVersions.red) && !data.frameworkVersions.downgrade) { $('.framework-import-sidebar-save-button').addClass('save'); } else { $('.framework-import-sidebar-save-button').remove(); } // Framework versions panel - if (data.frameworkVersions.imported !== data.frameworkVersions.installed) { + if ((data.frameworkVersions.imported !== data.frameworkVersions.installed) && !data.frameworkVersions.downgrade) { $frameworkVersions.html(Origin.l10n.t('app.importframeworkversions', { importVersion: data.frameworkVersions.imported, installedVersion: data.frameworkVersions.installed @@ -110,13 +110,19 @@ define(function(require){ var $summary_description = $details.find('.import-summary .description'); this.sidebarView.resetButtons(); + $summary_title.addClass('red').text(Origin.l10n.t('app.coursecannotbeimported')); + if (!_.isEmpty(data.pluginVersions.red)) { - $summary_title.addClass('red').text(Origin.l10n.t('app.coursecannotbeimported')); $summary_description.text(Origin.l10n.t('app.coursecannotbeimporteddesc')); return; } - $summary_title.text(Origin.l10n.t('app.coursecanbeimported')); + if (data.frameworkVersions.downgrade) { + $summary_description.text(Origin.l10n.t('app.coursecannotbeimporteddowngradedesc')); + return; + } + + $summary_title.removeClass('red').text(Origin.l10n.t('app.coursecanbeimported')); var greenExists = !(_.isEmpty(data.pluginVersions['green-install']) && _.isEmpty(data.pluginVersions['green-update'])); if (_.isEmpty(data.pluginVersions.amber) && !greenExists) { diff --git a/plugins/output/adapt/importsourcecheck.js b/plugins/output/adapt/importsourcecheck.js index 6e9edc8088..d9bc9bfcdc 100644 --- a/plugins/output/adapt/importsourcecheck.js +++ b/plugins/output/adapt/importsourcecheck.js @@ -10,6 +10,7 @@ const helpers = require('./helpers'); const IncomingForm = require('formidable').IncomingForm; const logger = require("../../../lib/logger"); const path = require("path"); +const semver = require('semver'); function ImportSourceCheck(req, done) { var contentMap = { @@ -146,6 +147,10 @@ function ImportSourceCheck(req, done) { helpers.checkFrameworkVersion(versionJson, function(error, data) { if(error) return cb(error); details.frameworkVersions = data; + if (semver.major(data.imported) > semver.major(data.installed)) { + details.frameworkVersions.downgrade = true; + return done(); + } cb(); }); }); diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 99d1055d93..6d5f64d109 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -358,6 +358,7 @@ "app.coursecanbeimporteddesc": "One of more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", "app.coursecannotbeimported": "Course cannot be imported", "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course are not compatible with the version of the framework that is used by this authoring tool. Please remove or update these plugins and try again.", + "app.coursecannotbeimporteddowngradedesc": "The framework version used in this course is newer than the framework version that is used by this authoring tool. You cannot import this course because the framework version cannot be downgraded.", "app.importversion": "Import Version", "app.atversion": "Installed Version", "app.action": "Action", From 0d094db9ff25bae52f41f3b99ffe1f710d95937c Mon Sep 17 00:00:00 2001 From: nicola Date: Wed, 31 Jul 2019 10:52:54 +0100 Subject: [PATCH 11/15] Fix typo --- routes/lang/en-application.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 6d5f64d109..1e53906d07 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -355,7 +355,7 @@ "app.importframeworkversions": "Import framework version: %{importVersion}
      Installed framework version: %{installedVersion}

      If you proceed with this import then your course will use framework %{installedVersion} and should be tested.", "app.coursecanbeimported": "Course can be imported", "app.coursecanbeimportedwhitedesc": "All of the plugins and the framework version used in this course are identical to those in this authoring tool.", - "app.coursecanbeimporteddesc": "One of more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", + "app.coursecanbeimporteddesc": "One or more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", "app.coursecannotbeimported": "Course cannot be imported", "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course are not compatible with the version of the framework that is used by this authoring tool. Please remove or update these plugins and try again.", "app.coursecannotbeimporteddowngradedesc": "The framework version used in this course is newer than the framework version that is used by this authoring tool. You cannot import this course because the framework version cannot be downgraded.", From a8ccad1e97275e81be41de00ac6f3c8b079ee984 Mon Sep 17 00:00:00 2001 From: nicola Date: Wed, 31 Jul 2019 10:53:39 +0100 Subject: [PATCH 12/15] Use lowercase --- routes/lang/en-application.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 1e53906d07..383a232896 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -365,7 +365,7 @@ "app.plugingreeninstalllabel": "Install", "app.plugingreenupdatelabel": "Update", "app.pluginamberlabel": "Use installed version", - "app.pluginredlabel": "Action Needed", + "app.pluginredlabel": "Action needed", "app.plugingreeninstallkey": "This plugin will be installed into the authoring tool during import.", "app.plugingreenupdatekey": "This plugin will be updated in the authoring tool during import.", "app.pluginamberkey": "The version of this plugin included in this import is either not compatible with this authoring tool, or a newer version is already installed. The imported course will use the existing version.", From 58f1f718ce89f18168ee61c513db0dee0b88648e Mon Sep 17 00:00:00 2001 From: nicola Date: Wed, 14 Aug 2019 09:09:15 +0100 Subject: [PATCH 13/15] Update all plugin versions matching text --- routes/lang/en-application.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/lang/en-application.json b/routes/lang/en-application.json index 383a232896..91a7bc69d6 100644 --- a/routes/lang/en-application.json +++ b/routes/lang/en-application.json @@ -354,7 +354,7 @@ "app.importinvalidpackage": "Encountered an unexpected file structure. Please check you have uploaded a valid export package and try again.", "app.importframeworkversions": "Import framework version: %{importVersion}
      Installed framework version: %{installedVersion}

      If you proceed with this import then your course will use framework %{installedVersion} and should be tested.", "app.coursecanbeimported": "Course can be imported", - "app.coursecanbeimportedwhitedesc": "All of the plugins and the framework version used in this course are identical to those in this authoring tool.", + "app.coursecanbeimportedwhitedesc": "All of the plugins used in this course are identical to those in this authoring tool.", "app.coursecanbeimporteddesc": "One or more of the plugins used in this course will be updated as part of the import process. You should test the course after the import has completed.", "app.coursecannotbeimported": "Course cannot be imported", "app.coursecannotbeimporteddesc": "One or more of the plugins used in this course are not compatible with the version of the framework that is used by this authoring tool. Please remove or update these plugins and try again.", From 65d4a4f533c22d4cef1c37be2c99949520548800 Mon Sep 17 00:00:00 2001 From: nicola Date: Thu, 15 Aug 2019 10:56:44 +0100 Subject: [PATCH 14/15] Remove leading slashes --- .../modules/frameworkImport/templates/frameworkImport.hbs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs b/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs index ba98b8d65f..4d9c383df2 100644 --- a/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs +++ b/frontend/src/modules/frameworkImport/templates/frameworkImport.hbs @@ -1,5 +1,5 @@
      -
      +
      \ No newline at end of file +
      From 027598eeedebc375c13375ecba2a35f183a8d29c Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 16 Aug 2019 09:28:27 +0100 Subject: [PATCH 15/15] Updates for IE11 & variable names --- .../views/frameworkImportView.js | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/frontend/src/modules/frameworkImport/views/frameworkImportView.js b/frontend/src/modules/frameworkImport/views/frameworkImportView.js index 10b3fa4aa9..69cb82438a 100644 --- a/frontend/src/modules/frameworkImport/views/frameworkImportView.js +++ b/frontend/src/modules/frameworkImport/views/frameworkImportView.js @@ -106,39 +106,39 @@ define(function(require){ displaySummary: function(data) { var $details = this.$('#import_details'); - var $summary_title = $details.find('.import-summary .title'); - var $summary_description = $details.find('.import-summary .description'); + var $summaryTitle = $details.find('.import-summary .title'); + var $summaryDescription = $details.find('.import-summary .description'); this.sidebarView.resetButtons(); - $summary_title.addClass('red').text(Origin.l10n.t('app.coursecannotbeimported')); + $summaryTitle.addClass('red').text(Origin.l10n.t('app.coursecannotbeimported')); if (!_.isEmpty(data.pluginVersions.red)) { - $summary_description.text(Origin.l10n.t('app.coursecannotbeimporteddesc')); + $summaryDescription.text(Origin.l10n.t('app.coursecannotbeimporteddesc')); return; } if (data.frameworkVersions.downgrade) { - $summary_description.text(Origin.l10n.t('app.coursecannotbeimporteddowngradedesc')); + $summaryDescription.text(Origin.l10n.t('app.coursecannotbeimporteddowngradedesc')); return; } - $summary_title.removeClass('red').text(Origin.l10n.t('app.coursecanbeimported')); + $summaryTitle.removeClass('red').text(Origin.l10n.t('app.coursecanbeimported')); var greenExists = !(_.isEmpty(data.pluginVersions['green-install']) && _.isEmpty(data.pluginVersions['green-update'])); if (_.isEmpty(data.pluginVersions.amber) && !greenExists) { - $summary_description.text(Origin.l10n.t('app.coursecanbeimportedwhitedesc')); + $summaryDescription.text(Origin.l10n.t('app.coursecanbeimportedwhitedesc')); return; } - $summary_title.addClass('amber'); - $summary_description.text(Origin.l10n.t('app.coursecanbeimporteddesc')); + $summaryTitle.addClass('amber'); + $summaryDescription.text(Origin.l10n.t('app.coursecanbeimporteddesc')); if (greenExists && _.isEmpty(data.pluginVersions.amber)) { - $summary_title.removeClass('amber').addClass('green'); + $summaryTitle.removeClass('amber').addClass('green'); } }, displayPluginList: function(data) { - var $plugin_list = this.$('#import_details').find('.plugin-list'); + var $pluginList = this.$('#import_details').find('.plugin-list'); var categoryMap = { 'green-install': { label: 'app.plugingreeninstalllabel' @@ -155,7 +155,7 @@ define(function(require){ }; var categories = ['red', 'amber', 'green-update', 'green-install']; - $plugin_list.append(new FrameworkImportPluginHeadingView().$el); + $pluginList.append(new FrameworkImportPluginHeadingView().$el); for (var i = 0, j = categories.length; i < j; i++) { var categoryData = data.pluginVersions[categories[i]]; @@ -163,7 +163,9 @@ define(function(require){ if (_.isEmpty(categoryData)) continue; // Sort plugins alphabetically - var pluginArray = Object.values(categoryData); + var pluginArray = Object.keys(categoryData).map(function(e) { + return categoryData[e] + }); pluginArray = pluginArray.sort(function(a, b) { return a.displayName.localeCompare(b.displayName); }); @@ -171,11 +173,11 @@ define(function(require){ pluginArray.forEach(function(plugin) { plugin.status = Origin.l10n.t(categoryMap[categories[i]].label); plugin.category = categories[i]; - $plugin_list.find('.frameworkImportPlugin-plugins').append(new FrameworkImportPluginView({ data: plugin }).$el); + $pluginList.find('.frameworkImportPlugin-plugins').append(new FrameworkImportPluginView({ data: plugin }).$el); }); - $plugin_list.removeClass('display-none'); - $plugin_list.find('.key-field.'+ categories[i]).removeClass('display-none'); + $pluginList.removeClass('display-none'); + $pluginList.find('.key-field.'+ categories[i]).removeClass('display-none'); } },