diff --git a/course/amd/build/activitychooser.min.js b/course/amd/build/activitychooser.min.js
index 929586d2f57..8d1704d5275 100644
--- a/course/amd/build/activitychooser.min.js
+++ b/course/amd/build/activitychooser.min.js
@@ -1,2 +1,2 @@
-define ("core_course/activitychooser",["exports","core_course/local/activitychooser/dialogue","core_course/local/activitychooser/repository","core_course/local/activitychooser/selectors","core/custom_interaction_events","core/templates","core/modal_factory","core/str","core/pending"],function(a,b,c,d,e,f,g,h,i){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=k(b);c=k(c);d=j(d);e=j(e);f=k(f);g=k(g);i=j(i);function j(a){return a&&a.__esModule?a:{default:a}}function k(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}function l(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function m(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){l(h,d,e,f,g,"next",a)}function g(a){l(h,d,e,f,g,"throw",a)}f(void 0)})}}var n=function(a){var b=new i.default;o(a);b.resolve()};a.init=n;var o=function(a){var f=["click",e.default.events.activate,e.default.events.keyboardActivate],g=function(){var b=null;return function(){if(!b){b=new Promise(function(b){b(c.activityModules(a))})}return b}}();e.default.define(document,f);f.forEach(function(a){document.addEventListener(a,function(){var a=m(regeneratorRuntime.mark(function a(c){var e,f,h;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:if(!c.target.closest(d.default.elements.sectionmodchooser)){a.next=12;break}e=c.target.closest(d.default.elements.sectionmodchooser);a.t0=p;a.next=5;return g();case 5:a.t1=a.sent;a.t2=e.dataset.sectionid;f=(0,a.t0)(a.t1,a.t2);a.next=10;return q(f);case 10:h=a.sent;b.displayChooser(e,h,f);case 12:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}())})},p=function(a,b){var c=JSON.parse(JSON.stringify(a));c.content_items.forEach(function(a){a.link+="§ion="+b});return c.content_items},q=function(a){return s(r(a))},r=function(a){var b=[],c=[],d=!!b.length,e=!!(c.length&&!1===d);return{default:a,favourites:b,recommended:c,favouritesFirst:d,recommendedFirst:e,fallback:!1===d&&!1===e}},s=function(a){return g.create({type:g.types.DEFAULT,title:(0,h.get_string)("addresourceoractivity"),body:f.render("core_course/chooser",a),large:!0,templateContext:{classes:"modchooser"}})}});
+define ("core_course/activitychooser",["exports","core_course/local/activitychooser/dialogue","core_course/local/activitychooser/repository","core_course/local/activitychooser/selectors","core/custom_interaction_events","core/templates","core/modal_factory","core/str","core/pending"],function(a,b,c,d,e,f,g,h,i){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=k(b);c=k(c);d=j(d);e=j(e);f=k(f);g=k(g);i=j(i);function j(a){return a&&a.__esModule?a:{default:a}}function k(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}function l(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function m(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){l(h,d,e,f,g,"next",a)}function g(a){l(h,d,e,f,g,"throw",a)}f(void 0)})}}var n=function(a){var b=new i.default;o(a);b.resolve()};a.init=n;var o=function(a){var f=["click",e.default.events.activate,e.default.events.keyboardActivate],g=function(){var b=null;return function(){if(!b){b=new Promise(function(b){b(c.activityModules(a))})}return b}}();e.default.define(document,f);f.forEach(function(a){document.addEventListener(a,function(){var a=m(regeneratorRuntime.mark(function a(c){var e,f,h;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:if(!c.target.closest(d.default.elements.sectionmodchooser)){a.next=12;break}e=c.target.closest(d.default.elements.sectionmodchooser);a.t0=p;a.next=5;return g();case 5:a.t1=a.sent;a.t2=e.dataset.sectionid;f=(0,a.t0)(a.t1,a.t2);a.next=10;return q(f);case 10:h=a.sent;b.displayChooser(e,h,f);case 12:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}())})},p=function(a,b){var c=JSON.parse(JSON.stringify(a));c.content_items.forEach(function(a){a.link+="§ion="+b});return c.content_items},q=function(a){return s(r(a))},r=function(a){var b=[],c=a.filter(function(a){return!0===a.recommended}),d=!!b.length,e=!!(c.length&&!1===d);return{default:a,favourites:b,recommended:c,favouritesFirst:d,recommendedFirst:e,fallback:!1===d&&!1===e}},s=function(a){return g.create({type:g.types.DEFAULT,title:(0,h.get_string)("addresourceoractivity"),body:f.render("core_course/chooser",a),large:!0,templateContext:{classes:"modchooser"}})}});
//# sourceMappingURL=activitychooser.min.js.map
diff --git a/course/amd/build/activitychooser.min.js.map b/course/amd/build/activitychooser.min.js.map
index c5fc3dfb887..45c977bcc35 100644
--- a/course/amd/build/activitychooser.min.js.map
+++ b/course/amd/build/activitychooser.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/activitychooser.js"],"names":["init","courseId","pendingPromise","Pending","registerListenerEvents","resolve","events","CustomEvents","activate","keyboardActivate","fetchModuleData","innerPromise","Promise","Repository","activityModules","define","document","forEach","event","addEventListener","e","target","closest","selectors","elements","sectionmodchooser","caller","sectionIdMapper","dataset","sectionid","builtModuleData","modalBuilder","sectionModal","ChooserDialogue","displayChooser","webServiceData","id","newData","JSON","parse","stringify","content_items","module","link","data","buildModal","templateDataBuilder","favourites","recommended","favouritesFirst","length","recommendedFirst","fallback","ModalFactory","create","type","types","DEFAULT","title","body","Templates","render","large","templateContext","classes"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A type of dialogue used as for choosing modules in a course.\n *\n * @module core_course/activitychooser\n * @package core_course\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as ChooserDialogue from 'core_course/local/activitychooser/dialogue';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport selectors from 'core_course/local/activitychooser/selectors';\nimport CustomEvents from 'core/custom_interaction_events';\nimport * as Templates from 'core/templates';\nimport * as ModalFactory from 'core/modal_factory';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\n\n/**\n * Set up the activity chooser.\n *\n * @method init\n * @param {Number} courseId Course ID to use later on in fetchModules()\n */\nexport const init = courseId => {\n const pendingPromise = new Pending();\n\n registerListenerEvents(courseId);\n\n pendingPromise.resolve();\n};\n\n/**\n * Once a selection has been made make the modal & module information and pass it along\n *\n * @method registerListenerEvents\n * @param {Number} courseId\n */\nconst registerListenerEvents = (courseId) => {\n const events = [\n 'click',\n CustomEvents.events.activate,\n CustomEvents.events.keyboardActivate\n ];\n\n const fetchModuleData = (() => {\n let innerPromise = null;\n\n return () => {\n if (!innerPromise) {\n innerPromise = new Promise((resolve) => {\n resolve(Repository.activityModules(courseId));\n });\n }\n\n return innerPromise;\n };\n })();\n\n CustomEvents.define(document, events);\n\n // Display module chooser event listeners.\n events.forEach((event) => {\n document.addEventListener(event, async(e) => {\n if (e.target.closest(selectors.elements.sectionmodchooser)) {\n const caller = e.target.closest(selectors.elements.sectionmodchooser);\n const builtModuleData = sectionIdMapper(await fetchModuleData(), caller.dataset.sectionid);\n const sectionModal = await modalBuilder(builtModuleData);\n\n ChooserDialogue.displayChooser(caller, sectionModal, builtModuleData);\n }\n });\n });\n};\n\n/**\n * Given the web service data and an ID we want to make a deep copy\n * of the WS data then add on the section ID to the addoption URL\n *\n * @method sectionIdMapper\n * @param {Object} webServiceData Our original data from the Web service call\n * @param {Array} id The ID of the section we need to append to the links\n * @return {Array} [modules] with URL's built\n */\nconst sectionIdMapper = (webServiceData, id) => {\n // We need to take a fresh deep copy of the original data as an object is a reference type.\n const newData = JSON.parse(JSON.stringify(webServiceData));\n newData.content_items.forEach((module) => {\n module.link += '§ion=' + id;\n });\n return newData.content_items;\n};\n\n/**\n * Build a modal for each section ID and store it into a map for quick access\n *\n * @method modalBuilder\n * @param {Map} data our map of section ID's & modules to generate modals for\n * @return {Object} TODO\n */\nconst modalBuilder = data => buildModal(templateDataBuilder(data));\n\n/**\n * Given an array of modules we want to figure out where & how to place them into our template object\n *\n * @method templateDataBuilder\n * @param {Array} data our modules to manipulate into a Templatable object\n * @return {Object} Our built object ready to render out\n */\nconst templateDataBuilder = (data) => {\n // Filter the incoming data to find favourite & recommended modules.\n const favourites = [];\n const recommended = [];\n\n // Given the results of the above filters lets figure out what tab to set active.\n\n // We have some favourites.\n const favouritesFirst = !!favourites.length;\n // Check if we have no favourites but have some recommended.\n const recommendedFirst = !!(recommended.length && favouritesFirst === false);\n // We have nothing fallback to show all modules.\n const fallback = favouritesFirst === false && recommendedFirst === false;\n\n return {\n 'default': data,\n favourites: favourites,\n recommended: recommended,\n favouritesFirst: favouritesFirst,\n recommendedFirst: recommendedFirst,\n fallback: fallback,\n };\n};\n\n/**\n * Given an object we want to prebuild a modal ready to store into a map\n *\n * @method buildModal\n * @param {Object} data The template data which contains arrays of modules\n * @return {Object} The modal for the calling section with everything already set up\n */\nconst buildModal = data => {\n return ModalFactory.create({\n type: ModalFactory.types.DEFAULT,\n title: getString('addresourceoractivity'),\n body: Templates.render('core_course/chooser', data),\n large: true,\n templateContext: {\n classes: 'modchooser'\n }\n });\n};\n"],"file":"activitychooser.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/activitychooser.js"],"names":["init","courseId","pendingPromise","Pending","registerListenerEvents","resolve","events","CustomEvents","activate","keyboardActivate","fetchModuleData","innerPromise","Promise","Repository","activityModules","define","document","forEach","event","addEventListener","e","target","closest","selectors","elements","sectionmodchooser","caller","sectionIdMapper","dataset","sectionid","builtModuleData","modalBuilder","sectionModal","ChooserDialogue","displayChooser","webServiceData","id","newData","JSON","parse","stringify","content_items","module","link","data","buildModal","templateDataBuilder","favourites","recommended","filter","mod","favouritesFirst","length","recommendedFirst","fallback","ModalFactory","create","type","types","DEFAULT","title","body","Templates","render","large","templateContext","classes"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A type of dialogue used as for choosing modules in a course.\n *\n * @module core_course/activitychooser\n * @package core_course\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as ChooserDialogue from 'core_course/local/activitychooser/dialogue';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport selectors from 'core_course/local/activitychooser/selectors';\nimport CustomEvents from 'core/custom_interaction_events';\nimport * as Templates from 'core/templates';\nimport * as ModalFactory from 'core/modal_factory';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\n\n/**\n * Set up the activity chooser.\n *\n * @method init\n * @param {Number} courseId Course ID to use later on in fetchModules()\n */\nexport const init = courseId => {\n const pendingPromise = new Pending();\n\n registerListenerEvents(courseId);\n\n pendingPromise.resolve();\n};\n\n/**\n * Once a selection has been made make the modal & module information and pass it along\n *\n * @method registerListenerEvents\n * @param {Number} courseId\n */\nconst registerListenerEvents = (courseId) => {\n const events = [\n 'click',\n CustomEvents.events.activate,\n CustomEvents.events.keyboardActivate\n ];\n\n const fetchModuleData = (() => {\n let innerPromise = null;\n\n return () => {\n if (!innerPromise) {\n innerPromise = new Promise((resolve) => {\n resolve(Repository.activityModules(courseId));\n });\n }\n\n return innerPromise;\n };\n })();\n\n CustomEvents.define(document, events);\n\n // Display module chooser event listeners.\n events.forEach((event) => {\n document.addEventListener(event, async(e) => {\n if (e.target.closest(selectors.elements.sectionmodchooser)) {\n const caller = e.target.closest(selectors.elements.sectionmodchooser);\n const builtModuleData = sectionIdMapper(await fetchModuleData(), caller.dataset.sectionid);\n const sectionModal = await modalBuilder(builtModuleData);\n\n ChooserDialogue.displayChooser(caller, sectionModal, builtModuleData);\n }\n });\n });\n};\n\n/**\n * Given the web service data and an ID we want to make a deep copy\n * of the WS data then add on the section ID to the addoption URL\n *\n * @method sectionIdMapper\n * @param {Object} webServiceData Our original data from the Web service call\n * @param {Array} id The ID of the section we need to append to the links\n * @return {Array} [modules] with URL's built\n */\nconst sectionIdMapper = (webServiceData, id) => {\n // We need to take a fresh deep copy of the original data as an object is a reference type.\n const newData = JSON.parse(JSON.stringify(webServiceData));\n newData.content_items.forEach((module) => {\n module.link += '§ion=' + id;\n });\n return newData.content_items;\n};\n\n/**\n * Build a modal for each section ID and store it into a map for quick access\n *\n * @method modalBuilder\n * @param {Map} data our map of section ID's & modules to generate modals for\n * @return {Object} TODO\n */\nconst modalBuilder = data => buildModal(templateDataBuilder(data));\n\n/**\n * Given an array of modules we want to figure out where & how to place them into our template object\n *\n * @method templateDataBuilder\n * @param {Array} data our modules to manipulate into a Templatable object\n * @return {Object} Our built object ready to render out\n */\nconst templateDataBuilder = (data) => {\n // Filter the incoming data to find favourite & recommended modules.\n const favourites = [];\n const recommended = data.filter(mod => mod.recommended === true);\n\n // Given the results of the above filters lets figure out what tab to set active.\n\n // We have some favourites.\n const favouritesFirst = !!favourites.length;\n // Check if we have no favourites but have some recommended.\n const recommendedFirst = !!(recommended.length && favouritesFirst === false);\n // We have nothing fallback to show all modules.\n const fallback = favouritesFirst === false && recommendedFirst === false;\n\n return {\n 'default': data,\n favourites: favourites,\n recommended: recommended,\n favouritesFirst: favouritesFirst,\n recommendedFirst: recommendedFirst,\n fallback: fallback,\n };\n};\n\n/**\n * Given an object we want to prebuild a modal ready to store into a map\n *\n * @method buildModal\n * @param {Object} data The template data which contains arrays of modules\n * @return {Object} The modal for the calling section with everything already set up\n */\nconst buildModal = data => {\n return ModalFactory.create({\n type: ModalFactory.types.DEFAULT,\n title: getString('addresourceoractivity'),\n body: Templates.render('core_course/chooser', data),\n large: true,\n templateContext: {\n classes: 'modchooser'\n }\n });\n};\n"],"file":"activitychooser.min.js"}
\ No newline at end of file
diff --git a/course/amd/src/activitychooser.js b/course/amd/src/activitychooser.js
index 2e5ecfc99d2..709cd9160b8 100644
--- a/course/amd/src/activitychooser.js
+++ b/course/amd/src/activitychooser.js
@@ -125,7 +125,7 @@ const modalBuilder = data => buildModal(templateDataBuilder(data));
const templateDataBuilder = (data) => {
// Filter the incoming data to find favourite & recommended modules.
const favourites = [];
- const recommended = [];
+ const recommended = data.filter(mod => mod.recommended === true);
// Given the results of the above filters lets figure out what tab to set active.
diff --git a/course/tests/behat/activity_chooser.feature b/course/tests/behat/activity_chooser.feature
index b8be7a9b7f2..9fdf2af1fbe 100644
--- a/course/tests/behat/activity_chooser.feature
+++ b/course/tests/behat/activity_chooser.feature
@@ -54,8 +54,17 @@ Feature: Display and choose from the available activities in course
And "Back" "button" should not exist in the "modules" "core_course > Activity chooser screen"
And I should not see "The assignment activity module enables a teacher to communicate tasks, collect work and provide grades and feedback." in the "Add an activity or resource" "dialogue"
- # Currently stubbed out in MDL-67321 as further issues will add more tabs.
- Scenario: Navigate between module tabs
- Given I open the activity chooser
- And I should see "Activities" in the "Add an activity or resource" "dialogue"
- Then I should see "Forum" in the "default" "core_course > Activity chooser tab"
+ Scenario: View recommended activities
+ When I log out
+ And I log in as "admin"
+ And I am on site homepage
+ And I navigate to "Courses > Recommended activities" in site administration
+ And I click on ".activity-recommend-checkbox" "css_element" in the "Book" "table_row"
+ # Setup done, lets check it works with a teacher.
+ And I log out
+ And I log in as "teacher"
+ And I am on "Course" course homepage with editing mode on
+ And I open the activity chooser
+ Then I should see "Recommended" in the "Add an activity or resource" "dialogue"
+ And I click on "Recommended" "link" in the "Add an activity or resource" "dialogue"
+ And I should see "Book" in the "recommended" "core_course > Activity chooser tab"