first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,41 @@
<?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/>.
/**
* Renderers to align Moodle's HTML with that expected by Bootstrap
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace theme_classic\output;
defined('MOODLE_INTERNAL') || die;
/**
* Renderers to align Moodle's HTML with that expected by Bootstrap
*
* Note: This class is required to avoid inheriting Boost's core_renderer,
* which removes the edit button required by Classic.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_renderer extends \core_renderer {
}
@@ -0,0 +1,50 @@
<?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/>.
/**
* Overridden fontawesome icons.
*
* @package theme_classic
* @copyright 2019 Moodle
* @author Bas Brands <bas@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace theme_classic\output;
defined('MOODLE_INTERNAL') || die();
/**
* Class overriding some of the Moodle default FontAwesome icons.
*
* @package theme_classic
* @copyright 2019 Moodle
* @author Bas Brands <bas@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class icon_system_fontawesome extends \core\output\icon_system_fontawesome {
/**
* Change the core icon map.
*
* @return Array replaced icons.
*/
public function get_core_icon_map() {
$iconmap = parent::get_core_icon_map();
$iconmap['core:i/navigationitem'] = 'fa-square';
return $iconmap;
}
}
@@ -0,0 +1,46 @@
<?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/>.
/**
* Privacy Subsystem implementation for theme_classic.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace theme_classic\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* The classic theme does not store any data.
*
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
+179
View File
@@ -0,0 +1,179 @@
<?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/>.
/**
* classic config.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
$THEME->name = 'classic';
$THEME->sheets = [];
$THEME->layouts = [
// Most backwards compatible layout without the blocks - this is the layout used by default.
'base' => array(
'file' => 'columns.php',
'regions' => array(),
),
// Standard layout with blocks, this is recommended for most pages with general information.
'standard' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
),
// Main course page.
'course' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('langmenu' => true),
),
'coursecategory' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// Part of course, typical for modules - default page layout if $cm specified in require_login().
'incourse' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
),
// The site home page.
'frontpage' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('nofullheader' => true),
),
// Server administration scripts.
'admin' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// My courses page.
'mycourses' => array(
'file' => 'columns.php',
'regions' => ['side-pre', 'side-post'],
'defaultregion' => 'side-pre',
),
// My dashboard page.
'mydashboard' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('langmenu' => true),
),
// My public page.
'mypublic' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
'login' => array(
'theme' => 'boost',
'file' => 'login.php',
'regions' => array(),
'options' => array('langmenu' => true),
),
// Pages that appear in pop-up windows - no navigation, no blocks, no header.
'popup' => array(
'file' => 'contentonly.php',
'regions' => array(),
'options' => array(
'nofooter' => true,
'nonavbar' => true,
'activityheader' => [
'notitle' => true,
'nocompletion' => true,
'nodescription' => true
]
),
),
// No blocks and minimal footer - used for legacy frame layouts only!
'frametop' => array(
'file' => 'contentonly.php',
'regions' => array(),
'options' => array(
'nofooter' => true,
'nocoursefooter' => true,
'activityheader' => [
'nocompletion' => true
]),
),
// Embeded pages, like iframe/object embeded in moodleform - it needs as much space as possible.
'embedded' => array(
'theme' => 'boost',
'file' => 'embedded.php',
'regions' => array()
),
// Used during upgrade and install, and for the 'This site is undergoing maintenance' message.
// This must not have any blocks, links, or API calls that would lead to database or cache interaction.
// Please be extremely careful if you are modifying this layout.
'maintenance' => array(
'theme' => 'boost',
'file' => 'maintenance.php',
'regions' => array(),
),
// Should display the content and basic headers only.
'print' => array(
'file' => 'contentonly.php',
'regions' => array(),
'options' => array('nofooter' => true, 'nonavbar' => false, 'noactivityheader' => true),
),
// The pagelayout used when a redirection is occuring.
'redirect' => array(
'theme' => 'boost',
'file' => 'embedded.php',
'regions' => array(),
),
// The pagelayout used for reports.
'report' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// The pagelayout used for safebrowser and securewindow.
'secure' => array(
'file' => 'secure.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre'
)
];
$THEME->editor_sheets = [];
$THEME->parents = ['boost'];
$THEME->enable_dock = false;
$THEME->extrascsscallback = 'theme_classic_get_extra_scss';
$THEME->prescsscallback = 'theme_classic_get_pre_scss';
$THEME->precompiledcsscallback = 'theme_classic_get_precompiled_css';
$THEME->yuicssmodules = array();
$THEME->rendererfactory = 'theme_overridden_renderer_factory';
$THEME->scss = function($theme) {
return theme_classic_get_main_scss_content($theme);
};
$THEME->usefallback = true;
$THEME->iconsystem = '\\theme_classic\\output\\icon_system_fontawesome';
$THEME->haseditswitch = false;
+42
View File
@@ -0,0 +1,42 @@
<?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/>.
/**
* Language file.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
// Raw SCSS setting.
$string['choosereadme'] = 'Classic is a highly-customisable theme, based on Boost, with an alternative navigation layout. This theme is intended to be used directly, or as a parent theme when creating or updating custom themes to utilise Bootstrap 4.';
$string['configtitle'] = 'Classic';
$string['navbardark'] = 'Use a dark style navbar';
$string['navbardarkdesc'] = 'Swaps text and background colours for the navbar at the top of the page between dark and light.';
$string['pluginname'] = 'Classic';
$string['presetfiles'] = 'Additional theme preset files';
$string['presetfiles_desc'] = 'Preset files can be used to dramatically alter the appearance of the theme. See <a href="https://docs.moodle.org/dev/Boost_Presets">Boost presets</a> for information on creating and sharing your own preset files, and see the <a href="https://moodle.net/search?q=boost+presets">Presets repository</a> for presets that others have shared.';
$string['preset'] = 'Theme preset';
$string['preset_desc'] = 'Pick a preset to broadly change the look of the theme.';
$string['privacy:metadata'] = 'The Classic theme does not store any personal data.';
$string['region-side-post'] = 'Right';
$string['region-side-pre'] = 'Left';
$string['sitetitle'] = 'Site title';
$string['totop'] = 'Go to top';
+50
View File
@@ -0,0 +1,50 @@
<?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/>.
/**
* The columns layout for the classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$bodyattributes = $OUTPUT->body_attributes();
$blockspre = $OUTPUT->blocks('side-pre');
$blockspost = $OUTPUT->blocks('side-post');
$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT);
$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT);
$PAGE->set_secondary_navigation(false);
$renderer = $PAGE->get_renderer('core');
$header = $PAGE->activityheader;
$headercontent = $header->export_for_template($renderer);
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'sidepreblocks' => $blockspre,
'sidepostblocks' => $blockspost,
'haspreblocks' => $hassidepre,
'haspostblocks' => $hassidepost,
'bodyattributes' => $bodyattributes,
'headercontent' => $headercontent,
];
echo $OUTPUT->render_from_template('theme_classic/columns', $templatecontext);
+41
View File
@@ -0,0 +1,41 @@
<?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/>.
/**
* A one column layout for the classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$bodyattributes = $OUTPUT->body_attributes([]);
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'bodyattributes' => $bodyattributes
];
if (empty($PAGE->layout_options['noactivityheader'])) {
$header = $PAGE->activityheader;
$renderer = $PAGE->get_renderer('core');
$templatecontext['headercontent'] = $header->export_for_template($renderer);
}
echo $OUTPUT->render_from_template('theme_classic/contentonly', $templatecontext);
+46
View File
@@ -0,0 +1,46 @@
<?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/>.
/**
* A secure layout for the classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$bodyattributes = $OUTPUT->body_attributes();
$blockspre = $OUTPUT->blocks('side-pre');
$blockspost = $OUTPUT->blocks('side-post');
$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT);
$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT);
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'sidepreblocks' => $blockspre,
'sidepostblocks' => $blockspost,
'haspreblocks' => $hassidepre,
'haspostblocks' => $hassidepost,
'bodyattributes' => $bodyattributes
];
echo $OUTPUT->render_from_template('theme_classic/secure', $templatecontext);
+158
View File
@@ -0,0 +1,158 @@
<?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/>.
/**
* Classic theme callbacks.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
/**
* Returns the main SCSS content.
*
* @param theme_config $theme The theme config object.
* @return string
*/
function theme_classic_get_main_scss_content($theme) {
global $CFG;
$scss = '';
$filename = !empty($theme->settings->preset) ? $theme->settings->preset : null;
$fs = get_file_storage();
$context = context_system::instance();
$scss .= file_get_contents($CFG->dirroot . '/theme/classic/scss/classic/pre.scss');
if ($filename && ($presetfile = $fs->get_file($context->id, 'theme_classic', 'preset', 0, '/', $filename))) {
$scss .= $presetfile->get_content();
} else {
// Safety fallback - maybe new installs etc.
$scss .= file_get_contents($CFG->dirroot . '/theme/classic/scss/preset/default.scss');
}
$scss .= file_get_contents($CFG->dirroot . '/theme/classic/scss/classic/post.scss');
return $scss;
}
/**
* Get SCSS to prepend.
*
* @param theme_config $theme The theme config object.
* @return array
*/
function theme_classic_get_pre_scss($theme) {
$scss = '';
$configurable = [
// Config key => [variableName, ...].
'brandcolor' => ['primary'],
];
// Prepend variables first.
foreach ($configurable as $configkey => $targets) {
$value = isset($theme->settings->{$configkey}) ? $theme->settings->{$configkey} : null;
if (empty($value)) {
continue;
}
array_map(function($target) use (&$scss, $value) {
$scss .= '$' . $target . ': ' . $value . ";\n";
}, (array) $targets);
}
// Prepend pre-scss.
if (!empty($theme->settings->scsspre)) {
$scss .= $theme->settings->scsspre;
}
return $scss;
}
/**
* Inject additional SCSS.
*
* @param theme_config $theme The theme config object.
* @return string
*/
function theme_classic_get_extra_scss($theme) {
global $CFG;
$content = '';
// Set the page background image.
$imageurl = $theme->setting_file_url('backgroundimage', 'backgroundimage');
if (!empty($imageurl)) {
$content .= '$imageurl: "' . $imageurl . '";';
$content .= file_get_contents($CFG->dirroot .
'/theme/classic/scss/classic/body-background.scss');
}
// Sets the login background image.
$loginbackgroundimageurl = $theme->setting_file_url('loginbackgroundimage', 'loginbackgroundimage');
if (!empty($loginbackgroundimageurl)) {
$content .= 'body.pagelayout-login #page { ';
$content .= "background-image: url('$loginbackgroundimageurl'); background-size: cover;";
$content .= ' }';
}
if (!empty($theme->settings->navbardark)) {
$content .= file_get_contents($CFG->dirroot .
'/theme/classic/scss/classic/navbar-dark.scss');
} else {
$content .= file_get_contents($CFG->dirroot .
'/theme/classic/scss/classic/navbar-light.scss');
}
if (!empty($theme->settings->scss)) {
$content .= $theme->settings->scss;
}
return $content;
}
/**
* Get compiled css.
*
* @return string compiled css
*/
function theme_classic_get_precompiled_css() {
global $CFG;
return file_get_contents($CFG->dirroot . '/theme/classic/style/moodle.css');
}
/**
* Serves any files associated with the theme settings.
*
* @param stdClass $course
* @param stdClass $cm
* @param context $context
* @param string $filearea
* @param array $args
* @param bool $forcedownload
* @param array $options
* @return bool
*/
function theme_classic_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
if ($context->contextlevel == CONTEXT_SYSTEM && ($filearea === 'backgroundimage' || $filearea === 'loginbackgroundimage')) {
$theme = theme_config::load('classic');
// By default, theme files must be cache-able by both browsers and proxies.
if (!array_key_exists('cacheability', $options)) {
$options['cacheability'] = 'public';
}
return $theme->setting_file_serve($filearea, $args, $forcedownload, $options);
} else {
send_file_not_found();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

+2
View File
@@ -0,0 +1,2 @@
// Import All of Bootstrap
@import "../../boost/scss/bootstrap";
@@ -0,0 +1,10 @@
body {
background-image: url($imageurl);
background-size: cover;
}
.region-main .region-main-content {
padding: 0.875rem;
background-color: $body-bg;
border: $card-border-width solid $card-border-color;
@include border-radius($card-border-radius);
}
@@ -0,0 +1,28 @@
$nabvar-bg-color: $dark !default;
.navbar-bootswatch {
@extend .navbar-dark;
background-color: $nabvar-bg-color;
.usermenu {
color: $navbar-dark-color;
.login a {
color: $navbar-dark-color;
}
}
a.dropdown-toggle,
a .usertext {
color: $navbar-dark-active-color;
&:hover,
&:focus {
color: $navbar-dark-hover-color;
}
&.disabled {
color: $navbar-dark-disabled-color;
}
}
.dropdown-menu a .icon {
color: inherit !important; // stylelint-disable-line declaration-no-important
}
}
@@ -0,0 +1,4 @@
.navbar-bootswatch {
@extend .navbar-light;
background-color: $white;
}
+208
View File
@@ -0,0 +1,208 @@
// General Post SCSS for use in all presets.
// Generate the column layout css.
@mixin page_layout($blockswidth) {
$mainwidth-oneblock: (100% - $blockswidth);
$mainwidth-twoblocks: (100% - $blockswidth * 2);
#page-content {
display: flex;
.region-main {
flex: 0 0 100%;
padding: 0 1rem;
max-width: 100%;
}
&.blocks-pre {
.columnleft {
flex: 0 0 $blockswidth;
order: -1;
padding: 0 1rem;
max-width: $blockswidth;
}
.region-main {
flex: 0 0 $mainwidth-oneblock;
max-width: $mainwidth-oneblock;
padding: 0 1rem 0 0;
#region-main {
border: $card-border-width solid $card-border-color;
padding: $card-spacer-x;
@if $enable-rounded {
@include border-radius($card-border-radius);
}
}
}
}
&.blocks-post {
.region-main {
flex: 0 0 $mainwidth-oneblock;
max-width: $mainwidth-oneblock;
padding: 0 0 0 1rem;
}
.columnright {
flex: 0 0 $blockswidth;
padding: 0 1rem;
max-width: $blockswidth;
}
}
&.blocks-pre.blocks-post {
.region-main {
flex: 0 0 $mainwidth-twoblocks;
max-width: $mainwidth-twoblocks;
padding: 0;
}
}
[data-region="blocks-column"] {
width: 100%;
}
}
.empty-region-side-pre {
&.used-region-side-post {
#page-content {
.region-main {
flex: 0 0 $mainwidth-oneblock;
max-width: $mainwidth-oneblock;
padding-left: 1rem;
}
.columnright {
flex: 0 0 $blockswidth;
padding: 0 1rem;
max-width: $blockswidth;
}
}
}
}
.empty-region-side-post {
&.used-region-side-pre {
#page-content {
.region-main {
flex: 0 0 $mainwidth-oneblock;
max-width: $mainwidth-oneblock;
padding-right: 1rem;
}
.columnleft {
flex: 0 0 $blockswidth;
order: -1;
padding: 0 1rem;
max-width: $blockswidth;
}
}
}
}
.used-region-side-post {
&.used-region-side-pre {
#page-content {
.region-main {
flex: 0 0 $mainwidth-twoblocks;
max-width: $mainwidth-twoblocks;
padding: 0;
}
.columnleft {
flex: 0 0 $blockswidth;
order: -1;
padding: 0 1rem;
max-width: $blockswidth;
}
.columnright {
flex: 0 0 $blockswidth;
padding: 0 1rem;
max-width: $blockswidth;
}
}
}
}
}
.path-grade-report-grader .gradeparent {
tr.heading {
top: $navbar-height;
}
th.header {
left: 0;
}
}
// The block column needs some padding on small devices.
@include media-breakpoint-down(sm) {
.blockcolumn,
.region-main {
flex: 0 0 100%;
max-width: 100%;
padding: 0 1rem;
margin-bottom: 1rem;
}
}
// When changing this please check the size of the calendar block.
@include media-breakpoint-up(md) {
@include page_layout(32%);
}
@include media-breakpoint-up(lg) {
@include page_layout(25%);
}
@include media-breakpoint-up(xl) {
@include page_layout(20%);
}
@media print {
#page-content .region-main {
max-width: 100% !important; /* stylelint-disable-line declaration-no-important */
flex: 0 0 100% !important; /* stylelint-disable-line declaration-no-important */
padding: 0 1rem 0 !important; /* stylelint-disable-line declaration-no-important */
}
}
// Settings and Navigation blocks don't render well from default boost.
.block_navigation,
.block_settings {
.block_tree {
&.list > li > ul {
padding-left: 0;
}
.tree_item.branch {
margin-left: 5px;
padding-left: 0.75rem;
}
p.hasicon {
text-indent: 0;
padding-left: 0.75rem;
}
ul {
margin-left: 0.25rem;
padding-left: 1rem;
}
}
}
.block_navigation .block_tree p.hasicon .icon,
.block_settings .block_tree p.hasicon .icon {
margin-right: 5px;
}
// Remove left indenting from root nodes to allow sub-nodes to indent correctly.
.root_node,
.navigation_node {
margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */
padding-left: 0 !important; /* stylelint-disable-line declaration-no-important */
}
.block.block_settings {
#settingsnav {
padding-top: 0 !important; /* stylelint-disable-line declaration-no-important */
}
}
#page-footer {
padding-top: $spacer * .5;
padding-bottom: $spacer * .5;
}
body.hasstickyfooter #page-footer {
padding-bottom: calc(#{$spacer} * .5 + #{$stickyfooter-height});
}
+7
View File
@@ -0,0 +1,7 @@
// General variables for all presets
// Disable the Boost theme reset styling and fixed width content.
$allow-reset-style: false;
$navbar-height: 50px;
$moremenu-height: 50px;
+4
View File
@@ -0,0 +1,4 @@
// This file allows the creation of precompiled css from the core Grunt task.
@import "classic/pre";
@import "preset/default";
@import "classic/post";
+2
View File
@@ -0,0 +1,2 @@
// Import FontAwesome.
@import "../../boost/scss/fontawesome";
+61
View File
@@ -0,0 +1,61 @@
// Import Boost Core moodle CSS
@import "../../boost/scss/moodle";
img.userpicture {
margin-right: 0.5rem;
}
.path-mod-forum {
// Style for the forum subscription mode node.
.subscriptionmode {
color: $body-color;
}
// Style for the currently selected subscription mode.
.activesetting {
color: $body-color;
font-weight: bold;
}
}
.path-mod-book {
#mod_book-chaptersnavigation {
margin: 0 -0.75rem;
@include media-breakpoint-down(sm) {
top: calc(100% - 150px);
z-index: 1;
}
}
.book_content {
margin: 0 30px;
@include media-breakpoint-down(sm) {
margin-left: -10px;
margin-right: -10px;
padding: 0 5px;
}
}
}
.tertiary-navigation {
&.full-width-bottom-border {
width: calc(100% + 2.5rem);
margin-left: -1.25rem;
margin-right: -1.25rem;
@include media-breakpoint-down(sm) {
width: calc(100% + 2rem);
margin-left: -1rem;
margin-right: -1rem;
}
}
}
#page-footer .homelink,
#page-footer .tool_dataprivacy,
#page-footer .purgecaches {
padding-bottom: 5px;
}
+150
View File
@@ -0,0 +1,150 @@
// Bootstrap variables
$white: #fff !default;
$gray-100: #f8f9fa !default;
$gray-200: #e9ecef !default;
$gray-300: #dee2e6 !default;
$gray-400: #ced4da !default;
$gray-500: #8f959e !default;
$gray-600: #6a737b !default;
$gray-700: #495057 !default;
$gray-800: #343a40 !default;
$gray-900: #1d2125 !default;
$black: #000 !default;
$blue: #0f6cbf !default;
$indigo: #6610f2 !default;
$purple: #613d7c !default;
$pink: #e83e8c !default;
$red: #ca3120 !default;
$orange: #f0ad4e !default;
$yellow: #ff7518 !default;
$green: #357a32 !default;
$teal: #20c997 !default;
$cyan: #008196 !default;
$primary: $blue !default;
$success: $green !default;
$info: $cyan !default;
$warning: $orange !default;
$danger: $red !default;
$secondary: $gray-400 !default;
$info-outline: #1f7e9a;
$warning-outline: #a6670e;
// Tables
$table-accent-bg: rgba($black, .03) !default;
// Options
$enable-rounded: true !default;
$enable-responsive-font-sizes: true !default;
// Body
$body-color: $gray-900 !default;
// Fonts
$font-size-base: 0.9375rem !default;
$rfs-base-font-size: 0.9rem !default;
$headings-font-weight: 300 !default;
// Navbar
$navbar-dark-hover-color: rgba($white, 1) !default;
$navbar-light-color: rgba($black, 0.6) !default;
$navbar-light-hover-color: rgba($black, .9) !default;
// Breadcrumbs
$breadcrumb-padding-y: .25rem !default;
$breadcrumb-padding-x: 0 !default;
$breadcrumb-item-padding: .5rem !default;
$breadcrumb-margin-bottom: 0 !default;
$breadcrumb-bg: transparent !default;
$breadcrumb-divider: "/" !default;
$breadcrumb-divider-rtl: "/" !default;
// Alerts
$alert-border-width: 0 !default;
$card-group-margin: .25rem;
// Toasts
$toast-color: $white !default;
$toast-background-color: rgba($gray-900, .95) !default;
$toast-header-color: $gray-100 !default;
$toast-header-background-color: rgba($white, .1) !default;
$input-btn-focus-color: rgba($primary, .75) !default;
$input-border-color: $gray-500 !default;
$dropdown-link-hover-color: $white;
$dropdown-link-hover-bg: $primary;
// stylelint-disable
$theme-colors: () !default;
$theme-colors: map-merge((
primary: $primary,
secondary: $secondary,
success: $success,
info: $info,
warning: $warning,
danger: $danger,
), $theme-colors);
// stylelint-enable
$spacer: 1rem !default;
$spacers: (
0: 0,
1: ($spacer * .25),
2: ($spacer * .5),
3: $spacer,
4: ($spacer * 1.5),
5: ($spacer * 2),
6: ($spacer * 3)
) !default;
// Import FontAwesome.
@import "fontawesome";
// Import All of Bootstrap
@import "bootstrap";
// Import Core moodle CSS
@import "moodle";
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
// Preset CSS
.navbar {
box-shadow: 0 2px 4px rgba(0, 0, 0, .08);
}
// Rounded user pictures
.userpicture {
border-radius: 50%;
}
.block {
background-color: $gray-100;
}
#page-my-index {
background-color: $white;
}
// Reset the default styling back to the bootstrap defaults for
// the secondary outline button because gray-200 is much too light
// for an outline button.
.btn-outline-secondary {
@include button-outline-variant($gray-600);
border-color: $gray-600;
}
.btn-outline-info {
@include button-outline-variant($info-outline);
}
.btn-outline-warning {
@include button-outline-variant($warning-outline);
}
+8
View File
@@ -0,0 +1,8 @@
// Import FontAwesome.
@import "fontawesome";
// Import All of Bootstrap
@import "bootstrap";
// Import Core moodle CSS
@import "moodle";
+118
View File
@@ -0,0 +1,118 @@
<?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/>.
/**
* Classic theme settings file.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
if ($ADMIN->fulltree) {
$settings = new theme_boost_admin_settingspage_tabs('themesettingclassic', get_string('configtitle', 'theme_classic'));
$page = new admin_settingpage('theme_classic_general', get_string('generalsettings', 'theme_boost'));
$name = 'theme_classic/navbardark';
$title = get_string('navbardark', 'theme_classic');
$description = get_string('navbardarkdesc', 'theme_classic');
$setting = new admin_setting_configcheckbox($name, $title, $description, 0);
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
// Unaddable blocks.
$setting = new admin_setting_configtext('theme_classic/unaddableblocks',
get_string('unaddableblocks', 'theme_boost'), get_string('unaddableblocks_desc', 'theme_boost'), '', PARAM_TEXT);
$page->add($setting);
// Preset.
$name = 'theme_classic/preset';
$title = get_string('preset', 'theme_classic');
$description = get_string('preset_desc', 'theme_classic');
$default = 'default.scss';
$context = context_system::instance();
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'theme_classic', 'preset', 0, 'itemid, filepath, filename', false);
$choices = [];
foreach ($files as $file) {
$choices[$file->get_filename()] = $file->get_filename();
}
// These are the built in presets.
$choices['default.scss'] = 'default.scss';
$choices['plain.scss'] = 'plain.scss';
$setting = new admin_setting_configthemepreset($name, $title, $description, $default, $choices, 'classic');
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
// Preset files setting.
$name = 'theme_classic/presetfiles';
$title = get_string('presetfiles', 'theme_classic');
$description = get_string('presetfiles_desc', 'theme_classic');
$setting = new admin_setting_configstoredfile($name, $title, $description, 'preset', 0,
array('maxfiles' => 20, 'accepted_types' => array('.scss')));
$page->add($setting);
// Background image setting.
$name = 'theme_classic/backgroundimage';
$title = get_string('backgroundimage', 'theme_boost');
$description = get_string('backgroundimage_desc', 'theme_boost');
$setting = new admin_setting_configstoredfile($name, $title, $description, 'backgroundimage');
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
$name = 'theme_classic/loginbackgroundimage';
$title = get_string('loginbackgroundimage', 'theme_boost');
$description = get_string('loginbackgroundimage_desc', 'theme_boost');
$setting = new admin_setting_configstoredfile($name, $title, $description, 'loginbackgroundimage');
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
// Variable $body-color.
// We use an empty default value because the default colour should come from the preset.
$name = 'theme_classic/brandcolor';
$title = get_string('brandcolor', 'theme_boost');
$description = get_string('brandcolor_desc', 'theme_boost');
$setting = new admin_setting_configcolourpicker($name, $title, $description, '');
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
// Must add the page after definiting all the settings!
$settings->add($page);
// Advanced settings.
$page = new admin_settingpage('theme_classic_advanced', get_string('advancedsettings', 'theme_boost'));
// Raw SCSS to include before the content.
$setting = new admin_setting_scsscode('theme_classic/scsspre',
get_string('rawscsspre', 'theme_boost'), get_string('rawscsspre_desc', 'theme_boost'), '', PARAM_RAW);
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
// Raw SCSS to include after the content.
$setting = new admin_setting_scsscode('theme_classic/scss', get_string('rawscss', 'theme_boost'),
get_string('rawscss_desc', 'theme_boost'), '', PARAM_RAW);
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
$settings->add($page);
}
File diff suppressed because it is too large Load Diff
+106
View File
@@ -0,0 +1,106 @@
{{!
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 theme_classic/columns
Admin time setting template.
Classic 1-3 column layout template.
Context variables required for this template:
* sitename - The name of the site
* output - The core renderer for the page
* bodyattributes - attributes for the body tag as a string of html attributes
* sidepreblocks - HTML for the blocks
* hasblocks - true if there are blocks on this page
* regionmainsettingsmenu - HTML for the region main settings menu
* hasregionmainsettingsmenu - There is a region main settings menu on this page.
Example context (json):
{
"sitename": "Moodle",
"output": {
"doctype": "<!DOCTYPE html>",
"page_title": "Test page",
"favicon": "favicon.ico",
"main_content": "<h1>Headings make html validators happier</h1>"
},
"bodyattributes":"",
"sidepreblocks": "<h2>Blocks html goes here</h2>",
"sidepostblocks": "<h2>Blocks html goes here</h2>",
"haspreblocks":true,
"haspostblocks":true
}
}}
{{> theme_boost/head }}
<body {{{ bodyattributes }}}>
<div id="page-wrapper" class="d-print-block">
{{{ output.standard_top_of_body_html }}}
{{>theme_classic/navbar}}
<div id="page" class="container-fluid d-print-block">
{{{ output.full_header }}}
<div id="page-content" class="row {{#haspreblocks}} blocks-pre {{/haspreblocks}} {{#haspostblocks}} blocks-post {{/haspostblocks}} d-print-block">
<div id="region-main-box" class="region-main">
{{#hasregionmainsettingsmenu}}
<div id="region-main-settings-menu" class="d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}">
<div> {{{ output.region_main_settings_menu }}} </div>
</div>
{{/hasregionmainsettingsmenu}}
<section id="region-main" class="region-main-content" aria-label="{{#str}}content{{/str}}">
{{#hasregionmainsettingsmenu}}
<div class="region_main_settings_menu_proxy"></div>
{{/hasregionmainsettingsmenu}}
{{{ output.course_content_header }}}
{{#headercontent}}
{{> core/activity_header }}
{{/headercontent}}
{{{ output.main_content }}}
{{{ output.activity_navigation }}}
{{{ output.course_content_footer }}}
</section>
</div>
<div class="columnleft blockcolumn {{#haspreblocks}} has-blocks {{/haspreblocks}}">
<section data-region="blocks-column" class="d-print-none" aria-label="{{#str}}blocks{{/str}}">
{{{ sidepreblocks }}}
</section>
</div>
<div class="columnright blockcolumn {{#haspostblocks}} has-blocks {{/haspostblocks}}">
<section data-region="blocks-column" class="d-print-none" aria-label="{{#str}}blocks{{/str}}">
{{{ sidepostblocks }}}
</section>
</div>
</div>
</div>
{{{ output.standard_after_main_region_html }}}
{{> theme_classic/footer }}
</div>
</body>
</html>
{{#js}}
M.util.js_pending('theme_boost/loader');
require(['theme_boost/loader'], function() {
M.util.js_complete('theme_boost/loader');
});
{{/js}}
@@ -0,0 +1,78 @@
{{!
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 theme_classic/contentonly
Classic 1 column layout template.
Context variables required for this template:
* sitename - The name of the site
* output - The core renderer for the page
* bodyattributes - attributes for the body tag as a string of html attributes
Example context (json):
{
"sitename": "Moodle",
"output": {
"doctype": "<!DOCTYPE html>",
"page_title": "Test page",
"favicon": "favicon.ico",
"main_content": "<h1>Headings make html validators happier</h1>"
},
"bodyattributes":""
}
}}
{{{ output.doctype }}}
<html {{{ output.htmlattributes }}}>
<head>
<title>{{{ output.page_title }}}</title>
<link rel="shortcut icon" href="{{{ output.favicon }}}" />
{{{ output.standard_head_html }}}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body {{{ bodyattributes }}}>
<div id="page-wrapper">
{{{ output.standard_top_of_body_html }}}
<div id="page" class="container-fluid">
<div id="page-content" class="row">
<div id="region-main-box" class="col-12">
<section id="region-main" aria-label="{{#str}}content{{/str}}">
{{{ output.course_content_header }}}
{{#headercontent}}
{{> core/activity_header }}
{{/headercontent}}
{{{ output.main_content }}}
{{{ output.activity_navigation }}}
{{{ output.course_content_footer }}}
</section>
</div>
</div>
</div>
</div>
{{{ output.standard_end_of_body_html }}}
</body>
</html>
{{#js}}
M.util.js_pending('theme_boost/loader');
require(['theme_boost/loader'], function() {
M.util.js_complete('theme_boost/loader');
});
{{/js}}
@@ -0,0 +1,68 @@
{{!
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/full_header
This template renders the header.
Example context (json):
{
"contextheader": "context_header_html",
"hasnavbar": false,
"navbar": "navbar_if_available",
"courseheader": "course_header_html",
"welcomemessage": "welcomemessage"
}
}}
<header id="page-header" class="row">
<div class="col-12 pt-3 pb-3">
<div class="card {{^contextheader}}border-0 bg-transparent{{/contextheader}}">
<div class="card-body {{^contextheader}}p-2{{/contextheader}}">
<div class="d-flex align-items-center">
<div class="mr-auto">
{{{contextheader}}}
</div>
<div class="header-actions-container flex-shrink-0" data-region="header-actions-container">
{{#headeractions}}
<div class="header-action ml-2">{{{.}}}</div>
{{/headeractions}}
</div>
</div>
<div class="d-flex flex-wrap">
{{#hasnavbar}}
<div id="page-navbar">
{{{navbar}}}
</div>
{{/hasnavbar}}
<div class="ml-auto d-flex">
{{{pageheadingbutton}}}
</div>
<div id="course-header">
{{{courseheader}}}
</div>
</div>
</div>
</div>
{{#welcomemessage}}
<div class="card border-0 mt-3">
<div class="card-body py-0">
{{> core/welcome }}
</div>
</div>
{{/welcomemessage}}
</div>
</header>
@@ -0,0 +1,105 @@
{{!
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/user_menu
Action link template.
Context variables required for this template:
* unauthenticateduseruser - (Optional) Items to be displayed if an an unautheticated user is accessing the site
* content - The content to be displayed in the header.
* url - The login url
* items - Array of user menu items used in user_action_menu_items. Required if the above not provided.
* metadata - Array of additional metadata to be displayed in the dropdown button.
* avatardata - Array of avatars to be displayed. Usually only the current user's avatar. If viewing as another user,
includes that user's avatar.
* userfullname - The name of the logged in user
* submenus - Array of submenus within the user menu.
* id - The id of the submenu.
* title - The title of the submenu.
* items - Array of the submenu items used in core/user_action_menu_submenu_items.
Example context (json):
{
"unauthenticateduser": {
"content": "You are not logged in",
"url": "https://yourmoodlesite/login/index.php"
},
"items": [],
"metadata": [],
"avatardata": [],
"userfullname": "Admin User",
"submenus": [
{
"id": "86cebd87",
"title": "Submenu title",
"items": []
}
]
}
}}
<div class="usermenu">
{{#unauthenticateduser}}
<span class="login pl-2">
{{content}}
{{#url}}
(<a href="{{url}}">{{#str}} login, core {{/str}}</a>)
{{/url}}
</span>
{{/unauthenticateduser}}
{{^unauthenticateduser}}
<div class="dropdown show">
<a href="#" role="button" id="user-menu-toggle" data-toggle="dropdown" aria-label="{{#str}}usermenu{{/str}}"
aria-haspopup="true" aria-controls="user-action-menu" class="btn dropdown-toggle">
<span class="userbutton">
{{> core/user_menu_metadata }}
</span>
</a>
<div id="user-action-menu" class="dropdown-menu dropdown-menu-right">
<div id="usermenu-carousel" class="carousel slide" data-touch="false" data-interval="false" data-keyboard="false">
<div class="carousel-inner">
<div id="carousel-item-main" class="carousel-item active" role="menu" tabindex="-1" aria-label="{{#str}}user{{/str}}">
{{> core/user_action_menu_items }}
</div>
{{#submenus}}
<div id="carousel-item-{{id}}" class="carousel-item submenu" tabindex="-1" aria-label="{{title}}">
<div class="d-flex flex-column h-100">
<div class="header">
<button type="button" class="btn btn-icon carousel-navigation-link text-decoration-none text-body" data-carousel-target-id="carousel-item-main" aria-label="{{#str}}usermenugoback{{/str}}">
<span class="dir-rtl-hide">{{#pix}}i/arrow-left{{/pix}}</span>
<span class="dir-ltr-hide">{{#pix}}i/arrow-right{{/pix}}</span>
</button>
<span class="pl-2" id="carousel-item-title-{{id}}">{{title}}</span>
</div>
<div class="dropdown-divider"></div>
<div class="items h-100 overflow-auto" role="menu" aria-labelledby="carousel-item-title-{{id}}">
{{> core/user_action_menu_submenu_items }}
</div>
</div>
</div>
{{/submenus}}
</div>
</div>
</div>
</div>
{{/unauthenticateduser}}
</div>
{{#js}}
require(['core/usermenu'], function(UserMenu) {
UserMenu.init();
});
{{/js}}
+72
View File
@@ -0,0 +1,72 @@
{{!
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 theme_classic/footer
Page footer.
Example context (json):
{
"output": {
"course_footer": "More information about this course",
"page_doc_link": "<a href='https://docs.moodle.org/'>Documentation for this page</a>",
"login_info": "You are logged in as cute kitten",
"supportemail": "<a href=\"#\">Contact site support</a>",
"services_support_link": "Services and support"
}
}
}}
<footer id="page-footer" class="footer-dark bg-dark text-light">
<div class="container footer-dark-inner">
<div id="course-footer">{{{ output.course_footer }}}</div>
{{#output.has_communication_links}}
<button onclick="window.open('{{output.communication_url}}', '_blank', 'noreferrer')" class="btn btn-icon bg-primary text-white icon-no-margin btn-footer-communication" aria-label="{{#str}}communicationroomlink, course{{/str}}">
{{#pix}}t/messages-o, core{{/pix}}
</button>
{{/output.has_communication_links}}
<div class="pb-3">
{{#output.has_communication_links}}
<div class="footer-section footer-link-communication">
<div class="footer-support-link">{{{ output.communication_link }}}</div>
</div>
{{/output.has_communication_links}}
{{# output.page_doc_link }}
<div class="footer-support-link">{{{ output.page_doc_link }}}</div>
{{/ output.page_doc_link }}
{{# output.services_support_link }}
<div class="footer-support-link">{{{ output.services_support_link }}}</div>
{{/ output.services_support_link }}
{{# output.supportemail }}
<div class="footer-support-link">{{{ output.supportemail }}}</div>
{{/ output.supportemail }}
</div>
{{{ output.login_info }}}
<div class="tool_usertours-resettourcontainer"></div>
{{{ output.home_link }}}
<nav class="nav navbar-nav d-md-none" aria-label="{{#str}}custommenu, admin{{/str}}">
{{# output.custom_menu_flat }}
<ul class="list-unstyled pt-3">
{{> theme_boost/custom_menu_footer }}
</ul>
{{/ output.custom_menu_flat }}
</nav>
{{{ output.standard_footer_html }}}
{{{ output.debug_footer_html }}}
{{{ output.standard_end_of_body_html }}}
</div>
</footer>
@@ -0,0 +1,52 @@
{{!
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 theme_classic/navbar-secure
This template renders the top navbar.
Example context (json):
{
"output": {
"should_display_navbar_logo": "true",
"get_compact_logo_url": "http://example.com/image.png"
},
"sitename": "Moodle Site"
}
}}
<nav class="fixed-top navbar navbar-bootswatch navbar-expand moodle-has-zindex">
<div class="container-fluid">
{{# output.should_display_navbar_logo }}
<span class="logo d-none d-sm-inline">
<img src="{{output.get_compact_logo_url}}" alt="{{sitename}}">
</span>
{{/ output.should_display_navbar_logo }}
<span class="site-name d-none d-md-inline">{{{ sitename }}}</span>
{{# output.secure_layout_language_menu }}
<ul class="navbar-nav d-none d-md-flex">
<!-- language_menu -->
{{{ . }}}
</ul>
{{/ output.secure_layout_language_menu }}
{{# output.secure_layout_login_info }}
<div class="ml-auto">
{{{ . }}}
</div>
{{/ output.secure_layout_login_info }}
</div>
</nav>
+66
View File
@@ -0,0 +1,66 @@
{{!
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 theme_classic/navbar
This template renders the top navbar.
Example context (json):
{
"output": {
"should_display_navbar_logo": true,
"get_compact_logo_url": "http://example.com/image.png",
"custom_menu": "<li>..</li>",
"page_heading_menu": "<li>..</li>",
"search_box": "<div><input type='text'></div>",
"navbar_plugin_output": "<div class='dropdown'>Messaging</div>",
"user_menu": "<div class='dropdown'>John Doe</div>"
},
"config": {
"wwwroot": "#",
"homeurl": "/my/"
},
"sitename": "Moodle Site"
}
}}
<nav class="fixed-top navbar navbar-bootswatch navbar-expand moodle-has-zindex">
<div class="container-fluid">
<a href="{{{ config.homeurl }}}" class="navbar-brand d-flex align-items-center m-1 p-0 aabtn">
{{# output.should_display_navbar_logo }}
<img src="{{output.get_compact_logo_url}}" class="logo mr-1" alt="{{sitename}}">
{{/ output.should_display_navbar_logo }}
{{^ output.should_display_navbar_logo }}
<span class="sitename">{{{ sitename }}}</span>
{{/ output.should_display_navbar_logo }}
</a>
<ul class="navbar-nav d-none d-md-flex">
<!-- custom_menu -->
{{{ output.custom_menu }}}
<!-- page_heading_menu -->
{{{ output.page_heading_menu }}}
</ul>
<div id="usernavigation" class="navbar-nav my-1 ml-auto">
<div class="divider border-left h-50 align-self-center mx-1"></div>
{{{ output.search_box }}}
{{{ output.navbar_plugin_output }}}
<div class="d-flex align-items-stretch usermenu-container" data-region="usermenu">
{{{ output.user_menu }}}
</div>
</div>
</div>
</nav>
+113
View File
@@ -0,0 +1,113 @@
{{!
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 theme_classic/secure
Classic secure layout template.
Context variables required for this template:
* sitename - The name of the site
* output - The core renderer for the page
* bodyattributes - Attributes for the body tag as a string of html attributes
* sidepreblocks - HTML for the pre blocks
* sidepostblocks - HTML for the post blocks
* haspreblocks - true if there are pre blocks on this page
* haspostblocks - true if there are post blocks on this page
* bodyattributes - attributes for the body tag as a string of html attributes
Example context (json):
{
"sitename": "Moodle",
"output": {
"doctype": "<!DOCTYPE html>",
"page_title": "Test page",
"favicon": "favicon.ico",
"main_content": "<h1>Headings make html validators happier</h1>"
},
"bodyattributes":"",
"sidepreblocks": "<h2>Pre blocks html goes here</h2>",
"sidepostblocks": "<h2>Post blocks html goes here</h2>",
"haspreblocks":true,
"haspostblocks":true,
"bodyattributes": ""
}
}}
{{> theme_boost/head }}
<body {{{ bodyattributes }}}>
<div id="page-wrapper">
{{{ output.standard_top_of_body_html }}}
{{>theme_classic/navbar-secure}}
<div id="page" class="container-fluid">
{{! Secured full header }}
<div id="page-header" class="row">
<div class="col-12 py-3">
<div class="page-context-header">
<div class="page-header-headings">
{{{ output.page_heading }}}
</div>
</div>
</div>
</div>
<div id="page-content" class="row {{#haspreblocks}} blocks-pre {{/haspreblocks}} {{#haspostblocks}} blocks-post {{/haspostblocks}}">
<div id="region-main-box" class="region-main">
<section id="region-main" aria-label="{{#str}}content{{/str}}">
<div class="card">
<div class="card-body">
{{{ output.course_content_header }}}
{{{ output.main_content }}}
{{{ output.course_content_footer }}}
</div>
</div>
</section>
</div>
<div class="columnleft {{#haspreblocks}} has-blocks {{/haspreblocks}}">
<section data-region="blocks-column" class="d-print-none" aria-label="{{#str}}blocks{{/str}}">
{{{ sidepreblocks }}}
</section>
</div>
<div class="columnright {{#haspostblocks}} has-blocks {{/haspostblocks}}">
<section data-region="blocks-column" class="d-print-none" aria-label="{{#str}}blocks{{/str}}">
{{{ sidepostblocks }}}
</section>
</div>
</div>
</div>
<footer id="page-footer" class="py-3 bg-dark text-light">
<div class="container">
<div id="course-footer">{{{ output.course_footer }}}</div>
{{{ output.standard_end_of_body_html }}}
</div>
</footer>
</div>
</body>
</html>
{{#js}}
M.util.js_pending('theme_boost/loader');
require(['theme_boost/loader'], function() {
M.util.js_complete('theme_boost/loader');
});
{{/js}}
@@ -0,0 +1,32 @@
@javascript @theme_classic
Feature: Add a block using classic theme
In order to check the blocks to display in the Add a block list for a them
As an administrator
I need to confirm the unaddableblocks setting is empty for classic.
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And I log in as "admin"
Scenario: All the expected blocks are displayed in the Add a block list for classic
Given I am on "Course 1" course homepage with editing mode on
When I click on "Add a block" "select"
Then I should see "Administration"
And I should see "Navigation"
And I should see "Courses"
And I should see "Section links"
Scenario: Admins can change unaddable blocks using the unaddableblocks setting for classic
Given the following config values are set as admin:
| unaddableblocks | online_users,private_files,settings | theme_classic|
And I am on "Course 1" course homepage with editing mode on
When I click on "Add a block" "select"
Then I should not see "Online users"
And I should not see "Private files"
# The settings block is defined as required block for classic, so it will be displayed always.
And I should see "Administration"
And I should see "Navigation"
And I should see "Courses"
And I should see "Section links"
@@ -0,0 +1,95 @@
<?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/>.
/**
* Step definitions related to administration overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
// For that reason, we can't even rely on $CFG->admin being available here.
require_once(__DIR__ . '/../../../../admin/tests/behat/behat_admin.php');
use Behat\Gherkin\Node\TableNode as TableNode,
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
/**
* Site administration level steps definitions overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_admin extends behat_admin {
/**
* Sets the specified site settings. A table with | Setting label | value | is expected.
*
* @param TableNode $table
*/
public function i_set_the_following_administration_settings_values(TableNode $table) {
if (!$data = $table->getRowsHash()) {
return;
}
foreach ($data as $label => $value) {
// We expect admin block to be visible, otherwise go to homepage.
if (!$this->getSession()->getPage()->find('css', '.block_settings')) {
$this->execute('behat_forms::i_am_on_homepage');
}
// Search by label.
$this->execute('behat_forms::i_set_the_field_to', [get_string('searchinsettings', 'admin'), $label]);
$this->execute("behat_general::i_click_on_in_the", [get_string('search', 'admin'), 'button', '.block_settings', 'css_element']);
// Admin settings does not use the same DOM structure than other moodle forms
// but we also need to use lib/behat/form_field/* to deal with the different moodle form elements.
$exception = new ElementNotFoundException($this->getSession(), '"' . $label . '" administration setting ');
// The argument should be converted to an xpath literal.
$label = behat_context_helper::escape($label);
// Single element settings.
try {
$fieldxpath = "//*[self::input | self::textarea | self::select]" .
"[not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]" .
"[@id=//label[contains(normalize-space(.), $label)]/@for or " .
"@id=//span[contains(normalize-space(.), $label)]/preceding-sibling::label[1]/@for]";
$fieldnode = $this->find('xpath', $fieldxpath, $exception);
} catch (ElementNotFoundException $e) {
// Multi element settings, interacting only the first one.
$fieldxpath = "//*[label[contains(., $label)]|span[contains(., $label)]]" .
"/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-item ')]" .
"/descendant::*[self::input | self::textarea | self::select]" .
"[not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]";
$fieldnode = $this->find('xpath', $fieldxpath);
}
$this->execute('behat_forms::i_set_the_field_with_xpath_to', [$fieldxpath, $value]);
$this->execute("behat_general::i_click_on", [get_string('savechanges'), 'button']);
}
}
}
@@ -0,0 +1,111 @@
<?php
use Behat\Gherkin\Node\TableNode;
// 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/>.
/**
* Step definitions related to blocks overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../blocks/tests/behat/behat_blocks.php');
/**
* Blocks management step definitions for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_blocks extends behat_blocks {
/**
* Adds the selected block. Editing mode must be previously enabled.
*
* @param string $blockname
* @return void
*/
public function i_add_the_block($blockname) {
$this->execute('behat_forms::i_set_the_field_to',
array("bui_addblock", $this->escape($blockname))
);
// If we are running without javascript we need to submit the form.
if (!$this->running_javascript()) {
$this->execute('behat_general::i_click_on_in_the',
array(get_string('go'), "button", "#add_block", "css_element")
);
}
}
/**
* Adds the selected block to the specified region
*
* Editing mode must be previously enabled.
*
* @param string $blockname
* @param string $region
*/
public function i_add_the_block_to_the_region(string $blockname, string $region) {
$this->execute('behat_blocks::i_add_the_block', [$blockname]);
}
/**
* Adds the selected block to the specified region and fills configuration form.
*
* Editing mode must be previously enabled.
*
* @param string $blockname
* @param string $region
* @param TableNode $data
*/
public function i_add_the_block_to_the_region_with(string $blockname, string $region, TableNode $data) {
$this->execute('behat_blocks::i_add_the_block_to_the_region', [$blockname, $region]);
$this->wait_for_pending_js();
$blocktitle = $blockname === 'Text' ? '(new text block)' : $blockname;
$this->execute('behat_blocks::i_configure_the_block', [$blocktitle]);
$dialogname = get_string('configureblock', 'core_block', $blocktitle);
$this->execute('behat_forms::i_set_the_following_fields_in_container_to_these_values',
[$dialogname, "dialogue", $data]);
$this->execute('behat_general::i_click_on_in_the', ["Save changes", 'button', $dialogname, 'dialogue']);
}
/**
* Ensures that block can be added to the page, but does not add it.
*
* @param string $blockname
* @return void
*/
public function the_add_block_selector_should_contain_block($blockname) {
$this->execute('behat_forms::the_select_box_should_contain', [get_string('addblock'), $blockname]);
}
/**
* Ensures that block cannot be added to the page.
*
* @param string $blockname
* @return void
*/
public function the_add_block_selector_should_not_contain_block($blockname) {
$this->execute('behat_forms::the_select_box_should_not_contain', [get_string('addblock'), $blockname]);
}
}
@@ -0,0 +1,40 @@
<?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/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../completion/tests/behat/behat_completion.php');
/**
* Step definitions related to blocks overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2021 Mathew May
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_completion extends behat_completion {
/**
* Goes to the current course activity completion report.
*/
public function go_to_the_current_course_activity_completion_report() {
$completionnode = get_string('pluginname', 'report_progress');
$reportsnode = get_string('reports');
$this->execute("behat_navigation::i_navigate_to_in_current_page_administration",
$reportsnode . ' > ' . $completionnode);
}
}
@@ -0,0 +1,49 @@
<?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/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../question/tests/behat/behat_core_question.php');
use Behat\Gherkin\Node\TableNode as TableNode;
/**
* Step definitions related to blocks overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2021 Mathew May
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_core_question extends behat_core_question {
/**
* Creates a question in the current course questions bank with the provided data.
* This step can only be used when creating question types composed by a single form.
*
* @param string $questiontypename The question type name
* @param TableNode $questiondata The data to fill the question type form.
*/
public function i_add_a_question_filling_the_form_with($questiontypename, TableNode $questiondata) {
// Go to question bank.
$this->execute("behat_general::click_link", get_string('questionbank', 'question'));
// Click on create question.
$this->execute('behat_forms::press_button', get_string('createnewquestion', 'question'));
// Add question.
$this->finish_adding_question($questiontypename, $questiondata);
}
}
@@ -0,0 +1,74 @@
<?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/>.
/**
* Behat course-related step definition overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../course/tests/behat/behat_course.php');
/**
* Course-related step definition overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_course extends behat_course {
/**
* Go to the course participants.
*/
public function i_navigate_to_course_participants() {
$coursestr = behat_context_helper::escape(get_string('courses'));
$mycoursestr = behat_context_helper::escape(get_string('mycourses'));
$xpath = "//div[contains(@class,'block')]//li[contains(@class,'contains_branch')]" .
"[p/*[string(.)=$coursestr or string(.)=$mycoursestr]]";
$this->execute('behat_general::i_click_on_in_the', [get_string('participants'), 'link', $xpath, 'xpath_element']);
}
/**
* Returns whether the user has permission to modify this course.
*
* @return bool
*/
protected function is_course_editor(): bool {
// If the course is already in editing mode then it will have the class 'editing' on the body.
// This is a 'cheap' way of telling if the course is in editing mode.
$body = $this->find('css', 'body');
if ($body->hasClass('editing')) {
return true;
}
// If the course is not already in editing mode, then the only real way to find out if the current user may edit
// the page is to look for the "Turn editing on" button.
// If the button is found then the user is a course editor.
try {
$this->find('button', get_string('turneditingon'), false, false, 0);
return true;
} catch (Exception $e) {
return false;
}
}
}
@@ -0,0 +1,57 @@
<?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/>.
use Behat\Mink\Exception\ElementNotFoundException;
require_once(__DIR__ . '/../../../../lib/tests/behat/behat_general.php');
/**
* Behat grade related step definition overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_general extends behat_general {
/**
* Check whether edit mode is available on the current page.
*
* @return bool
*/
public function is_edit_mode_available(): bool {
// If the course is already in editing mode then it will have the class 'editing' on the body.
// This is a 'cheap' way of telling if the course is in editing mode and therefore if edit mode is available.
$body = $this->find('css', 'body');
if ($body->hasClass('editing')) {
return true;
}
// If the page is not in editing mode then the only way to put it in editing mode is a "Turn editing on" button
// or link.
try {
$this->find('button', get_string('turneditingon'), false, false, 0);
return true;
} catch (ElementNotFoundException $e) {}
try {
$this->find('link', get_string('turneditingon'), false, false, 0);
return true;
} catch (ElementNotFoundException $e) {}
return false;
}
}
@@ -0,0 +1,57 @@
<?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/>.
/**
* Behat grade related step definition overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../grade/tests/behat/behat_grade.php');
use Behat\Gherkin\Node\TableNode as TableNode;
/**
* Behat grade overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_grade extends behat_grade {
/**
* Navigates to the course gradebook and selects a specified item from the grade navigation tabs.
*
* @param string $gradepath
*/
public function i_navigate_to_in_the_course_gradebook($gradepath) {
// If we are not on one of the gradebook pages already, follow "Grades" link in the navigation block.
$xpath = '//div[contains(@class,\'grade-navigation\')]';
if (!$this->getSession()->getPage()->findAll('xpath', $xpath)) {
$this->execute("behat_general::i_click_on_in_the", array(get_string('grades'), 'link',
get_string('pluginname', 'block_navigation'), 'block'));
}
$this->execute('behat_forms::i_set_the_field_to', [get_string('gradebooknavigationmenu', 'grades'), $gradepath]);
}
}
@@ -0,0 +1,42 @@
<?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/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../grade/grading/tests/behat/behat_grading.php');
/**
* Step definitions related to blocks overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2021 Mathew May
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_grading extends behat_grading {
/**
* Goes to the selected advanced grading page. You should be in the course page when this step begins.
*
* @param string $activityname
*/
public function i_go_to_advanced_grading_page($activityname) {
$this->execute("behat_general::i_click_on_in_the", [$this->escape($activityname), 'link', 'page', 'region']);
$this->execute('behat_navigation::i_navigate_to_in_current_page_administration',
get_string('gradingmanagement', 'grading'));
}
}
@@ -0,0 +1,446 @@
<?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/>.
/**
* Navigation step definition overrides for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: No MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../lib/tests/behat/behat_navigation.php');
use Behat\Mink\Exception\ExpectationException as ExpectationException;
use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
use Behat\Mink\Exception\DriverException as DriverException;
/**
* Step definitions and overrides to navigate through the navigation tree nodes in the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_navigation extends behat_navigation {
/**
* Navigate to an item in a current page administration menu.
*
* @throws ExpectationException
* @param string $nodetext The navigation node/path to follow, eg "Course administration > Edit settings"
* @return void
*/
public function i_navigate_to_in_current_page_administration($nodetext) {
$parentnodes = array_map('trim', explode('>', $nodetext));
// Find the name of the first category of the administration block tree.
$xpath = "//section[contains(@class,'block_settings')]//div[@id='settingsnav']/ul[1]/li[1]/p[1]/span";
$node = $this->find('xpath', $xpath);
array_unshift($parentnodes, $node->getText());
$lastnode = array_pop($parentnodes);
try {
$this->select_node_in_navigation($lastnode, $parentnodes);
} catch (Exception $e) {
try {
$this->execute("behat_general::click_link", $lastnode);
} catch (Exception $e) {
// We must be in a weird state i.e. Add competencies to course.
$this->execute("behat_general::click_link", array_pop($parentnodes));
$this->execute('behat_forms::press_button', $lastnode);
}
}
}
/**
* Navigate to an item within the site administration menu.
*
* @throws ExpectationException
* @param string $nodetext The navigation node/path to follow, excluding "Site administration" itself, eg "Grades > Scales"
* @return void
*/
public function i_navigate_to_in_site_administration($nodetext) {
$parentnodes = array_map('trim', explode('>', $nodetext));
array_unshift($parentnodes, get_string('administrationsite'));
$lastnode = array_pop($parentnodes);
$this->select_node_in_navigation($lastnode, $parentnodes);
}
/**
* Helper function to get top navigation node in the tree.
*
* @throws ExpectationException if node not found.
* @param string $nodetext name of top navigation node in tree.
* @return NodeElement
*/
protected function get_top_navigation_node($nodetext) {
// Avoid problems with quotes.
$nodetextliteral = behat_context_helper::escape($nodetext);
$exception = new ExpectationException('Top navigation node "' . $nodetext . '" not found', $this->getSession());
$xpath = // Navigation block.
"//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]" .
"/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
"/ul/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
"[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"[span[normalize-space(.)={$nodetextliteral}] or a[normalize-space(.)={$nodetextliteral}]]]" .
"|" .
// Administration block.
"//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]/div" .
"/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
"/ul/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
"[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/span[normalize-space(.)={$nodetextliteral}]]" .
"|" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]/div" .
"/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/li[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/span[normalize-space(.)={$nodetextliteral}]]" .
"|" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]/div" .
"/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/li[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/a[normalize-space(.)={$nodetextliteral}]]";
$node = $this->find('xpath', $xpath, $exception);
return $node;
}
/**
* Check that current page administration contains an element.
*
* @throws ElementNotFoundException
* @param string $element The locator of the specified selector.
* This may be a path, for example "Subscription mode > Forced subscription"
* @param string $selectortype The selector type (link or text)
* @return void
*/
public function should_exist_in_current_page_administration($element, $selectortype) {
$nodes = array_map('trim', explode('>', $element));
$nodetext = end($nodes);
// Find administration menu.
$rootxpath = $this->find_header_administration_menu() ?: $this->find_page_administration_menu(true);
$menuxpath = $rootxpath . '/p/../ul[1]';
for ($i = 0; $i < (count($nodes) - 1); $i++) {
$menuxpath .= "/li/p/span[contains(text(), '{$nodes[$i]}')]/../../ul[1]";
}
if ($selectortype == 'link') {
$menuxpath .= "/li/p[a[contains(text(), '{$nodetext}')]";
$menuxpath .= "|a/span[contains(text(), '{$nodetext}')]]";
} else {
$menuxpath .= "/li/p/span[contains(text(), '{$nodes[$i]}')]";
}
$exception = new ElementNotFoundException($this->getSession(), "\"{$element}\" \"{$selectortype}\"");
try {
$this->find('xpath', $menuxpath, $exception);
} catch (Exception $e) {
// For question bank a different approach.
$menuxpath = $rootxpath . "//div[contains(@class, 'dropdown-menu')]";
if ($selectortype === 'link') {
$menuxpath .= "//a[contains(text(), 'Categories')]";
}
$this->find('xpath', $menuxpath, $e);
}
}
/**
* Check that current page administration does not contains an element.
*
* @throws ExpectationException
* @param string $element The locator of the specified selector.
* This may be a path, for example "Subscription mode > Forced subscription"
* @param string $selectortype The selector type (link or text)
* @return void
*/
public function should_not_exist_in_current_page_administration($element, $selectortype) {
try {
$menuxpath = $this->find_header_administration_menu() ?: $this->find_page_administration_menu(true);
} catch (Exception $e) {
// If an exception was thrown, it means the root note does not exist, so we can conclude the test is a success.
return;
}
// Test if the element exists.
try {
$this->should_exist_in_current_page_administration($element, $selectortype);
} catch (ElementNotFoundException $e) {
// If an exception was thrown, it means the element does not exist, so the test is successful.
return;
}
// If the try block passed, the element exists, so throw an exception.
$exception = 'The "' . $element . '" "' . $selectortype . '" was found, but should not exist';
throw new ExpectationException($exception, $this->getSession());
}
/**
* Check that the page administration menu exists on the page.
*
* This confirms the existence of the menu, which authorised users should have access to.
* @Given /^I should see the page administration menu$/
*
* @throws ExpectationException
* @return void
*/
public function page_administration_exists() {
$menuxpath = "//section[contains(@class,'block_settings')]//div[@id='settingsnav']";
$this->ensure_element_exists($menuxpath, 'xpath_element');
}
/**
* Check that the page administration menu does not exist on the page.
*
* This confirms the absence of the menu, which unauthorised users should not have access to.
* @Given /^I should not see the page administration menu$/
*
* @throws ExpectationException
* @return void
*/
public function page_administration_does_not_exist() {
$menuxpath = "//section[contains(@class,'block_settings')]//div[@id='settingsnav']";
$this->ensure_element_does_not_exist($menuxpath, 'xpath_element');
}
/**
* Locate the administration menu on the page (but not in the header) and return its xpath.
*
* @throws ElementNotFoundException
* @param bool $mustexist If true, throws an exception if menu is not found
* @return null|string
*/
protected function find_page_administration_menu($mustexist = false) {
$menuxpath = "//section[contains(@class,'block_settings')]//div[@id='settingsnav']/ul[1]/li[1]";
if ($mustexist) {
$exception = new ElementNotFoundException($this->getSession(), 'Page administration menu');
$this->find('xpath', $menuxpath, $exception);
} else if (!$this->getSession()->getPage()->find('xpath', $menuxpath)) {
return null;
}
return $menuxpath;
}
/**
* Turns editing mode off.
*/
public function i_turn_editing_mode_off(): void {
$buttonnames = [get_string('turneditingoff'), get_string('updatemymoodleoff'), get_string('blockseditoff')];
foreach ($buttonnames as $buttonname) {
if ($editbutton = $this->getSession()->getPage()->findButton($buttonname)) {
$this->execute('behat_general::i_click_on', [$editbutton, 'NodeElement']);
return;
}
}
// Click the turneditingoff link in the Site Administration block.
if ($this->is_editing_on()) {
$this->execute('behat_general::i_click_on', [get_string('turneditingoff'), "link"]);
}
}
/**
* Turns editing mode on.
*/
public function i_turn_editing_mode_on(): void {
$buttonnames = [get_string('turneditingon'), get_string('updatemymoodleon'), get_string('blocksediton')];
foreach ($buttonnames as $buttonname) {
if ($editbutton = $this->getSession()->getPage()->findButton($buttonname)) {
$this->execute('behat_general::i_click_on', [$editbutton, 'NodeElement']);
return;
}
}
if (!$this->is_editing_on()) {
$this->execute('behat_general::i_click_on', [get_string('turneditingon'), "link"]);
}
}
/**
* Finds and clicks a link on the admin page (site administration or course administration)
*
* @param array $nodelist
*/
protected function select_on_administration_page($nodelist) {
$parentnodes = $nodelist;
$lastnode = array_pop($parentnodes);
$xpath = '//section[@id=\'region-main\']';
// Check if there is a separate tab for this submenu of the page. If found go to it.
if ($parentnodes) {
$tabname = behat_context_helper::escape($parentnodes[0]);
$tabxpath = '//ul[@role=\'tablist\']/li/a[contains(normalize-space(.), ' . $tabname . ')]';
$menubarxpath = '//ul[@role=\'menubar\']/li/a[contains(normalize-space(.), ' . $tabname . ')]';
$linkname = behat_context_helper::escape(get_string('moremenu'));
$menubarmorexpath = '//ul[@role=\'menubar\']/li/a[contains(normalize-space(.), ' . $linkname . ')]';
$tabnode = $this->getSession()->getPage()->find('xpath', $tabxpath);
$menunode = $this->getSession()->getPage()->find('xpath', $menubarxpath);
$menubuttons = $this->getSession()->getPage()->findAll('xpath', $menubarmorexpath);
if ($tabnode || $menunode) {
$node = is_object($tabnode) ? $tabnode : $menunode;
if ($this->running_javascript()) {
$this->execute('behat_general::i_click_on', [$node, 'NodeElement']);
// Click on the tab and add 'active' tab to the xpath.
$xpath .= '//div[contains(@class,\'active\')]';
} else {
// Add the tab content selector to the xpath.
$tabid = behat_context_helper::escape(ltrim($node->getAttribute('href'), '#'));
$xpath .= '//div[@id = ' . $tabid . ']';
}
array_shift($parentnodes);
} else if (count($menubuttons) > 0) {
try {
$menubuttons[0]->isVisible();
try {
$this->execute('behat_general::i_click_on', [$menubuttons[1], 'NodeElement']);
} catch (Exception $e) {
$this->execute('behat_general::i_click_on', [$menubuttons[0], 'NodeElement']);
}
$moreitemxpath = '//ul[@data-region=\'moredropdown\']/li/a[contains(normalize-space(.), ' . $tabname . ')]';
if ($morenode = $this->getSession()->getPage()->find('xpath', $moreitemxpath)) {
$this->execute('behat_general::i_click_on', [$morenode, 'NodeElement']);
$xpath .= '//div[contains(@class,\'active\')]';
array_shift($parentnodes);
}
} catch (Exception $e) {
return;
}
}
}
// Find a section with the parent name in it.
if ($parentnodes) {
// Find the section on the page (links may be repeating in different sections).
$section = behat_context_helper::escape($parentnodes[0]);
$xpath .= '//div[@class=\'row\' and contains(.,'.$section.')]';
}
// Find a link and click on it.
$linkname = behat_context_helper::escape($lastnode);
$xpath .= '//a[contains(normalize-space(.), ' . $linkname . ')]';
if (!$node = $this->getSession()->getPage()->find('xpath', $xpath)) {
throw new ElementNotFoundException($this->getSession(), 'Link "' . join(' > ', $nodelist) . '"');
}
$this->execute('behat_general::i_click_on', [$node, 'NodeElement']);
}
/**
* Locates the administration menu in the <header> element and returns its xpath
*
* @param bool $mustexist if specified throws an exception if menu is not found
* @return null|string
*/
protected function find_header_administration_menu($mustexist = false) {
$menuxpath = '//header[@id=\'page-header\']//div[contains(@class,\'moodle-actionmenu\')]';
if ($mustexist) {
$exception = new ElementNotFoundException($this->getSession(), 'Page header administration menu');
$this->find('xpath', $menuxpath, $exception);
} else if (!$this->getSession()->getPage()->find('xpath', $menuxpath)) {
return null;
}
return $menuxpath;
}
/**
* Toggles administration menu
*
* @param string $menuxpath (optional) xpath to the page administration menu if already known
*/
protected function toggle_page_administration_menu($menuxpath = null) {
if (!$menuxpath) {
$menuxpath = $this->find_header_administration_menu() ?: $this->find_page_administration_menu();
}
if ($menuxpath && $this->running_javascript()) {
$node = $this->find('xpath', $menuxpath . '//a[@data-toggle=\'dropdown\']');
$this->execute('behat_general::i_click_on', [$node, 'NodeElement']);
}
}
/**
* Finds a page edit cog and select an item from it
*
* If the page edit cog is in the page header and the item is not found there, click "More..." link
* and find the item on the course/frontpage administration page
*
* @param array $nodelist
* @throws ElementNotFoundException
*/
protected function select_from_administration_menu($nodelist) {
// Find administration menu.
if ($menuxpath = $this->find_header_administration_menu()) {
$isheader = true;
} else {
$menuxpath = $this->find_page_administration_menu(true);
$isheader = false;
}
$this->execute('behat_navigation::toggle_page_administration_menu', [$menuxpath]);
if (!$isheader || count($nodelist) == 1) {
$lastnode = end($nodelist);
$linkname = behat_context_helper::escape($lastnode);
$link = $this->getSession()->getPage()->find('xpath', $menuxpath . '//a[contains(normalize-space(.), ' .
$linkname . ')]'
);
if ($link) {
$this->execute('behat_general::i_click_on', [$link, 'NodeElement']);
return;
}
}
if ($isheader) {
// Course administration and Front page administration will have subnodes under "More...".
$linkname = behat_context_helper::escape(get_string('morenavigationlinks'));
$link = $this->getSession()->getPage()->find('xpath', $menuxpath . '//a[contains(normalize-space(.), ' .
$linkname . ')]'
);
if ($link) {
$this->execute('behat_general::i_click_on', [$link, 'NodeElement']);
$this->select_on_administration_page($nodelist);
return;
}
}
throw new ElementNotFoundException($this->getSession(),
'Link "' . join(' > ', $nodelist) . '" in the current page edit menu"');
}
#[\Override]
public function menu_item_should_be_active(string $navigationmenuitem): void {
throw new DriverException(
'The Classic theme does not implement navigation in a way that allows this step to be used.',
);
}
#[\Override]
public function menu_item_should_not_be_active(string $navigationmenuitem): void {
throw new DriverException(
'The Classic theme does not implement the navigation in a way that allows this step to be used.',
);
}
}
@@ -0,0 +1,74 @@
<?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/>.
/**
* Override definitions for the upload repository type for the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../repository/upload/tests/behat/behat_repository_upload.php');
use Behat\Mink\Exception\ExpectationException as ExpectationException;
/**
* Override step definitions to deal with the upload repository in the Classic theme.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_theme_classic_behat_repository_upload extends behat_repository_upload {
/**
* Gets the NodeElement for filepicker of filemanager moodleform element.
*
* @throws ExpectationException
* @param string $filepickerelement The filepicker form field label
* @return NodeElement The hidden element node.
*/
protected function get_filepicker_node($filepickerelement) {
// More info about the problem (in case there is a problem).
$exception = new ExpectationException('"' . $filepickerelement . '" filepicker can not be found', $this->getSession());
// If no file picker label is mentioned take the first file picker from the page.
if (empty($filepickerelement)) {
$filepickercontainer = $this->find(
'xpath',
"//*[@class=\"form-filemanager\"]",
$exception
);
} else {
// Gets the filemanager node specified by the locator which contains the filepicker container.
$filepickerelement = behat_context_helper::escape($filepickerelement);
$filepickercontainer = $this->find(
'xpath',
"//input[./@id = substring-before(//p[normalize-space(.)=$filepickerelement]/@id, '_label')]" .
"//ancestor::*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']",
$exception
);
}
return $filepickercontainer;
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"contexts": [
"behat_theme_boost_behat_navigation"
],
"features": [
"lib/tests/behat/action_menu.feature",
"admin/tests/behat/site_administration.feature",
"blocks/tests/behat/hide_blocks.feature",
"blocks/tests/behat/move_blocks.feature",
"course/format/tests/behat/course_courseindex.feature",
"course/format/tests/behat/courseindex_keyboardnav.feature",
"course/format/tests/behat/courseindex_completion.feature",
"course/format/tests/behat/courseindex_language.feature",
"badges/tests/behat/badge_navigation.feature",
"lib/tests/behat/menu_navigation_single_activity.feature",
"lib/tests/behat/menu_navigation_topics.feature"
],
"tags": [
"addablocklink"
]
}
@@ -0,0 +1,42 @@
@core @core_course @theme_classic
Feature: Role assignments can be made at the category level in classic
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"
Then "Assign roles" "link" should exist in current page administration
@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"
Then "Assign roles" "link" should not exist in current page administration
@@ -0,0 +1,30 @@
@theme_classic
Feature: Select course sections using classic theme
In order to view course sections when using the classic theme
As a teacher
I need to select the section from the section selector
Background:
Given the following "course" exists:
| fullname | Course 1 |
| shortname | C1 |
| numsections | 3 |
| initsections | 1 |
And the following "activities" exist:
| course | activity | name | idnumber | section |
| C1 | assign | Assignment 1 | assign1 | 1 |
| C1 | assign | Assignment 2 | assign2 | 2 |
@javascript
Scenario: Use the course section selector in classic theme
Given I am on the "C1" "Course" page logged in as "admin"
And I turn editing mode on
When I choose the "View" item in the "Edit" action menu of the "Section 1" "section"
Then I should see "Section 1"
And I should see "Assignment 1"
And I should not see "Assignment 2"
And I select "Section 2" from the "jump" singleselect
And I should see "Section 2"
And I should not see "Assignment 1"
And I should see "Assignment 2"
And the "jump" select box should contain "Section 3"
@@ -0,0 +1,27 @@
@javascript @theme_classic
Feature: Course administration menu
To navigate in classic theme teachers need to use the course administration menu
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
Scenario: Teacher can use the course administration menu
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I should see the page administration menu
Scenario: Student cannot see the course administration menu
And I log in as "student1"
And I am on "Course 1" course homepage
And I should not see the page administration menu
And I log out
@@ -0,0 +1,27 @@
@javascript @theme_classic
Feature: My courses page block layout in Classic theme
In order to have a clear and consistent view on the my courses page
As a student
I need to see the blocks in the expected placement
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student@example.com |
And I log in as "admin"
And I am on site homepage
And I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
| Text block title | Text on all pages |
| Content | This is visible on all pages |
| Default region | Right |
And I press "Save changes"
Scenario: Student can see relevant blocks with correct placement on my courses page
When I log in as "student1"
And I am on the "My courses" page
Then "Course overview" "text" should exist in the "region-main" "region"
And "This is visible on all pages" "text" should exist in the ".columnright" "css_element"
@@ -0,0 +1,50 @@
@javascript @theme_classic
Feature: Page administration menu
To navigate in classic theme I need to use the page administration menu
Background:
Given the following "courses" exist:
| fullname | shortname | newsitems |
| Course 1 | C1 | 5 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activities" exist:
| activity | name | intro | course | idnumber | option |
| choice | Choice name | Test choice description | C1 | choice1 | Option 1, Option 2, Option 3 |
Scenario: Teacher can access activity administration menus
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Choice name"
And I should see the page administration menu
And "Settings" "link" should exist in current page administration
And I navigate to "Settings" in current page administration
And I should see "Edit settings"
And I navigate to course participants
And I should see the page administration menu
And I am on the "Course 1" "Enrolment methods" page
And I should see "Enrolment methods"
And I log out
Scenario: Student cannot access course and activity administration menus
And I log in as "student1"
And I am on "Course 1" course homepage
And I should not see the page administration menu
And I follow "Choice name"
And I should not see the page administration menu
And I log out
Scenario: Administrator can access site administration menus and sub-menus
And I log in as "admin"
And I should see the page administration menu
And I navigate to "Advanced features" in site administration
And I should see "Enable comments"
And I navigate to "Users > Accounts > Add a new user" in site administration
And I should see "New password"
And I log out
@@ -0,0 +1,32 @@
@core @core_admin @theme_classic
Feature: Select a theme in Classic theme
In order to choose a theme
As an admin
I need to preview the theme and make a selection
Background:
Given I log in as "admin"
And I navigate to "Appearance > Themes" in site administration
@javascript
Scenario: I am able to preview a theme using a modal window
When I click on "Preview theme 'Classic'" "button"
Then I should see "Classic" in the "Classic" "dialogue"
And I should see "Classic is a highly-customisable theme," in the "Classic" "dialogue"
And I should see "Current theme" in the "Classic" "dialogue"
@javascript
Scenario: I am able to change the theme using the modal window select button
Given I should see "Current theme" in the "#theme-card-classic" "css_element"
When I click on "Preview theme 'Boost'" "button"
And I click on "Select theme" "button" in the "Boost" "dialogue"
Then I should see "Current theme" in the "#theme-card-boost" "css_element"
Scenario: I am able to change the theme using the normal select button
Given I should see "Current theme" in the "#theme-card-classic" "css_element"
When I click on "Select theme 'Boost'" "button"
Then I should see "Current theme" in the "#theme-card-boost" "css_element"
Scenario: I am able to view a theme's settings page
Given I click on "Edit theme settings 'Classic'" "link"
Then I should see "Classic"
@@ -0,0 +1,32 @@
@javascript @theme_classic
Feature: Welcome message on classic
To be welcome in moodle
As a User
I need to see a welcome message on the first page
Scenario: Login and be welcomed on the homepage
Given the following config values are set as admin:
| defaulthomepage | 0 |
When I log in as "admin"
Then I should see "Acceptance test site" in the "page-header" "region"
And I should see "Welcome, Admin!" in the "page-header" "region"
And I reload the page
And I should not see "Welcome, Admin!" in the "page-header" "region"
Scenario: Login and be welcomed on the dashboard
Given the following config values are set as admin:
| defaulthomepage | 1 |
When I log in as "admin"
Then I should see "Dashboard" in the "page-header" "region"
And I should see "Welcome, Admin!" in the "page-header" "region"
And I reload the page
And I should not see "Welcome, Admin!" in the "page-header" "region"
Scenario: Login and be welcomed on the my courses page
Given the following config values are set as admin:
| defaulthomepage | 3 |
When I log in as "admin"
Then I should see "My courses" in the "page-header" "region"
And I should see "Welcome, Admin!" in the "page-header" "region"
And I reload the page
And I should not see "Welcome, Admin!" in the "page-header" "region"
+43
View File
@@ -0,0 +1,43 @@
<?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 theme_classic;
/**
* Unit tests for scss compilation.
*
* @package theme_classic
* @category test
* @copyright 2019 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class scss_test extends \advanced_testcase {
/**
* Test that classic can be compiled using SassC (the defacto implemention).
*/
public function test_scss_compilation_with_sassc(): void {
if (!defined('PHPUNIT_PATH_TO_SASSC')) {
$this->markTestSkipped('Path to SassC not provided');
}
$this->resetAfterTest();
set_config('pathtosassc', PHPUNIT_PATH_TO_SASSC);
$this->assertNotEmpty(
\theme_config::load('classic')->get_css_content_debug('scss', null, null)
);
}
}
+31
View File
@@ -0,0 +1,31 @@
<?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/>.
/**
* Classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200;
$plugin->requires = 2024041600;
$plugin->component = 'theme_classic';
$plugin->dependencies = ['theme_boost' => 2024041600];