MDL-86036 course: Add gradable info to activity chooser
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
issueNumber: MDL-86036
|
||||
notes:
|
||||
core_course:
|
||||
- message: Added new `gradable` property to `core_course\local\entity\content_item`
|
||||
type: improved
|
||||
@@ -6,6 +6,6 @@ define("core_course/local/activitychooser/exporter",["exports","core/str"],(func
|
||||
* @copyright 2025 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
const activityCategories=["administration","assessment","collaboration","communication","content","interactivecontent"];let allStrings=null;loadNecessaryStrings();async function loadNecessaryStrings(){if(null!==allStrings)return allStrings;allStrings={};const stringToLoad=[{key:"all",component:"core"},{key:"favourites",component:"core"},{key:"recommended",component:"core"},{key:"recommended_help",component:"core_course"},{key:"supports",component:"core_course"},...activityCategories.map((key=>({key:"mod_purpose_"+key,component:"core_course"}))),...activityCategories.map((key=>({key:"mod_purpose_"+key+"_help",component:"core_course"})))],loadedStrings=await(0,_str.getStrings)(stringToLoad);return stringToLoad.forEach(((_ref,index)=>{let{key:key}=_ref;allStrings[key]=loadedStrings[index]})),allStrings}return _exports.default=class{getTabData(tabId,filteredModules,tabLabel){let tabHelp=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;const result={tabId:tabId,active:arguments.length>4&&void 0!==arguments[4]&&arguments[4],items:filteredModules,displayed:filteredModules.length>0,tabLabel:tabLabel};return tabHelp&&(result.tabHelp=tabHelp),result}normaliseModulesData(modulesData){if(modulesData instanceof Map)modulesData=Array.from(modulesData.values());else if(!Array.isArray(modulesData))throw new Error("Invalid modules data format. Expected an array or a Map.");return modulesData}async getModChooserTemplateData(modulesData){modulesData=this.normaliseModulesData(modulesData);const allStrings=await loadNecessaryStrings(),favouriteTab=await this.getFavouriteTabData(modulesData),tabs=[{...this.getTabData("all",modulesData,allStrings.all,null,!favouriteTab.displayed),hasSearchResults:!0},favouriteTab,{...this.getTabData("recommended",modulesData.filter((mod=>!0===mod.recommended)),allStrings.recommended,allStrings.recommended_help),separator:!0}];return activityCategories.forEach((category=>{const categoryModules=modulesData.filter((mod=>mod.purpose==category));0!==categoryModules.length&&tabs.push(this.getTabData(category,categoryModules,allStrings["mod_purpose_"+category],allStrings["mod_purpose_"+category+"_help"]))})),{modules:modulesData,tabs:tabs}}async getModuleHelpTemplateData(moduleData){const purposeKey="mod_purpose_".concat(moduleData.purpose),allStrings=await loadNecessaryStrings(),data={...moduleData};return data.details=[{label:allStrings.supports,value:allStrings[purposeKey]||""}],data}async getFavouriteTabData(modulesData){modulesData=this.normaliseModulesData(modulesData);const allStrings=await loadNecessaryStrings(),favouriteModules=modulesData.filter((mod=>!0===mod.favourite));return this.getTabData("favourites",favouriteModules,allStrings.favourites,null,favouriteModules.length>0)}getSearchResultData(resultsModulesData){return{searchresultsnumber:(resultsModulesData=this.normaliseModulesData(resultsModulesData)).length,searchresults:resultsModulesData}}countTabItems(tabData){var _tabData$items$length,_tabData$items;return null!==(_tabData$items$length=null===(_tabData$items=tabData.items)||void 0===_tabData$items?void 0:_tabData$items.length)&&void 0!==_tabData$items$length?_tabData$items$length:0}getFooterData(footerData){return{activeFooter:footerData.customfootertemplate}}},_exports.default}));
|
||||
const activityCategories=["administration","assessment","collaboration","communication","content","interactivecontent"];let allStrings=null;loadNecessaryStrings();async function loadNecessaryStrings(){if(null!==allStrings)return allStrings;allStrings={};const stringToLoad=[{key:"all",component:"core"},{key:"yes",component:"core"},{key:"no",component:"core"},{key:"favourites",component:"core"},{key:"recommended",component:"core"},{key:"gradable",component:"core"},{key:"recommended_help",component:"core_course"},{key:"supports",component:"core_course"},...activityCategories.map((key=>({key:"mod_purpose_"+key,component:"core_course"}))),...activityCategories.map((key=>({key:"mod_purpose_"+key+"_help",component:"core_course"})))],loadedStrings=await(0,_str.getStrings)(stringToLoad);return stringToLoad.forEach(((_ref,index)=>{let{key:key}=_ref;allStrings[key]=loadedStrings[index]})),allStrings}return _exports.default=class{getTabData(tabId,filteredModules,tabLabel){let tabHelp=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;const result={tabId:tabId,active:arguments.length>4&&void 0!==arguments[4]&&arguments[4],items:filteredModules,displayed:filteredModules.length>0,tabLabel:tabLabel};return tabHelp&&(result.tabHelp=tabHelp),result}normaliseModulesData(modulesData){if(modulesData instanceof Map)modulesData=Array.from(modulesData.values());else if(!Array.isArray(modulesData))throw new Error("Invalid modules data format. Expected an array or a Map.");return modulesData}async getModChooserTemplateData(modulesData){modulesData=this.normaliseModulesData(modulesData);const allStrings=await loadNecessaryStrings(),favouriteTab=await this.getFavouriteTabData(modulesData),tabs=[{...this.getTabData("all",modulesData,allStrings.all,null,!favouriteTab.displayed),hasSearchResults:!0},favouriteTab,{...this.getTabData("recommended",modulesData.filter((mod=>!0===mod.recommended)),allStrings.recommended,allStrings.recommended_help),separator:!0}];return activityCategories.forEach((category=>{const categoryModules=modulesData.filter((mod=>mod.purpose==category));0!==categoryModules.length&&tabs.push(this.getTabData(category,categoryModules,allStrings["mod_purpose_"+category],allStrings["mod_purpose_"+category+"_help"]))})),{modules:modulesData,tabs:tabs}}async getModuleHelpTemplateData(moduleData){const purposeKey="mod_purpose_".concat(moduleData.purpose),allStrings=await loadNecessaryStrings(),data={...moduleData};return data.details=[{label:allStrings.supports,value:allStrings[purposeKey]||""},{label:allStrings.gradable,value:moduleData.gradable?allStrings.yes:allStrings.no}],data}async getFavouriteTabData(modulesData){modulesData=this.normaliseModulesData(modulesData);const allStrings=await loadNecessaryStrings(),favouriteModules=modulesData.filter((mod=>!0===mod.favourite));return this.getTabData("favourites",favouriteModules,allStrings.favourites,null,favouriteModules.length>0)}getSearchResultData(resultsModulesData){return{searchresultsnumber:(resultsModulesData=this.normaliseModulesData(resultsModulesData)).length,searchresults:resultsModulesData}}countTabItems(tabData){var _tabData$items$length,_tabData$items;return null!==(_tabData$items$length=null===(_tabData$items=tabData.items)||void 0===_tabData$items?void 0:_tabData$items.length)&&void 0!==_tabData$items$length?_tabData$items$length:0}getFooterData(footerData){return{activeFooter:footerData.customfootertemplate}}},_exports.default}));
|
||||
|
||||
//# sourceMappingURL=exporter.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -164,6 +164,10 @@ export default class {
|
||||
label: allStrings['supports'],
|
||||
value: allStrings[purposeKey] || '',
|
||||
},
|
||||
{
|
||||
label: allStrings['gradable'],
|
||||
value: moduleData.gradable ? allStrings['yes'] : allStrings['no'],
|
||||
},
|
||||
];
|
||||
return data;
|
||||
}
|
||||
@@ -243,8 +247,11 @@ async function loadNecessaryStrings() {
|
||||
|
||||
const stringToLoad = [
|
||||
{key: 'all', component: 'core'},
|
||||
{key: 'yes', component: 'core'},
|
||||
{key: 'no', component: 'core'},
|
||||
{key: 'favourites', component: 'core'},
|
||||
{key: 'recommended', component: 'core'},
|
||||
{key: 'gradable', component: 'core'},
|
||||
{key: 'recommended_help', component: 'core_course'},
|
||||
{key: 'supports', component: 'core_course'},
|
||||
...activityCategories.map(
|
||||
|
||||
@@ -33,36 +33,6 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class content_item {
|
||||
/** @var int $id the id. */
|
||||
private $id;
|
||||
|
||||
/** @var string $name the name. */
|
||||
private $name;
|
||||
|
||||
/** @var title $title the title. */
|
||||
private $title;
|
||||
|
||||
/** @var \moodle_url $link the url for the content item's setup page (usually mod/edit.php). */
|
||||
private $link;
|
||||
|
||||
/** @var string $icon an html string containing the icon for this item. */
|
||||
private $icon;
|
||||
|
||||
/** @var string $help the description/help text for this content item. */
|
||||
private $help;
|
||||
|
||||
/** @var int $achetype a module archetype, e.g. MOD_ARCHETYPE_RESOURCE, MOD_ARCHETYPE_OTHER. */
|
||||
private $archetype;
|
||||
|
||||
/** @var string $componentname the name of the component from which this content item originates. */
|
||||
private $componentname;
|
||||
|
||||
/** @var string $purpose the purpose type of this component. */
|
||||
private $purpose;
|
||||
|
||||
/** @var bool $branded whether or not this component is branded. */
|
||||
private $branded;
|
||||
|
||||
/**
|
||||
* The content_item constructor.
|
||||
*
|
||||
@@ -76,19 +46,32 @@ class content_item {
|
||||
* @param string $componentname the name of the component/plugin with which this content item is associated.
|
||||
* @param string $purpose the purpose type of this component.
|
||||
* @param bool $branded whether or not this item is branded.
|
||||
* @param bool $gradable whether or not this item is gradable.
|
||||
*/
|
||||
public function __construct(int $id, string $name, title $title, \moodle_url $link, string $icon, string $help,
|
||||
int $archetype, string $componentname, string $purpose, bool $branded = false) {
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
$this->title = $title;
|
||||
$this->link = $link;
|
||||
$this->icon = $icon;
|
||||
$this->help = $help;
|
||||
$this->archetype = $archetype;
|
||||
$this->componentname = $componentname;
|
||||
$this->purpose = $purpose;
|
||||
$this->branded = $branded;
|
||||
public function __construct(
|
||||
/** @var int $id the id. */
|
||||
private int $id,
|
||||
/** @var string $name the name. */
|
||||
private string $name,
|
||||
/** @var title $title the title. */
|
||||
private title $title,
|
||||
/** @var \moodle_url $link the url for the content item's setup page (usually mod/edit.php). */
|
||||
private \moodle_url $link,
|
||||
/** @var string $icon an html string containing the icon for this item. */
|
||||
private string $icon,
|
||||
/** @var string $help the description/help text for this content item. */
|
||||
private string $help,
|
||||
/** @var int $archetype a module archetype, e.g. MOD_ARCHETYPE_RESOURCE, MOD_ARCHETYPE_OTHER. */
|
||||
private int $archetype,
|
||||
/** @var string $componentname the name of the component from which this content item originates. */
|
||||
private string $componentname,
|
||||
/** @var string $purpose the purpose type of this component. */
|
||||
private string $purpose,
|
||||
/** @var bool $branded whether or not this component is branded. */
|
||||
private bool $branded = false,
|
||||
/** @var bool $gradable whether or not this component is gradable. */
|
||||
private bool $gradable = false,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,4 +162,13 @@ class content_item {
|
||||
public function is_branded(): bool {
|
||||
return $this->branded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this item is gradable.
|
||||
*
|
||||
* @return bool true if this item is gradable, false otherwise.
|
||||
*/
|
||||
public function is_gradable(): bool {
|
||||
return $this->gradable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ class course_content_item_exporter extends exporter {
|
||||
'componentname' => ['type' => PARAM_TEXT, 'description' => 'The name of the component exposing the content item'],
|
||||
'purpose' => ['type' => PARAM_TEXT, 'description' => 'The purpose of the component exposing the content item'],
|
||||
'branded' => ['type' => PARAM_BOOL, 'description' => ' Whether this content item is branded or not'],
|
||||
'gradable' => ['type' => PARAM_BOOL, 'description' => 'Whether this content item is gradable or not'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -141,6 +142,7 @@ class course_content_item_exporter extends exporter {
|
||||
'recommended' => $recommended,
|
||||
'purpose' => $this->contentitem->get_purpose(),
|
||||
'branded' => $this->contentitem->is_branded(),
|
||||
'gradable' => $this->contentitem->is_gradable(),
|
||||
];
|
||||
|
||||
return $properties;
|
||||
|
||||
@@ -146,18 +146,20 @@ class content_item_readonly_repository implements content_item_readonly_reposito
|
||||
$archetype = plugin_supports('mod', $mod->name, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
|
||||
$purpose = plugin_supports('mod', $mod->name, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER);
|
||||
$isbranded = component_callback('mod_' . $mod->name, 'is_branded', [], false);
|
||||
$gradable = plugin_supports('mod', $mod->name, FEATURE_GRADE_HAS_GRADE, false);
|
||||
|
||||
$contentitem = new content_item(
|
||||
$mod->id,
|
||||
$mod->name,
|
||||
new lang_string_title("modulename", $mod->name),
|
||||
new \moodle_url(''), // No course scope, so just an empty link.
|
||||
$OUTPUT->pix_icon('monologo', '', $mod->name, ['class' => 'icon activityicon']),
|
||||
$help,
|
||||
$archetype,
|
||||
'mod_' . $mod->name,
|
||||
$purpose,
|
||||
$isbranded,
|
||||
id: $mod->id,
|
||||
name: $mod->name,
|
||||
title: new lang_string_title("modulename", $mod->name),
|
||||
link: new \moodle_url(''), // No course scope, so just an empty link.
|
||||
icon: $OUTPUT->pix_icon('monologo', '', $mod->name, ['class' => 'icon activityicon']),
|
||||
help: $help,
|
||||
archetype: $archetype,
|
||||
componentname: 'mod_' . $mod->name,
|
||||
purpose: $purpose,
|
||||
branded: $isbranded,
|
||||
gradable: $gradable,
|
||||
);
|
||||
|
||||
$modcontentitemreference = clone($contentitem);
|
||||
@@ -212,6 +214,7 @@ class content_item_readonly_repository implements content_item_readonly_reposito
|
||||
$archetype = plugin_supports('mod', $mod->name, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
|
||||
$purpose = plugin_supports('mod', $mod->name, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER);
|
||||
$isbranded = component_callback('mod_' . $mod->name, 'is_branded', [], false);
|
||||
$gradable = plugin_supports('mod', $mod->name, FEATURE_GRADE_HAS_GRADE, false);
|
||||
|
||||
$icon = 'monologo';
|
||||
// Quick check for monologo icons.
|
||||
@@ -222,16 +225,17 @@ class content_item_readonly_repository implements content_item_readonly_reposito
|
||||
$iconclass = 'nofilter';
|
||||
}
|
||||
$contentitem = new content_item(
|
||||
$mod->id,
|
||||
$mod->name,
|
||||
new lang_string_title("modulename", $mod->name),
|
||||
new \moodle_url('/course/mod.php', ['id' => $course->id, 'add' => $mod->name]),
|
||||
$OUTPUT->pix_icon($icon, '', $mod->name, ['class' => "activityicon $iconclass"]),
|
||||
$help,
|
||||
$archetype,
|
||||
'mod_' . $mod->name,
|
||||
$purpose,
|
||||
$isbranded,
|
||||
id: $mod->id,
|
||||
name: $mod->name,
|
||||
title: new lang_string_title("modulename", $mod->name),
|
||||
link: new \moodle_url('/course/mod.php', ['id' => $course->id, 'add' => $mod->name]),
|
||||
icon: $OUTPUT->pix_icon($icon, '', $mod->name, ['class' => "activityicon $iconclass"]),
|
||||
help: $help,
|
||||
archetype: $archetype,
|
||||
componentname: 'mod_' . $mod->name,
|
||||
purpose: $purpose,
|
||||
branded: $isbranded,
|
||||
gradable: $gradable,
|
||||
);
|
||||
|
||||
$modcontentitemreference = clone($contentitem);
|
||||
|
||||
@@ -47,7 +47,18 @@ Feature: Display and choose from the available activities in course
|
||||
When I click on "Information about the Assignment activity" "button" in the "Add an activity or resource" "dialogue"
|
||||
Then I should see "Assignment" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "The assignment activity module enables a teacher to communicate tasks, collect work and provide grades and feedback."
|
||||
And I should see "Supports" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "Assessment" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "Gradable" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "Yes" in the "help" "core_course > Activity chooser screen"
|
||||
And I click on "Back" "button" in the "Add an activity or resource" "dialogue"
|
||||
And I click on "Information about the Book activity" "button" in the "Add an activity or resource" "dialogue"
|
||||
Then I should see "Book" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "The book module enables a teacher to create a multi-page resource in a book-like format"
|
||||
And I should see "Supports" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "Resources" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "Gradable" in the "help" "core_course > Activity chooser screen"
|
||||
And I should see "No" in the "help" "core_course > Activity chooser screen"
|
||||
# Confirm show summary also works for weekly format course
|
||||
And I am on "C2" course homepage with editing mode on
|
||||
And I click on "Add content" "button" in the "13 January - 19 January" "section"
|
||||
|
||||
@@ -39,9 +39,19 @@ final class content_item_test extends \advanced_testcase {
|
||||
public function test_content_item(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$contentitem = new content_item(22, 'Item name', new lang_string_title('modulename', 'mod_assign'),
|
||||
new \moodle_url('mod_edit.php'), '<img src="test">', 'Description of the module', MOD_ARCHETYPE_RESOURCE, 'mod_page',
|
||||
MOD_PURPOSE_CONTENT, true);
|
||||
$contentitem = new content_item(
|
||||
id: 22,
|
||||
name: 'Item name',
|
||||
title: new lang_string_title('modulename', 'mod_assign'),
|
||||
link: new \moodle_url('mod_edit.php'),
|
||||
icon: '<img src="test">',
|
||||
help: 'Description of the module',
|
||||
archetype: MOD_ARCHETYPE_RESOURCE,
|
||||
componentname: 'mod_page',
|
||||
purpose: MOD_PURPOSE_CONTENT,
|
||||
branded: true,
|
||||
gradable: true,
|
||||
);
|
||||
|
||||
$this->assertEquals(22, $contentitem->get_id());
|
||||
$this->assertEquals('Item name', $contentitem->get_name());
|
||||
@@ -53,6 +63,7 @@ final class content_item_test extends \advanced_testcase {
|
||||
$this->assertEquals('mod_page', $contentitem->get_component_name());
|
||||
$this->assertEquals('content', $contentitem->get_purpose());
|
||||
$this->assertTrue($contentitem->is_branded());
|
||||
$this->assertTrue($contentitem->is_gradable());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -991,6 +991,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the Moodle License information page for full details: https://moodledev.io/general/license';
|
||||
$string['gradable'] = 'Gradable';
|
||||
$string['grades'] = 'Grades';
|
||||
$string['gradenoun'] = 'Grade';
|
||||
$string['gradeverb'] = 'Grade';
|
||||
|
||||
Reference in New Issue
Block a user