MDL-74800 core_courseformat: fix accessibility checks
This commit is contained in:
@@ -102,7 +102,7 @@ class block_site_main_menu extends block_list {
|
||||
'contentwithoutlink activity-item activity'
|
||||
);
|
||||
} else {
|
||||
$cmname = new $cmnameclass($format, $cm->get_section_info(), $cm, $isediting);
|
||||
$cmname = new $cmnameclass($format, $cm->get_section_info(), $cm);
|
||||
$activitybasis = html_writer::div(
|
||||
$indent . $courserenderer->render($cmname),
|
||||
'activity-basis d-flex align-items-center');
|
||||
@@ -214,7 +214,7 @@ class block_site_main_menu extends block_list {
|
||||
'contentwithoutlink activity-item activity'
|
||||
);
|
||||
} else {
|
||||
$cmname = new $cmnameclass($format, $mod->get_section_info(), $mod, $isediting);
|
||||
$cmname = new $cmnameclass($format, $mod->get_section_info(), $mod);
|
||||
$activitybasis = html_writer::div(
|
||||
$moveaction .
|
||||
$indent .
|
||||
|
||||
@@ -99,7 +99,7 @@ class block_social_activities extends block_list {
|
||||
$this->content->items[] = $content;
|
||||
$this->content->icons[] = '';
|
||||
} else {
|
||||
$cmname = new $cmnameclass($format, $cm->get_section_info(), $cm, $isediting);
|
||||
$cmname = new $cmnameclass($format, $cm->get_section_info(), $cm);
|
||||
$activitybasis = html_writer::div(
|
||||
$courserenderer->render($cmname),
|
||||
'activity-basis d-flex align-items-center');
|
||||
@@ -205,7 +205,7 @@ class block_social_activities extends block_list {
|
||||
$this->content->items[] = $content;
|
||||
$this->content->icons[] = '';
|
||||
} else {
|
||||
$cmname = new $cmnameclass($format, $mod->get_section_info(), $mod, $isediting);
|
||||
$cmname = new $cmnameclass($format, $mod->get_section_info(), $mod);
|
||||
$activitybasis = html_writer::div(
|
||||
$courserenderer->render($cmname) .
|
||||
$editbuttons,
|
||||
|
||||
@@ -59,12 +59,6 @@ class cm implements named_templatable, renderable {
|
||||
/** @var array optional display options */
|
||||
protected $displayoptions;
|
||||
|
||||
/** @var string activity link css classes */
|
||||
protected $linkclasses = null;
|
||||
|
||||
/** @var string text css classes */
|
||||
protected $textclasses = null;
|
||||
|
||||
/** @var string the activity name output class name */
|
||||
protected $cmnameclass;
|
||||
|
||||
@@ -88,10 +82,8 @@ class cm implements named_templatable, renderable {
|
||||
$this->mod = $mod;
|
||||
|
||||
// Add extra display options.
|
||||
$this->load_classes();
|
||||
$displayoptions['linkclasses'] = $this->get_link_classes();
|
||||
$displayoptions['textclasses'] = $this->get_text_classes();
|
||||
$this->displayoptions = $displayoptions;
|
||||
$this->load_classes();
|
||||
|
||||
// Get the necessary classes.
|
||||
$this->cmnameclass = $format->get_output_classname('content\\cm\\cmname');
|
||||
@@ -148,11 +140,11 @@ class cm implements named_templatable, renderable {
|
||||
$this->format,
|
||||
$this->section,
|
||||
$this->mod,
|
||||
$this->format->show_editor(),
|
||||
null,
|
||||
$this->displayoptions
|
||||
);
|
||||
$data->cmname = $cmname->export_for_template($output);
|
||||
$data->hasname = !empty($data->cmname['displayvalue']);
|
||||
$data->hasname = $cmname->has_name();
|
||||
return $data->hasname;
|
||||
}
|
||||
|
||||
@@ -323,8 +315,9 @@ class cm implements named_templatable, renderable {
|
||||
$textclasses .= ' conditionalhidden';
|
||||
}
|
||||
}
|
||||
$this->linkclasses = $linkclasses;
|
||||
$this->textclasses = $textclasses;
|
||||
$this->displayoptions['linkclasses'] = $linkclasses;
|
||||
$this->displayoptions['textclasses'] = $textclasses;
|
||||
$this->displayoptions['onclick'] = htmlspecialchars_decode($mod->onclick, ENT_QUOTES);;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,7 +326,7 @@ class cm implements named_templatable, renderable {
|
||||
* @return string the activity link classes.
|
||||
*/
|
||||
public function get_link_classes(): string {
|
||||
return $this->linkclasses;
|
||||
return $this->displayoptions['linkclasses'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,6 +335,15 @@ class cm implements named_templatable, renderable {
|
||||
* @return string the activity text classes.
|
||||
*/
|
||||
public function get_text_classes(): string {
|
||||
return $this->textclasses;
|
||||
return $this->displayoptions['textclasses'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity onclick code.
|
||||
*
|
||||
* @return string the activity onclick.
|
||||
*/
|
||||
public function get_onclick_code(): string {
|
||||
return $this->displayoptions['onclick'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,9 @@
|
||||
namespace core_courseformat\output\local\content\cm;
|
||||
|
||||
use cm_info;
|
||||
use context_module;
|
||||
use core\output\inplace_editable;
|
||||
use core\output\named_templatable;
|
||||
use core_courseformat\base as course_format;
|
||||
use core_courseformat\output\local\courseformat_named_templatable;
|
||||
use external_api;
|
||||
use lang_string;
|
||||
use renderable;
|
||||
use section_info;
|
||||
use stdClass;
|
||||
@@ -43,7 +39,7 @@ use stdClass;
|
||||
* @copyright 2020 Ferran Recio <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class cmname extends inplace_editable implements named_templatable, renderable {
|
||||
class cmname implements named_templatable, renderable {
|
||||
|
||||
use courseformat_named_templatable;
|
||||
|
||||
@@ -56,9 +52,6 @@ class cmname extends inplace_editable implements named_templatable, renderable {
|
||||
/** @var cm_info the course module instance */
|
||||
protected $mod;
|
||||
|
||||
/** @var editable if the title is editable */
|
||||
protected $editable;
|
||||
|
||||
/** @var array optional display options */
|
||||
protected $displayoptions;
|
||||
|
||||
@@ -71,14 +64,14 @@ class cmname extends inplace_editable implements named_templatable, renderable {
|
||||
* @param course_format $format the course format
|
||||
* @param section_info $section the section info
|
||||
* @param cm_info $mod the course module ionfo
|
||||
* @param bool $editable if it is editable
|
||||
* @param bool|null $editable if it is editable (not used)
|
||||
* @param array $displayoptions optional extra display options
|
||||
*/
|
||||
public function __construct(
|
||||
course_format $format,
|
||||
section_info $section,
|
||||
cm_info $mod,
|
||||
bool $editable,
|
||||
?bool $editable = null,
|
||||
array $displayoptions = []
|
||||
) {
|
||||
$this->format = $format;
|
||||
@@ -86,25 +79,8 @@ class cmname extends inplace_editable implements named_templatable, renderable {
|
||||
$this->mod = $mod;
|
||||
$this->displayoptions = $displayoptions;
|
||||
|
||||
$this->editable = $editable && has_capability(
|
||||
'moodle/course:manageactivities',
|
||||
$mod->context
|
||||
);
|
||||
|
||||
// Get the necessary classes.
|
||||
$this->titleclass = $format->get_output_classname('content\\cm\\title');
|
||||
|
||||
// Setup inplace editable.
|
||||
parent::__construct(
|
||||
'core_course',
|
||||
'activityname',
|
||||
$mod->id,
|
||||
$this->editable,
|
||||
$mod->name,
|
||||
$mod->name,
|
||||
new lang_string('edittitle'),
|
||||
new lang_string('newactivityname', '', $mod->get_formatted_name())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,51 +90,49 @@ class cmname extends inplace_editable implements named_templatable, renderable {
|
||||
* @return stdClass data context for a mustache template
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output): array {
|
||||
global $PAGE;
|
||||
$mod = $this->mod;
|
||||
$displayoptions = $this->displayoptions;
|
||||
|
||||
// Inplace editable uses core renderer by default. However, course elements require
|
||||
// the format specific renderer.
|
||||
$courseoutput = $this->format->get_renderer($PAGE);
|
||||
if (!$this->has_name()) {
|
||||
// Nothing to be displayed to the user.
|
||||
return [];
|
||||
}
|
||||
|
||||
// Inplace editable uses pre-rendered elements and does not allow line beaks in the UI value.
|
||||
$data = [
|
||||
'url' => $mod->url,
|
||||
'icon' => $mod->get_icon_url(),
|
||||
'modname' => $mod->modname,
|
||||
'pluginname' => get_string('pluginname', 'mod_' . $mod->modname),
|
||||
'textclasses' => $displayoptions['textclasses'] ?? '',
|
||||
'purpose' => plugin_supports('mod', $mod->modname, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER),
|
||||
'activityname' => $this->get_title_data($output),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the title data.
|
||||
*
|
||||
* @param \renderer_base $output typically, the renderer that's calling this function
|
||||
* @return array data context for a mustache template
|
||||
*/
|
||||
protected function get_title_data(\renderer_base $output): array {
|
||||
$title = new $this->titleclass(
|
||||
$this->format,
|
||||
$this->section,
|
||||
$this->mod,
|
||||
$this->displayoptions
|
||||
);
|
||||
$this->displayvalue = str_replace("\n", "", $courseoutput->render($title));
|
||||
|
||||
if (trim($this->displayvalue) == '') {
|
||||
$this->editable = false;
|
||||
}
|
||||
$data = parent::export_for_template($output);
|
||||
|
||||
return $data;
|
||||
return (array) $title->export_for_template($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates course module name
|
||||
* Return if the activity has a visible name.
|
||||
*
|
||||
* @param int $itemid course module id
|
||||
* @param string $newvalue new name
|
||||
* @return static
|
||||
* @return bool if the title is visible.
|
||||
*/
|
||||
public static function update($itemid, $newvalue) {
|
||||
$context = context_module::instance($itemid);
|
||||
// Check access.
|
||||
external_api::validate_context($context);
|
||||
require_capability('moodle/course:manageactivities', $context);
|
||||
|
||||
// Trim module name and Update value.
|
||||
set_coursemodule_name($itemid, trim($newvalue));
|
||||
$coursemodulerecord = get_coursemodule_from_id('', $itemid, 0, false, MUST_EXIST);
|
||||
// Return instance.
|
||||
$modinfo = get_fast_modinfo($coursemodulerecord->course);
|
||||
$cm = $modinfo->get_cm($itemid);
|
||||
$section = $modinfo->get_section_info($cm->sectionnum);
|
||||
|
||||
$format = course_get_format($cm->course);
|
||||
return new static($format, $section, $cm, true);
|
||||
public function has_name(): bool {
|
||||
return $this->mod->is_visible_on_course_page() && $this->mod->url;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,16 @@
|
||||
namespace core_courseformat\output\local\content\cm;
|
||||
|
||||
use cm_info;
|
||||
use core\output\inplace_editable;
|
||||
use core\output\named_templatable;
|
||||
use core_courseformat\base as course_format;
|
||||
use core_courseformat\output\local\courseformat_named_templatable;
|
||||
use core_text;
|
||||
use lang_string;
|
||||
use renderable;
|
||||
use section_info;
|
||||
use stdClass;
|
||||
use external_api;
|
||||
use context_module;
|
||||
|
||||
/**
|
||||
* Base class to render a course module title inside a course format.
|
||||
@@ -42,9 +45,7 @@ use stdClass;
|
||||
* @copyright 2020 Ferran Recio <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class title implements named_templatable, renderable {
|
||||
|
||||
use courseformat_named_templatable;
|
||||
class title extends inplace_editable implements named_templatable, renderable {
|
||||
|
||||
/** @var course_format the course format */
|
||||
protected $format;
|
||||
@@ -58,6 +59,12 @@ class title implements named_templatable, renderable {
|
||||
/** @var array optional display options */
|
||||
protected $displayoptions;
|
||||
|
||||
/** @var editable if the title is editable */
|
||||
protected $editable;
|
||||
|
||||
/** @var displaytemplate the default display template */
|
||||
protected $displaytemplate = 'core_courseformat/local/content/cm/title';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -65,12 +72,52 @@ class title implements named_templatable, renderable {
|
||||
* @param section_info $section the section info
|
||||
* @param cm_info $mod the course module ionfo
|
||||
* @param array $displayoptions optional extra display options
|
||||
* @param bool|null $editable force editable value
|
||||
*/
|
||||
public function __construct(course_format $format, section_info $section, cm_info $mod, array $displayoptions = []) {
|
||||
public function __construct(
|
||||
course_format $format,
|
||||
section_info $section,
|
||||
cm_info $mod,
|
||||
array $displayoptions = [],
|
||||
?bool $editable = null
|
||||
) {
|
||||
$this->format = $format;
|
||||
$this->section = $section;
|
||||
$this->mod = $mod;
|
||||
$this->displayoptions = $displayoptions;
|
||||
|
||||
// Usually displayoptions are loaded in the main cm output. However when the user uses the inplace editor
|
||||
// the cmname output does not calculate the css classes.
|
||||
$this->displayoptions = $this->load_display_options($displayoptions);
|
||||
|
||||
if ($editable === null) {
|
||||
$editable = $format->show_editor() && has_capability(
|
||||
'moodle/course:manageactivities',
|
||||
$mod->context
|
||||
);
|
||||
}
|
||||
$this->editable = $editable;
|
||||
|
||||
// Setup inplace editable.
|
||||
parent::__construct(
|
||||
'core_course',
|
||||
'activityname',
|
||||
$mod->id,
|
||||
$this->editable,
|
||||
$mod->name,
|
||||
$mod->name,
|
||||
new lang_string('edittitle'),
|
||||
new lang_string('newactivityname', '', $mod->get_formatted_name())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the template to use for this templatable.
|
||||
*
|
||||
* @param \renderer_base $renderer The renderer requesting the template name
|
||||
* @return string
|
||||
*/
|
||||
public function get_template_name(\renderer_base $renderer): string {
|
||||
return 'core/inplace_editable';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,41 +126,35 @@ class title implements named_templatable, renderable {
|
||||
* @param \renderer_base $output typically, the renderer that's calling this function
|
||||
* @return stdClass data context for a mustache template
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output): stdClass {
|
||||
public function export_for_template(\renderer_base $output): array {
|
||||
|
||||
// Inplace editable uses pre-rendered elements and does not allow line beaks in the UI value.
|
||||
$this->displayvalue = str_replace("\n", "", $this->get_title_displayvalue());
|
||||
|
||||
if (trim($this->displayvalue) == '') {
|
||||
$this->editable = false;
|
||||
}
|
||||
return parent::export_for_template($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the title template data to be used inside the inplace editable.
|
||||
*
|
||||
*/
|
||||
protected function get_title_displayvalue (): string {
|
||||
global $PAGE;
|
||||
|
||||
// Inplace editable uses core renderer by default. However, course elements require
|
||||
// the format specific renderer.
|
||||
$courseoutput = $this->format->get_renderer($PAGE);
|
||||
|
||||
$format = $this->format;
|
||||
$mod = $this->mod;
|
||||
$displayoptions = $this->displayoptions;
|
||||
|
||||
if (!$mod->is_visible_on_course_page() || !$mod->url) {
|
||||
// Nothing to be displayed to the user.
|
||||
return new stdClass();
|
||||
}
|
||||
|
||||
// Usually classes are loaded in the main cm output. However when the user uses the inplace editor
|
||||
// the cmname output does not calculate the css classes.
|
||||
if (!isset($displayoptions['linkclasses']) || !isset($displayoptions['textclasses'])) {
|
||||
$cmclass = $format->get_output_classname('content\\cm');
|
||||
$cmoutput = new $cmclass(
|
||||
$format,
|
||||
$this->section,
|
||||
$mod,
|
||||
$displayoptions
|
||||
);
|
||||
$displayoptions['linkclasses'] = $cmoutput->get_link_classes();
|
||||
$displayoptions['textclasses'] = $cmoutput->get_text_classes();
|
||||
}
|
||||
|
||||
$data = (object)[
|
||||
'url' => $mod->url,
|
||||
'instancename' => $mod->get_formatted_name(),
|
||||
'uservisible' => $mod->uservisible,
|
||||
'icon' => $mod->get_icon_url(),
|
||||
'modname' => $mod->modname,
|
||||
'pluginname' => get_string('pluginname', 'mod_' . $mod->modname),
|
||||
'linkclasses' => $displayoptions['linkclasses'],
|
||||
'textclasses' => $displayoptions['textclasses'],
|
||||
'purpose' => plugin_supports('mod', $mod->modname, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER),
|
||||
'linkclasses' => $this->displayoptions['linkclasses'],
|
||||
];
|
||||
|
||||
// File type after name, for alphabetic lists (screen reader).
|
||||
@@ -128,6 +169,71 @@ class title implements named_templatable, renderable {
|
||||
// has already been encoded for display (puke).
|
||||
$data->onclick = htmlspecialchars_decode($mod->onclick, ENT_QUOTES);
|
||||
|
||||
return $data;
|
||||
return $courseoutput->render_from_template(
|
||||
$this->displaytemplate,
|
||||
$data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the required display options if not present already.
|
||||
*
|
||||
* In most cases, display options are provided as a param when creating the
|
||||
* object. However, inplace_editable and some blocks does not know all of them as it is
|
||||
* called in a webservice and we need to ensure it is calculated.
|
||||
*
|
||||
* @param array $displayoptions the provided dispaly options
|
||||
* @return array the full display options list
|
||||
*/
|
||||
protected function load_display_options(array $displayoptions): array {
|
||||
$format = $this->format;
|
||||
$mod = $this->mod;
|
||||
|
||||
if (
|
||||
isset($displayoptions['linkclasses']) &&
|
||||
isset($displayoptions['textclasses']) &&
|
||||
isset($displayoptions['onclick'])
|
||||
) {
|
||||
return $displayoptions;
|
||||
}
|
||||
|
||||
$cmclass = $format->get_output_classname('content\\cm');
|
||||
$cmoutput = new $cmclass(
|
||||
$format,
|
||||
$this->section,
|
||||
$mod,
|
||||
$displayoptions
|
||||
);
|
||||
$displayoptions['linkclasses'] = $cmoutput->get_link_classes();
|
||||
$displayoptions['textclasses'] = $cmoutput->get_text_classes();
|
||||
$displayoptions['onclick'] = $cmoutput->get_onclick_code();
|
||||
return $displayoptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates course module name.
|
||||
*
|
||||
* This method is used mainly by inplace_editable webservice.
|
||||
*
|
||||
* @param int $itemid course module id
|
||||
* @param string $newvalue new name
|
||||
* @return static
|
||||
*/
|
||||
public static function update($itemid, $newvalue) {
|
||||
$context = context_module::instance($itemid);
|
||||
// Check access.
|
||||
external_api::validate_context($context);
|
||||
require_capability('moodle/course:manageactivities', $context);
|
||||
|
||||
// Trim module name and Update value.
|
||||
set_coursemodule_name($itemid, trim($newvalue));
|
||||
$coursemodulerecord = get_coursemodule_from_id('', $itemid, 0, false, MUST_EXIST);
|
||||
// Return instance.
|
||||
$modinfo = get_fast_modinfo($coursemodulerecord->course);
|
||||
$cm = $modinfo->get_cm($itemid);
|
||||
$section = $modinfo->get_section_info($cm->sectionnum);
|
||||
|
||||
$format = course_get_format($cm->course);
|
||||
return new static($format, $section, $cm, [], true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
}
|
||||
}}
|
||||
{{#showaddsection}}
|
||||
<div id="changenumsections" class="mdl-left py-2">
|
||||
<div class="mdl-left py-2 changenumsections">
|
||||
{{#increase}}
|
||||
<a href="{{{url}}}" class="increase-sections">
|
||||
{{#pix}}t/switch_plus, moodle, {{#str}} increasesections, moodle {{/str}}{{/pix}}
|
||||
|
||||
@@ -65,9 +65,9 @@
|
||||
{{/ core_courseformat/local/content/cm/badges }}
|
||||
{{/hasname}}
|
||||
{{#cmname}}
|
||||
{{$ core/inplace_editable }}
|
||||
{{> core/inplace_editable }}
|
||||
{{/ core/inplace_editable }}
|
||||
{{$ core_courseformat/local/content/cm/cmname }}
|
||||
{{> core_courseformat/local/content/cm/cmname }}
|
||||
{{/ core_courseformat/local/content/cm/cmname }}
|
||||
{{/cmname}}
|
||||
{{#afterlink}}
|
||||
<div class="afterlink">
|
||||
|
||||
@@ -23,18 +23,44 @@
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"displayvalue" : "<a href=\"#\">Moodle</a>",
|
||||
"value" : "Moodle",
|
||||
"itemid" : "1",
|
||||
"component" : "core_unknown",
|
||||
"itemtype" : "unknown",
|
||||
"edithint" : "Edit this",
|
||||
"editlabel" : "New name for this",
|
||||
"type" : "text",
|
||||
"options" : "",
|
||||
"linkeverything": 0
|
||||
"url": "#",
|
||||
"icon": "../../../pix/help.svg",
|
||||
"pluginname": "File",
|
||||
"textclasses": "",
|
||||
"purpose": "content",
|
||||
"modname": "resource",
|
||||
"activityname": {
|
||||
"displayvalue" : "<a href=\"#\">Moodle</a>",
|
||||
"value" : "Moodle",
|
||||
"itemid" : "1",
|
||||
"component" : "core_unknown",
|
||||
"itemtype" : "unknown",
|
||||
"edithint" : "Edit this",
|
||||
"editlabel" : "New name for this",
|
||||
"type" : "text",
|
||||
"options" : "",
|
||||
"linkeverything": 0
|
||||
}
|
||||
}
|
||||
}}
|
||||
{{$ core/inplace_editable }}
|
||||
{{> core/inplace_editable }}
|
||||
{{/ core/inplace_editable }}
|
||||
{{#url}}
|
||||
<div class="activity-instance d-flex flex-column">
|
||||
<div class="activitytitle media {{textclasses}} modtype_{{modname}} position-relative align-self-start">
|
||||
<div class="activityiconcontainer {{purpose}} courseicon align-self-start mr-3">
|
||||
<img src="{{{icon}}}" class="activityicon " alt="{{{modname}}} icon">
|
||||
</div>
|
||||
<div class="media-body align-self-center">
|
||||
<div class="text-uppercase small">
|
||||
{{{pluginname}}}
|
||||
</div>
|
||||
<div class="activityname">
|
||||
{{#activityname}}
|
||||
{{$ core/inplace_editable }}
|
||||
{{> core/inplace_editable }}
|
||||
{{/ core/inplace_editable }}
|
||||
{{/activityname}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/url}}
|
||||
|
||||
@@ -24,39 +24,19 @@
|
||||
"url": "#",
|
||||
"instancename": "Activity name",
|
||||
"uservisible": true,
|
||||
"icon": "../../../pix/help.svg",
|
||||
"onclick": "alert('ok')",
|
||||
"pluginname": "File",
|
||||
"altname": "PDF file",
|
||||
"linkclasses": "",
|
||||
"textclasses": "",
|
||||
"purpose": "content",
|
||||
"modname": "resource"
|
||||
}
|
||||
}}
|
||||
{{#url}}
|
||||
<div class="activity-instance d-flex flex-column">
|
||||
<div class="activitytitle media {{textclasses}} modtype_{{modname}} position-relative align-self-start">
|
||||
<div class="activityiconcontainer {{purpose}} courseicon align-self-start mr-3">
|
||||
<img src="{{{icon}}}" class="activityicon " alt="{{{modname}}} icon">
|
||||
</div>
|
||||
<div class="media-body align-self-center">
|
||||
<div class="text-uppercase small">
|
||||
{{{pluginname}}}
|
||||
</div>
|
||||
<div class="activityname">
|
||||
{{#uservisible}}
|
||||
<a href="{{url}}" class="{{linkclasses}} aalink stretched-link" onclick="{{{onclick}}}">
|
||||
<span class="instancename">{{{instancename}}} {{{altname}}}</span>
|
||||
</a>
|
||||
{{/uservisible}}
|
||||
{{^uservisible}}
|
||||
<span class="instancename">
|
||||
{{{instancename}}} {{{altname}}}
|
||||
</span>
|
||||
{{/uservisible}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/url}}
|
||||
{{#uservisible}}
|
||||
<a href="{{url}}" class="{{linkclasses}} aalink stretched-link" onclick="{{{onclick}}}">
|
||||
<span class="instancename">{{{instancename}}} {{{altname}}}</span>
|
||||
</a>
|
||||
{{/uservisible}}
|
||||
{{^uservisible}}
|
||||
<span class="instancename">
|
||||
{{{instancename}}} {{{altname}}}
|
||||
</span>
|
||||
{{/uservisible}}
|
||||
|
||||
+1
-1
@@ -3663,7 +3663,7 @@ function course_get_tagged_courses($tag, $exclusivemode = false, $fromctx = 0, $
|
||||
*/
|
||||
function core_course_inplace_editable($itemtype, $itemid, $newvalue) {
|
||||
if ($itemtype === 'activityname') {
|
||||
return \core_courseformat\output\local\content\cm\cmname::update($itemid, $newvalue);
|
||||
return \core_courseformat\output\local\content\cm\title::update($itemid, $newvalue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -606,14 +606,12 @@ class core_course_renderer extends plugin_renderer_base {
|
||||
$format,
|
||||
$mod->get_section_info(),
|
||||
$mod,
|
||||
$this->page->user_is_editing(),
|
||||
null,
|
||||
$displayoptions
|
||||
);
|
||||
|
||||
$data = $cmname->export_for_template($this->output);
|
||||
|
||||
return $this->output->render_from_template('core/inplace_editable', $data) .
|
||||
$groupinglabel;
|
||||
$renderer = $format->get_renderer($this->page);
|
||||
return $renderer->render($cmname) . $groupinglabel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,11 @@ information provided here is intended especially for developers.
|
||||
=== 4.1 ===
|
||||
* The function course_modchooser() has been finally deprecated and can not be used anymore. Please use
|
||||
course_activitychooser() instead.
|
||||
* A critical accessibility issue is been found (MDL-74800) at the output class
|
||||
core_courseformat\output\local\content\cm\cmname. To solve the problem this output element is not
|
||||
rendered anymore using inplace_editable but using a regular named_templatable interface.
|
||||
Some format plugins that override the deprecated renderer method course_section_cm_name can be affected.
|
||||
Check the current course_section_cm_name code to see how to render it properly.
|
||||
|
||||
=== 4.0 ===
|
||||
* All activity icons have been replaced with black monochrome icons. The background
|
||||
|
||||
@@ -22,15 +22,23 @@
|
||||
Example context (json):
|
||||
{
|
||||
"classes": "",
|
||||
"instance": "1",
|
||||
"primary": {
|
||||
"items": [{"rawhtml": "<p>Item in primary menu</p>"}]
|
||||
},
|
||||
"secondary": {
|
||||
"items": [{"rawhtml": "<p>Item in secondary menu</p>"}]
|
||||
"attributes": [
|
||||
{"name": "id", "value": "action-menu-1-menu"}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"rawhtml": "<p>Item in secondary menu</p>"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}}
|
||||
<div class="action-menu {{classes}}"{{#attributes}} {{name}}="{{value}}"{{/attributes}}>
|
||||
<div class="action-menu {{classes}}"{{#attributes}} {{name}}="{{value}}"{{/attributes}} role="menu">
|
||||
{{#primary}}
|
||||
|
||||
<div class="{{classes}} d-flex "{{#attributes}} {{name}}="{{value}}"{{/attributes}}>
|
||||
|
||||
@@ -1258,7 +1258,7 @@ $activity-add-hover: theme-color-level('primary', -10) !default;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#changenumsections {
|
||||
.changenumsections {
|
||||
border-top: $border-width solid $primary-light-border;
|
||||
}
|
||||
|
||||
@@ -1437,9 +1437,16 @@ $activity-add-hover: theme-color-level('primary', -10) !default;
|
||||
flex: 0 1 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
.inplaceeditable .quickeditlink,
|
||||
.afterlink {
|
||||
margin: 1.5rem 0 0.2rem 0.5rem;
|
||||
|
||||
/* Prevent bootstrap strech-link from covering the inplace editable button using z-index. */
|
||||
.activityname {
|
||||
.afterlink {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
.inplaceeditable .quickeditlink {
|
||||
z-index: 2;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.action-menu-item {
|
||||
|
||||
@@ -14731,7 +14731,7 @@ span.editinstructions {
|
||||
.block-add:hover .activity-add-text {
|
||||
text-decoration: underline; }
|
||||
|
||||
#changenumsections {
|
||||
.changenumsections {
|
||||
border-top: 1px solid #3584c9; }
|
||||
|
||||
.section-collapsemenu .collapseall {
|
||||
@@ -14821,7 +14821,8 @@ span.editinstructions {
|
||||
|
||||
.activity-item {
|
||||
position: relative;
|
||||
border-radius: 0.5rem; }
|
||||
border-radius: 0.5rem;
|
||||
/* Prevent bootstrap strech-link from covering the inplace editable button using z-index. */ }
|
||||
.activity-item:not(.activityinline) {
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 1rem; }
|
||||
@@ -14841,9 +14842,11 @@ span.editinstructions {
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
max-width: 100%; }
|
||||
.activity-item .inplaceeditable .quickeditlink,
|
||||
.activity-item .afterlink {
|
||||
margin: 1.5rem 0 0.2rem 0.5rem; }
|
||||
.activity-item .activityname .afterlink {
|
||||
margin-left: 0.5rem; }
|
||||
.activity-item .activityname .inplaceeditable .quickeditlink {
|
||||
z-index: 2;
|
||||
margin-left: 0.5rem; }
|
||||
.activity-item .action-menu-item {
|
||||
display: flex;
|
||||
align-items: center; }
|
||||
|
||||
@@ -14731,7 +14731,7 @@ span.editinstructions {
|
||||
.block-add:hover .activity-add-text {
|
||||
text-decoration: underline; }
|
||||
|
||||
#changenumsections {
|
||||
.changenumsections {
|
||||
border-top: 1px solid #3584c9; }
|
||||
|
||||
.section-collapsemenu .collapseall {
|
||||
@@ -14821,7 +14821,8 @@ span.editinstructions {
|
||||
|
||||
.activity-item {
|
||||
position: relative;
|
||||
border-radius: 0.25rem; }
|
||||
border-radius: 0.25rem;
|
||||
/* Prevent bootstrap strech-link from covering the inplace editable button using z-index. */ }
|
||||
.activity-item:not(.activityinline) {
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 1rem; }
|
||||
@@ -14841,9 +14842,11 @@ span.editinstructions {
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
max-width: 100%; }
|
||||
.activity-item .inplaceeditable .quickeditlink,
|
||||
.activity-item .afterlink {
|
||||
margin: 1.5rem 0 0.2rem 0.5rem; }
|
||||
.activity-item .activityname .afterlink {
|
||||
margin-left: 0.5rem; }
|
||||
.activity-item .activityname .inplaceeditable .quickeditlink {
|
||||
z-index: 2;
|
||||
margin-left: 0.5rem; }
|
||||
.activity-item .action-menu-item {
|
||||
display: flex;
|
||||
align-items: center; }
|
||||
|
||||
Reference in New Issue
Block a user