MDL-73462 course: Introduce course category tertiary navigation

Update the category management page.
This commit is contained in:
Peter Dias
2022-03-01 17:57:24 +08:00
parent 9cd77c4130
commit f1959af7f6
20 changed files with 694 additions and 81 deletions
+4 -1
View File
@@ -183,7 +183,10 @@ switch ($context->contextlevel) {
break;
}
$PAGE->set_navigation_overflow_state(false);
// In a course category context we leverage overflow for the tertiary navigation
if ($context->contextlevel != CONTEXT_COURSECAT) {
$PAGE->set_navigation_overflow_state(false);
}
// Within a course context we need to explicitly set active tab as there isn't a reference in the nav tree.
if ($context->contextlevel == CONTEXT_COURSE) {
+5 -1
View File
@@ -126,7 +126,11 @@ if (!is_null($reportuser)) {
$rolenames = role_get_names($context);
}
$PAGE->set_navigation_overflow_state(false);
// In a course category context we leverage overflow for the tertiary navigation
if ($context->contextlevel != CONTEXT_COURSECAT) {
$PAGE->set_navigation_overflow_state(false);
}
echo $OUTPUT->header();
if ($context->contextlevel == CONTEXT_COURSE || $context->contextlevel == CONTEXT_MODULE) {
echo $OUTPUT->render_participants_tertiary_nav($course);
+5 -1
View File
@@ -204,7 +204,11 @@ if ($capability && ($allowoverrides || ($allowsafeoverrides && is_safe_capabilit
}
}
$PAGE->set_navigation_overflow_state(false);
// When we are within a category context we leave it to the overflow state to display additional nav nodes.
if ($context->contextlevel != CONTEXT_COURSECAT) {
$PAGE->set_navigation_overflow_state(false);
}
echo $OUTPUT->header();
if ($context->contextlevel == CONTEXT_COURSE || $context->contextlevel == CONTEXT_MODULE) {
echo $OUTPUT->render_participants_tertiary_nav($course);
+11
View File
@@ -2777,6 +2777,17 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
return has_capability('moodle/category:manage', $this->get_context());
}
/**
* Checks whether the category has access to content bank
*
* @return bool
*/
public function has_contentbank() {
$cb = new \core_contentbank\contentbank();
return ($cb->is_context_allowed($this->get_context()) &&
has_capability('moodle/contentbank:access', $this->get_context()));
}
/**
* Returns true if the user has the manage capability on the parent category.
* @return bool
+19 -22
View File
@@ -173,6 +173,14 @@ class helper {
$manageurl = new \moodle_url('/course/management.php', array('categoryid' => $category->id));
$baseurl = new \moodle_url($manageurl, array('sesskey' => \sesskey()));
$actions = array();
// View link.
$actions['view'] = [
'url' => new \moodle_url('/course/index.php', ['categoryid' => $category->id]),
'icon' => null,
'string' => get_string('view')
];
// Edit.
if ($category->can_edit()) {
$actions['edit'] = array(
@@ -252,36 +260,15 @@ class helper {
);
}
// Assign roles.
if ($category->can_review_roles()) {
$actions['assignroles'] = array(
'url' => new \moodle_url('/admin/roles/assign.php', array('contextid' => $category->get_context()->id,
'returnurl' => $manageurl->out_as_local_url(false))),
'icon' => new \pix_icon('t/assignroles', new \lang_string('assignroles', 'role')),
'string' => new \lang_string('assignroles', 'role')
);
}
// Permissions.
if ($category->can_review_permissions()) {
$actions['permissions'] = array(
'url' => new \moodle_url('/admin/roles/permissions.php', array('contextid' => $category->get_context()->id,
'returnurl' => $manageurl->out_as_local_url(false))),
'url' => new \moodle_url('/admin/roles/permissions.php', ['contextid' => $category->get_context()->id]),
'icon' => new \pix_icon('i/permissions', new \lang_string('permissions', 'role')),
'string' => new \lang_string('permissions', 'role')
);
}
// Check permissions.
if ($category->can_review_permissions()) {
$actions['checkroles'] = array(
'url' => new \moodle_url('/admin/roles/check.php', array('contextid' => $category->get_context()->id,
'returnurl' => $manageurl->out_as_local_url(false))),
'icon' => new \pix_icon('i/checkpermissions', new \lang_string('checkpermissions', 'role')),
'string' => new \lang_string('checkpermissions', 'role')
);
}
// Context locking.
if (!empty($CFG->contextlocking) && has_capability('moodle/site:managecontextlocks', $category->get_context())) {
$parentcontext = $category->get_context()->get_parent_context();
@@ -351,6 +338,16 @@ class helper {
}
}
// Content bank.
if ($category->has_contentbank()) {
$url = new \moodle_url('/contentbank/index.php', ['contextid' => $category->get_context()->id]);
$actions['contentbank'] = [
'url' => $url,
'icon' => new \pix_icon('i/contentbank', ''),
'string' => get_string('contentbank')
];
}
return $actions;
}
+16 -1
View File
@@ -64,12 +64,16 @@ class core_course_management_renderer extends plugin_renderer_base {
/**
* Displays a heading for the management pages.
*
* @deprecated since Moodle 4.0. This is now handled/replaced with the tertiary navigation
* @todo Final deprecation MDL-73975
* @param string $heading The heading to display
* @param string|null $viewmode The current view mode if there are options.
* @param int|null $categoryid The currently selected category if there is one.
* @return string
*/
public function management_heading($heading, $viewmode = null, $categoryid = null) {
debugging('management_heading() is deprecated. Use the class manage_categories_action_bar instead.', DEBUG_DEVELOPER);
$html = html_writer::start_div('coursecat-management-header clearfix');
if (!empty($heading)) {
$html .= $this->heading($heading);
@@ -1294,11 +1298,13 @@ class core_course_management_renderer extends plugin_renderer_base {
/**
* Renders html to display a course search form
*
* @deprecated since Moodle 4.0. This is now handled within manage_categories_action_bar
* @todo Final deprecation MDL-73975
* @param string $value default value to populate the search field
* @return string
*/
public function course_search_form($value = '') {
debugging('course_search_form() is deprecated. Use the class manage_categories_action_bar instead.', DEBUG_DEVELOPER);
$data = [
'action' => new moodle_url('/course/management.php'),
'btnclass' => 'btn-primary',
@@ -1337,4 +1343,13 @@ class core_course_management_renderer extends plugin_renderer_base {
return $html;
}
/**
* Render the tertiary nav for the manage categories page.
*
* @param \core_course\output\manage_categories_action_bar $actionbar
* @return string The renderered template
*/
public function render_action_bar(\core_course\output\manage_categories_action_bar $actionbar): string {
return $this->render_from_template('core_course/manage_category_actionbar', $actionbar->export_for_template($this));
}
}
@@ -0,0 +1,171 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle 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
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_course\output;
use context_coursecat;
use core_course_category;
use course_request;
use moodle_page;
use moodle_url;
/**
* Class responsible for generating the action bar (tertiary nav) elements in an individual category page
*
* @package core
* @copyright 2021 Peter Dias
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_action_bar extends manage_categories_action_bar {
/**
* @var object The current category we are referring to.
*/
protected $category;
/**
* Constructor category_action_bar
*
* @param moodle_page $page The page object
* @param object $category
* @param object|null $course The course that we are generating the nav for
* @param string|null $searchvalue
*/
public function __construct(moodle_page $page, object $category, ?object $course = null, ?string $searchvalue = null) {
$this->category = $category;
parent::__construct($page, 'courses', $course, $searchvalue);
}
/**
* Gets the url_select to be displayed in the participants page if available.
*
* @param \renderer_base $output
* @return object|null The content required to render the url_select
*/
protected function get_category_select(\renderer_base $output): ?object {
if (!$this->searchvalue && !core_course_category::is_simple_site()) {
$categories = core_course_category::make_categories_list();
if (count($categories) > 1) {
foreach ($categories as $id => $cat) {
$url = new moodle_url($this->page->url, ['categoryid' => $id]);
$options[$url->out()] = $cat;
}
$currenturl = new moodle_url($this->page->url, ['categoryid' => $this->category->id]);
$select = new \url_select($options, $currenturl, null);
$select->set_label(get_string('categories'), ['class' => 'sr-only']);
$select->class .= ' text-truncate w-100';
return $select->export_for_template($output);
}
}
return null;
}
/**
* Gets the additional options to be displayed within a 'More' dropdown in the tertiary navigation.
* The predefined order defined by UX is:
* - Add a course
* - Add a sub cat
* - Manage course
* - Request a course
* - Course pending approval
*
* @return array
*/
protected function get_additional_category_options(): array {
global $CFG, $DB;
if ($this->category->is_uservisible()) {
$context = get_category_or_system_context($this->category->id);
if (has_capability('moodle/course:create', $context)) {
$params = [
'category' => $this->category->id ?: $CFG->defaultrequestcategory,
'returnto' => $this->category->id ? 'category' : 'topcat'
];
$options[0] = [
'url' => new moodle_url('/course/edit.php', $params),
'string' => get_string('addnewcourse')
];
}
if (!empty($CFG->enablecourserequests)) {
// Display an option to request a new course.
if (course_request::can_request($context)) {
$params = [];
if ($context instanceof context_coursecat) {
$params['category'] = $context->instanceid;
}
$options[3] = [
'url' => new moodle_url('/course/request.php', $params),
'string' => get_string('requestcourse')
];
}
// Display the manage pending requests option.
if (has_capability('moodle/site:approvecourse', $context)) {
$disabled = !$DB->record_exists('course_request', array());
if (!$disabled) {
$options[4] = [
'url' => new moodle_url('/course/pending.php'),
'string' => get_string('coursespending')
];
}
}
}
}
if ($this->category->can_create_course() || $this->category->has_manage_capability()) {
// Add 'Manage' button if user has permissions to edit this category.
$options[2] = [
'url' => new moodle_url('/course/management.php', ['categoryid' => $this->category->id]),
'string' => get_string('managecourses')
];
if ($this->category->has_manage_capability()) {
$addsubcaturl = new moodle_url('/course/editcategory.php', array('parent' => $this->category->id));
$options[1] = [
'url' => $addsubcaturl,
'string' => get_string('addsubcategory')
];
}
}
// We have stored the options in a predefined order. Sort it based on index and return.
if (isset($options)) {
sort($options);
return ['options' => $options];
}
return [];
}
/**
* Export the content to be displayed on the category page.
*
* @param \renderer_base $output
* @return array Consists of the following:
* - categoryselect A list of available categories to be fed into a urlselect
* - search The course search form
* - additionaloptions Additional actions that can be performed in a category
*/
public function export_for_template(\renderer_base $output): array {
return [
'categoryselect' => $this->get_category_select($output),
'search' => $this->get_search_form(),
'additionaloptions' => $this->get_additional_category_options()
];
}
}
@@ -0,0 +1,156 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle 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
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_course\output;
use moodle_page;
use moodle_url;
/**
* Class responsible for generating the action bar (tertiary nav) elements in the category management page
*
* @package core
* @copyright 2021 Peter Dias
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class manage_categories_action_bar implements \renderable {
/** @var object $course The course we are dealing with. */
protected $course;
/** @var moodle_page $page The current page. */
protected $page;
/** @var string|null $viewmode The viewmode of the underlying page - Course and categories, categories or courses */
protected $viewmode;
/** @var string|null $heading The heading to display */
protected $heading;
/** @var string|null $searchvalue The search value if any */
protected $searchvalue;
/**
* Constructor for the manage_categories_action_bar
*
* @param moodle_page $page The page object
* @param string $viewmode The type of page we are viewing.
* @param object|null $course The course that we are generating the nav for
* @param string|null $searchvalue The search value if applicable
*/
public function __construct(moodle_page $page, string $viewmode, ?object $course, ?string $searchvalue) {
$this->course = $course;
$this->page = $page;
$this->viewmode = $viewmode;
$this->searchvalue = $searchvalue;
if ($searchvalue) {
$this->heading = get_string('searchresults');
}
}
/**
* Gets the url_select to be displayed in the participants page if available.
*
* @param \renderer_base $output
* @return object|null The content required to render the url_select
*/
protected function get_dropdown(\renderer_base $output): ?object {
// If a search is being performed then no need to display the dropdown.
if ($this->searchvalue) {
return null;
}
$modes = \core_course\management\helper::get_management_viewmodes();
$activeurl = null;
$content = [];
foreach ($modes as $mode => $description) {
$url = new moodle_url($this->page->url, ['view' => $mode]);
$content[$url->out()] = $description;
if ($this->viewmode == $mode) {
$activeurl = $url->out();
$this->heading = get_string("manage$mode");
}
}
// Default to the first option if asking for default. This is combined.
if (!$activeurl && $this->viewmode === 'default') {
$activeurl = array_key_first($content);
$this->heading = get_string("managecombined");
}
if ($content) {
$urlselect = new \url_select($content, $activeurl, null);
$urlselect->set_label(get_string('viewing'), ['class' => 'sr-only']);
return $urlselect->export_for_template($output);
}
return null;
}
/**
* Gets the url_select to be displayed in the participants page if available.
*
* @param \renderer_base $output
* @return object|null The content required to render the url_select
*/
protected function get_category_select(\renderer_base $output): ?object {
if (!$this->searchvalue && $this->viewmode === 'courses') {
$categories = \core_course_category::make_categories_list(array('moodle/category:manage', 'moodle/course:create'));
$currentcat = $this->page->url->param('categoryid');
foreach ($categories as $id => $cat) {
$url = new moodle_url($this->page->url, ['categoryid' => $id]);
if ($id == $currentcat) {
$currenturl = $url->out();
}
$options[$url->out()] = $cat;
}
$select = new \url_select($options, $currenturl, null);
$select->set_label(get_string('category'), ['class' => 'sr-only']);
$select->class .= ' text-truncate w-100';
return $select->export_for_template($output);
}
return null;
}
/**
* Get the search box
*
* @return array
*/
protected function get_search_form(): array {
return [
'action' => new moodle_url('/course/management.php'),
'btnclass' => 'btn-primary',
'inputname' => 'search',
'searchstring' => get_string('searchcourses'),
'query' => $this->searchvalue
];
}
/**
* Export the content to be displayed on the participants page.
*
* @param \renderer_base $output
* @return array Consists of the following:
* - urlselect A stdclass representing the standard navigation options to be fed into a urlselect
* - renderedcontent Rendered content to be displayed in line with the tertiary nav
*/
public function export_for_template(\renderer_base $output): array {
return [
'urlselect' => $this->get_dropdown($output),
'categoryselect' => $this->get_category_select($output),
'search' => $this->get_search_form(),
'heading' => $this->heading,
];
}
}
+5
View File
@@ -112,6 +112,11 @@ if ($id) {
$PAGE->set_context($catcontext);
}
// We are adding a new course and have a category context.
if (isset($catcontext)) {
$PAGE->set_secondary_active_tab('categorymain');
}
// Prepare course and the editor.
$editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>false, 'noclean'=>true);
$overviewfilesoptions = course_overviewfiles_options($course);
+4
View File
@@ -650,9 +650,13 @@ function get_category_or_system_context($categoryid) {
* Print the buttons relating to course requests.
*
* @param context $context current page context.
* @deprecated since Moodle 4.0
* @todo Final deprecation MDL-73976
*/
function print_course_request_buttons($context) {
global $CFG, $DB, $OUTPUT;
debugging("print_course_request_buttons() is deprecated. " .
"This is replaced with the category_action_bar tertiary navigation.", DEBUG_DEVELOPER);
if (empty($CFG->enablecourserequests)) {
return;
}
+3 -9
View File
@@ -108,7 +108,7 @@ $PAGE->set_pagelayout('admin');
$PAGE->set_title($strmanagement);
$PAGE->set_heading($pageheading);
$PAGE->requires->js_call_amd('core_course/copy_modal', 'init', array($context->id));
$PAGE->set_secondary_active_tab('managecategory');
$PAGE->set_secondary_active_tab('categorymain');
// This is a system level page that operates on other contexts.
require_login();
@@ -473,12 +473,8 @@ $displaycourselisting = ($viewmode === 'default' || $viewmode === 'combined' ||
$displaycoursedetail = (isset($courseid));
echo $renderer->header();
if (!$issearching) {
echo $renderer->management_heading($strmanagement, $viewmode, $categoryid);
} else {
echo $renderer->management_heading(new lang_string('searchresults'));
}
$actionbar = new \core_course\output\manage_categories_action_bar($PAGE, $viewmode, $course, $search);
echo $renderer->render_action_bar($actionbar);
if (count($notificationspass) > 0) {
echo $renderer->notification(join('<br />', $notificationspass), 'notifysuccess');
@@ -489,8 +485,6 @@ if (count($notificationsfail) > 0) {
// Start the management form.
echo $renderer->course_search_form($search);
echo $renderer->management_form_start();
echo $renderer->accessible_skipto_links($displaycategorylisting, $displaycourselisting, $displaycoursedetail);
+2 -42
View File
@@ -1667,14 +1667,8 @@ class core_course_renderer extends plugin_renderer_base {
$coursecat = core_course_category::get(is_object($category) ? $category->id : $category);
}
$site = get_site();
$output = '';
if ($coursecat->can_create_course() || $coursecat->has_manage_capability()) {
// Add 'Manage' button if user has permissions to edit this category.
$managebutton = $this->single_button(new moodle_url('/course/management.php',
array('categoryid' => $coursecat->id)), get_string('managecourses'), 'get');
$this->page->set_button($managebutton);
}
$actionbar = new \core_course\output\category_action_bar($this->page, $coursecat);
$output = $this->render_from_template('core_course/category_actionbar', $actionbar->export_for_template($this));
if (core_course_category::is_simple_site()) {
// There is only one category in the system, do not display link to it.
@@ -1686,17 +1680,6 @@ class core_course_renderer extends plugin_renderer_base {
} else {
$strfulllistofcourses = get_string('fulllistofcourses');
$this->page->set_title("$site->shortname: $strfulllistofcourses");
// Print the category selector
$categorieslist = core_course_category::make_categories_list();
if (count($categorieslist) > 1) {
$output .= html_writer::start_tag('div', array('class' => 'categorypicker'));
$select = new single_select(new moodle_url('/course/index.php'), 'categoryid',
core_course_category::make_categories_list(), $coursecat->id, null, 'switchcategory');
$select->set_label(get_string('categories').':', ['class' => 'sr-only']);
$output .= $this->render($select);
$output .= html_writer::end_tag('div'); // .categorypicker
}
}
// Print current category description
@@ -1741,33 +1724,10 @@ class core_course_renderer extends plugin_renderer_base {
$catdisplayoptions['viewmoreurl'] = new moodle_url($baseurl, array('browse' => 'categories', 'page' => 1));
}
$chelper->set_courses_display_options($coursedisplayoptions)->set_categories_display_options($catdisplayoptions);
// Add course search form.
$output .= $this->course_search_form();
// Display course category tree.
$output .= $this->coursecat_tree($chelper, $coursecat);
// Add action buttons
$output .= $this->container_start('buttons mt-3');
if ($coursecat->is_uservisible()) {
$context = get_category_or_system_context($coursecat->id);
if (has_capability('moodle/course:create', $context)) {
// Print link to create a new course, for the 1st available category.
if ($coursecat->id) {
$url = new moodle_url('/course/edit.php', array('category' => $coursecat->id, 'returnto' => 'category'));
} else {
$url = new moodle_url('/course/edit.php',
array('category' => $CFG->defaultrequestcategory, 'returnto' => 'topcat'));
}
$output .= $this->single_button($url, get_string('addnewcourse'), 'get');
}
ob_start();
print_course_request_buttons($context);
$output .= ob_get_contents();
ob_end_clean();
}
$output .= $this->container_end();
return $output;
}
@@ -0,0 +1,117 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template core_course/category_actionbar
Displays the tertiary nav for the category page
Context variables required for this template:
* urlselect Object - The content to be rendered within the url_select
* renderedcontent String - Any additional content/actions to be displayed inline with the select box
Example context (json):
{
"categoryselect" : {
"formid": "url_select_f61834256d7754158",
"classes": "urlselect",
"label": "",
"disabled": false,
"title":null,
"id":"url_select61834256d7754159",
"sesskey":"LWILINyZMH",
"action":"http:\/\/localhost\/stable_master\/course\/jumpto.php",
"showbutton":null,
"options": [
{
"name":"Category 1",
"value":"\/course\/index.php\/?categoryid=279"
},
{
"name":"Category 2",
"value":"\/course\/index.php\/?categoryid=280"
},
{
"name":"Category 3",
"value":"\/course\/index.php\/?categoryid=281"
}
],
"labelattributes":[],
"helpicon":false,
"attributes":[]
},
"search": {
"action": "https://moodle.local/admin/search.php",
"extraclasses": "my-2",
"inputname": "search",
"inform": false,
"searchstring": "Search settings",
"value": "policy",
"btnclass": "primary",
"query": "themedesigner",
"hiddenfields": [
{
"name": "context",
"value": "11"
}
]
},
"additionaloptions": {
"options": [
{
"url": "\/course\/index.php\/?categoryid=281",
"string": "Action 1"
"attributes": [
{
"name": "data-id",
"value": "1"
},
{
"name": "aria-role",
"value": "test"
}
]
}
]
}
}
}}
<div class="container-fluid tertiary-navigation" id="action_bar">
<div class="row">
{{#categoryselect}}
<div class="navitem">
{{> core/url_select }}
</div>
{{/categoryselect}}
{{#search}}
<div class="navitem">
{{> core/search_input }}
</div>
{{/search}}
{{#additionaloptions}}
<div class="ml-auto d-flex">
<div class="navitem dropdown">
<button aria-label="{{#str}}moreactions{{/str}}" class="btn btn-secondary dropdown-toggle" id="dropdown-actions" data-toggle="dropdown" aria-haspopup="true" aria-controls="moreactionsmenu">
{{#str}}moremenu{{/str}}
</button>
<div id="moreactionsmenu" class="dropdown-menu" aria-labelledby="dropdown-actions" role="menu">
{{#options}}
<a role="menuitem" class="dropdown-item" {{#attributes}}{{name}}="{{value}}"{{/attributes}} href="{{url}}" tabindex="-1">{{string}}</a>
{{/options}}
</div>
</div>
</div>
{{/additionaloptions}}
</div>
</div>
@@ -0,0 +1,119 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template core_course/manage_category_actionbar
Displays the tertiary nav for the category page
Context variables required for this template:
* urlselect Object - The content to be rendered within the url_select
* renderedcontent String - Any additional content/actions to be displayed inline with the select box
Example context (json):
{
"urlselect" : {
"formid": "url_select_f61834256d7754158",
"classes": "urlselect",
"label": "",
"disabled": false,
"title":null,
"id":"url_select61834256d7754159",
"sesskey":"LWILINyZMH",
"action":"http:\/\/localhost\/stable_master\/course\/jumpto.php",
"showbutton":null,
"options": [
{
"name":"Course and categories",
"value":"\/course\/index.php\/?categoryid=279"
},
{
"name":"Courses",
"value":"\/course\/index.php\/?categoryid=280"
},
{
"name":"Categories",
"value":"\/course\/index.php\/?categoryid=281"
}
],
"labelattributes":[],
"helpicon":false,
"attributes":[]
},
"categoryselect" : {
"formid": "url_select_f61834256d7754158",
"classes": "urlselect",
"label": "",
"disabled": false,
"title":null,
"id":"url_select61834256d7754159",
"sesskey":"LWILINyZMH",
"action":"http:\/\/localhost\/stable_master\/course\/jumpto.php",
"showbutton":null,
"options": [
{
"name":"Category 1",
"value":"\/course\/index.php\/?categoryid=279"
},
{
"name":"Category 2",
"value":"\/course\/index.php\/?categoryid=280"
},
{
"name":"Category 3",
"value":"\/course\/index.php\/?categoryid=281"
}
],
"labelattributes":[],
"helpicon":false,
"attributes":[]
},
"search": {
"action": "https://moodle.local/admin/search.php",
"extraclasses": "my-2",
"inputname": "search",
"inform": false,
"searchstring": "Search settings",
"value": "policy",
"btnclass": "primary",
"query": "themedesigner",
"hiddenfields": [
{
"name": "context",
"value": "11"
}
]
},
"heading": "Heading of page"
}
}}
<div class="container-fluid tertiary-navigation" id="action_bar">
<div class="row">
{{#urlselect}}
<div class="navitem">
{{> core/url_select }}
</div>
{{/urlselect}}
{{#categoryselect}}
<div class="navitem">
{{> core/url_select }}
</div>
{{/categoryselect}}
{{#search}}
<div class="navitem">
{{> core/search_input }}
</div>
{{/search}}
</div>
</div>
<h2>{{heading}}</h2>
-1
View File
@@ -1118,7 +1118,6 @@ class core_course_management_helper_test extends advanced_testcase {
$this->assertArrayHasKey('moveup', $actions);
$this->assertArrayHasKey('movedown', $actions);
$this->assertArrayHasKey('delete', $actions);
$this->assertArrayHasKey('assignroles', $actions);
$this->assertArrayHasKey('permissions', $actions);
$this->assertArrayHasKey('cohorts', $actions);
$this->assertArrayHasKey('filters', $actions);
+3
View File
@@ -1225,6 +1225,8 @@ $string['makeavailable'] = 'Make available';
$string['makeeditable'] = 'If you make \'{$a}\' editable by the web server process (eg apache) then you could edit this file directly from this page';
$string['makethismyhome'] = 'Make this my home page';
$string['makeunavailable'] = 'Make unavailable';
$string['managecombined'] = 'Manage course categories and courses';
$string['managecategories'] = 'Manage course categories';
$string['manageblocks'] = 'Blocks';
$string['managecategorythis'] = 'Manage this category';
$string['managecontentbanktypes'] = 'Manage content types';
@@ -1374,6 +1376,7 @@ $string['movefull'] = 'Move {$a} to this location';
$string['movehere'] = 'Move to here';
$string['moveleft'] = 'Move left';
$string['moremenu'] = 'More';
$string['moreactions'] = 'More actions';
$string['moveright'] = 'Move right';
$string['movesection'] = 'Move section {$a}';
$string['moveselectedcategoriesto'] = 'Move selected categories to';
+8 -2
View File
@@ -586,7 +586,9 @@ class secondary extends view {
// that are redirected to, be in the course context or module context depending on which callback was used.
// Third part plugins were checked to see if any existing plugins had settings in a system context and none were found.
// The request of third party developers is to keep their settings within the specified context.
if ($this->page->context->contextlevel != CONTEXT_COURSE && $this->page->context->contextlevel != CONTEXT_MODULE) {
if ($this->page->context->contextlevel != CONTEXT_COURSE
&& $this->page->context->contextlevel != CONTEXT_MODULE
&& $this->page->context->contextlevel != CONTEXT_COURSECAT) {
return null;
}
@@ -657,8 +659,12 @@ class secondary extends view {
$settingsnav = $this->page->settingsnav;
$mainnode = $settingsnav->find('categorysettings', self::TYPE_CONTAINER);
$nodes = $this->get_default_category_mapping();
$siteadmin = $settingsnav->find('root', self::TYPE_SITE_ADMIN);
if ($mainnode) {
// If an admin is viewing a category context then load the site admin menu.
if ($siteadmin) {
$this->load_admin_navigation();
} else if ($mainnode) {
$url = new \moodle_url('/course/index.php', ['categoryid' => $this->context->instanceid]);
$this->add($this->context->get_context_name(), $url, self::TYPE_CONTAINER, null, 'categorymain');
+2 -1
View File
@@ -5426,7 +5426,8 @@ class settings_navigation extends navigation_node {
$categorynode->add(get_string('editcategorythis'), $editurl, self::TYPE_SETTING, null, 'edit', new pix_icon('i/edit', ''));
$addsubcaturl = new moodle_url('/course/editcategory.php', array('parent' => $catcontext->instanceid));
$categorynode->add(get_string('addsubcategory'), $addsubcaturl, self::TYPE_SETTING, null, 'addsubcat', new pix_icon('i/withsubcat', ''));
$categorynode->add(get_string('addsubcategory'), $addsubcaturl, self::TYPE_SETTING, null,
'addsubcat', new pix_icon('i/withsubcat', ''))->set_show_in_secondary_navigation(false);
}
// Assign local roles
@@ -0,0 +1,44 @@
@core @core_course
Feature: Role assignments can be made at the category level
In order to grant a user different capabilities
As a user
I can assign roles in categories
Background:
Given the following "users" exist:
| username | firstname | lastname |
| manager | Manager | Manager |
And the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| manager | manager | Category | CAT1 |
And I log in as "admin"
@javascript
Scenario: A user with a category role can assign roles
Given I define the allowed role assignments for the "Manager" role as:
| Teacher | Assignable |
And I log out
And I log in as "manager"
And I am on course index
When I follow "Cat 1"
And I navigate to "Permissions" in current page administration
Then I should see "Assign roles" in the "jump" "select"
@javascript
Scenario: A user with a category role cannot assign roles if there are no roles to assign
Given I define the allowed role assignments for the "Manager" role as:
| Manager | Not assignable |
| Course creator | Not assignable |
| Teacher | Not assignable |
| Non-editing teacher | Not assignable |
| Student | Not assignable |
And I change window size to "large"
And I log out
And I log in as "manager"
And I am on course index
When I follow "Cat 1"
And I navigate to "Permissions" in current page administration
Then I should not see "Assign roles" in the "jump" "select"