This patch includes a big set of changes that are all designed to work together to provide
a better way to navigate in the new theme, and a different way of working with blocks.
Blocks have been moved to a "drawer" that can be opened and closed (this is remembered in a user pref).
A new "flat navigation" element is also available in a drawer - which should let you do 90% of things
without needing to open the "blocks" drawer.
The flat navigation is build from specific parts of the nav tree - the top nodes like "calendar, dashboard" are
hand picked. There is a mycourses node listing your enrolled courses.
There is a node for the current course, built from the top nodes in the current course node in the nav tree.
Administrators have a link to the Site admin settings here too.
These nav elements are used by the templates for the new theme, which also has a resigned layout for login and signup.
There have also been some additional fixes / improvements to the scss for the new theme which goes along with these
layout changes.
This set of changes is a collaboration between Martin, Damyon and Alberto (thanks!).
--- /dev/null
+<?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/>.
+
+/**
+ * Admin settings search form
+ *
+ * @package admin
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once $CFG->libdir.'/formslib.php';
+
+/**
+ * Admin settings search form
+ *
+ * @package admin
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class admin_settings_search_form extends moodleform {
+ function definition () {
+ $mform = $this->_form;
+
+ //$mform->addElement('header', 'settingsheader', get_string('search', 'admin'));
+ $elements = [];
+ $elements[] = $mform->createElement('text', 'query', get_string('query', 'admin'));
+ $elements[] = $mform->createElement('submit', 'search', get_string('search'));
+ $mform->addGroup($elements);
+ $mform->setType('query', PARAM_RAW);
+ $mform->setDefault('query', optional_param('query', '', PARAM_RAW));
+ }
+}
// to modify them
echo $OUTPUT->header($focus);
+echo $OUTPUT->heading(get_string('administrationsite'));
+
if ($errormsg !== '') {
echo $OUTPUT->notification($errormsg);
echo $OUTPUT->notification($statusmsg, 'notifysuccess');
}
-echo admin_search_settings_html($query);
+require_once("admin_settings_search_form.php");
+$form = new admin_settings_search_form();
+$form->display();
+echo '<hr>';
+
+if ($query) {
+ echo admin_search_settings_html($query);
+} else {
+ $node = $PAGE->settingsnav->find('root', navigation_node::TYPE_SITE_ADMIN);
+ if ($node) {
+ echo $OUTPUT->render_from_template('core/settings_link_page', ['node' => $node]);
+ }
+}
echo $OUTPUT->footer();
$ADMIN->add('root', new admin_category('unsupported', new lang_string('unsupported', 'admin'), true));
// hidden search script
-$ADMIN->add('root', new admin_externalpage('search', new lang_string('searchresults'), "$CFG->wwwroot/$CFG->admin/search.php", 'moodle/site:config', true));
+$ADMIN->add('root', new admin_externalpage('search', new lang_string('search', 'admin'), "$CFG->wwwroot/$CFG->admin/search.php", 'moodle/site:config', true));
--- /dev/null
+<?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/>.
+
+/**
+ * Listing of the course administration pages for this course.
+ *
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once("../config.php");
+
+$courseid = required_param('courseid', PARAM_INT);
+
+$PAGE->set_url('/course/admin.php', array('courseid'=>$courseid));
+
+$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
+
+require_login($course);
+$context = context_course::instance($course->id);
+
+$PAGE->set_pagelayout('incourse');
+$PAGE->set_title(get_string('courseadministration'));
+$PAGE->set_heading($course->fullname);
+$PAGE->navbar->add(get_string('courseadministration'));
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('courseadministration'));
+
+$node = $PAGE->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
+if ($node) {
+ echo $OUTPUT->render_from_template('core/settings_link_page', ['node' => $node]);
+}
+
+echo $OUTPUT->footer();
if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$url->param('section', $sectionno);
} else {
- if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) {
- return null;
- }
$url->set_anchor('section-'.$sectionno);
}
}
if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$url->param('section', $sectionno);
} else {
- if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) {
- return null;
- }
$url->set_anchor('section-'.$sectionno);
}
}
$options->participants = has_capability('moodle/course:viewparticipants', $context);
$options->badges = !empty($CFG->enablebadges) && !empty($CFG->badges_allowcoursebadges) &&
has_capability('moodle/badges:viewbadges', $context);
+ // Add view grade report is permitted.
+ $grades = false;
+ if (has_capability('moodle/grade:viewall', $context)) {
+ $grades = true;
+ } else if (!empty($course->showgrades)) {
+ $reports = core_component::get_plugin_list('gradereport');
+ if (is_array($reports) && count($reports) > 0) { // Get all installed reports.
+ arsort($reports); // User is last, we want to test it first.
+ foreach ($reports as $plugin => $plugindir) {
+ if (has_capability('gradereport/'.$plugin.':view', $context)) {
+ // Stop when the first visible plugin is found.
+ $grades = true;
+ break;
+ }
+ }
+ }
+ }
+ $options->grades = $grades;
+ }
+
+ if (\core_competency\api::is_enabled()) {
+ $capabilities = array('moodle/competency:coursecompetencyview', 'moodle/competency:coursecompetencymanage');
+ $options->competencies = has_any_capability($capabilities, $context);
}
return $options;
}
$returnurl = clean_param($returnurl, PARAM_URL);
}
-$PAGE->set_url('/course/switchrole.php', array('id'=>$id));
+$PAGE->set_url('/course/switchrole.php', array('id'=>$id, 'switchrole'=>$switchrole));
-require_sesskey();
+if ($switchrole >= 0) {
+ require_sesskey();
+}
if (!$course = $DB->get_record('course', array('id'=>$id))) {
redirect(new moodle_url('/'));
if (is_array($aroles) && isset($aroles[$switchrole])) {
role_switch($switchrole, $context);
}
+} else if ($switchrole < 0) {
+
+ $PAGE->set_title(get_string('switchroleto'));
+ $PAGE->set_heading($course->fullname);
+ $PAGE->set_pagelayout('incourse');
+
+ echo $OUTPUT->header();
+ echo $OUTPUT->heading(get_string('switchroleto'));
+
+ require_once($CFG->dirroot.'/course/switchrole_form.php');
+ $form = new switchrole_form(null, ['course' => $course]);
+ $form->display();
+
+ echo $OUTPUT->footer();
+ exit;
}
redirect($returnurl);
--- /dev/null
+<?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/>.
+
+/**
+ * Switch roles form.
+ *
+ * @package core_course
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Defines the course completion settings form.
+ */
+class switchrole_form extends moodleform {
+
+ /**
+ * Determine whether the user is assuming another role
+ *
+ * This function checks to see if the user is assuming another role by means of
+ * role switching. In doing this we compare each RSW key (context path) against
+ * the current context path. This ensures that we can provide the switching
+ * options against both the course and any page shown under the course.
+ *
+ * @param context $context
+ * @return bool|int The role(int) if the user is in another role, false otherwise
+ */
+ protected function in_alternative_role($context) {
+ global $USER, $PAGE;
+ if (!empty($USER->access['rsw']) && is_array($USER->access['rsw'])) {
+ if (!empty($PAGE->context) && !empty($USER->access['rsw'][$PAGE->context->path])) {
+ return $USER->access['rsw'][$PAGE->context->path];
+ }
+ foreach ($USER->access['rsw'] as $key=>$role) {
+ if (strpos($context->path, $key)===0) {
+ return $role;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Defines the form fields.
+ */
+ public function definition() {
+ global $USER, $CFG, $DB;
+
+ $mform = $this->_form;
+ $course = $this->_customdata['course'];
+
+ // Overall criteria aggregation.
+ $context = context_course::instance($course->id);
+ $roles = array();
+ $assumedrole = -1;
+ if (is_role_switched($course->id)) {
+ $roles[0] = get_string('switchrolereturn');
+ $assumedrole = $USER->access['rsw'][$context->path];
+ }
+ $availableroles = get_switchable_roles($context);
+ if (is_array($availableroles)) {
+ foreach ($availableroles as $key=>$role) {
+ if ($assumedrole == (int)$key) {
+ continue;
+ }
+ $roles[$key] = $role;
+ }
+ }
+ $mform->addElement('select', 'switchrole', get_string('role'), $roles);
+
+ // Add common action buttons.
+ $this->add_action_buttons();
+
+ // Add hidden fields.
+ $mform->addElement('hidden', 'id', $course->id);
+ $mform->setType('id', PARAM_INT);
+ }
+}
$navoptions->{$option['name']} = $option['available'];
}
if ($course['id'] == SITEID) {
- $this->assertCount(7, $course['options']);
+ $this->assertCount(8, $course['options']);
$this->assertTrue($navoptions->blogs);
$this->assertFalse($navoptions->notes);
$this->assertFalse($navoptions->participants);
$this->assertTrue($navoptions->tags);
$this->assertFalse($navoptions->search);
$this->assertTrue($navoptions->calendar);
+ $this->assertTrue($navoptions->competencies);
} else {
- $this->assertCount(4, $course['options']);
+ $this->assertCount(6, $course['options']);
$this->assertTrue($navoptions->blogs);
$this->assertFalse($navoptions->notes);
$this->assertTrue($navoptions->participants);
$this->assertTrue($navoptions->badges);
+ $this->assertTrue($navoptions->grades);
+ $this->assertTrue($navoptions->competencies);
}
}
}
$string['proxyport'] = 'Proxy port';
$string['proxytype'] = 'Proxy type';
$string['proxyuser'] = 'Proxy username';
+$string['query'] = 'Query';
$string['question'] = 'Question';
$string['questionbehaviours'] = 'Question behaviours';
$string['questioncwqpfscheck'] = 'One or more \'random\' questions in a quiz are set up to select questions from a mixture of shared and unshared question categories. There is a more detailed report <a href="{$a->reporturl}">here</a> and see Moodle Docs page <a href="{$a->docsurl}">here</a>.';
$string['anypagematchingtheabove'] = 'Any page matching the above';
$string['appearsinsubcontexts'] = 'Appears in sub-contexts';
$string['assignrolesinblock'] = 'Assign roles in {$a} block';
+$string['blocksdrawertoggle'] = 'Hide/show blocks drawer';
$string['blocksettings'] = 'Block settings';
$string['bracketfirst'] = '{$a} (first)';
$string['bracketlast'] = '{$a} (last)';
$string['moveblockbefore'] = 'Move block to before {$a} block';
$string['moveblockinregion'] = 'Move block to {$a} region';
$string['movingthisblockcancel'] = 'Moving this block ({$a})';
+$string['myblocks'] = 'My blocks';
$string['onthispage'] = 'On this page';
$string['pagetypes'] = 'Page types';
$string['pagetypewarning'] = 'The previously specified page type is no longer selectable. Please choose the most appropriate page type below.';
public $includesectionnum = false;
/** @var bool does the node need to be loaded via ajax */
public $requiresajaxloading = false;
+ /** @var bool If set to true this node will be added to the "flat" navigation */
+ public $showinflatnavigation = false;
/**
* Constructs a new navigation_node
return false;
}
+ /**
+ * True if this nav node has siblings in the tree.
+ *
+ * @return bool
+ */
+ public function has_siblings() {
+ if (empty($this->parent) || empty($this->parent->children)) {
+ return false;
+ }
+ if ($this->parent->children instanceof navigation_node_collection) {
+ $count = $this->parent->children->count();
+ } else {
+ $count = count($this->parent->children);
+ }
+ return ($count > 1);
+ }
+
+ /**
+ * Recursively walk the tree looking for a node with a valid action.
+ * Depth first search.
+ *
+ * @return bool
+ */
+ public function resolve_action() {
+ if ($this->action) {
+ return $this->action;
+ }
+ if (!empty($this->children)) {
+ foreach ($this->children as $child) {
+ $action = $child->resolve_action();
+ if (!empty($action)) {
+ return $action;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get a list of sibling navigation nodes at the same level as this one.
+ *
+ * @return bool|array of navigation_node
+ */
+ public function get_siblings() {
+ // Returns a list of the siblings of the current node for display in a flat navigation element. Either
+ // the in-page links or the breadcrumb links.
+ $siblings = false;
+
+ if ($this->has_siblings()) {
+ $siblings = [];
+ foreach ($this->parent->children as $child) {
+ if ($child->display) {
+ $siblings[] = $child;
+ }
+ }
+ }
+ return $siblings;
+ }
+
/**
* This sets the URL that the URL of new nodes get compared to when locating
* the active node.
return $this->children->find($key, $type);
}
+ /**
+ * Walk the tree building up a list of all the flat navigation nodes.
+ *
+ * @param flat_navigation $nodes List of the found flat navigation nodes.
+ */
+ public function build_flat_navigation_list(flat_navigation $nodes) {
+ if ($this->showinflatnavigation) {
+ $indent = 0;
+ if ($this->type == self::TYPE_COURSE) {
+ $indent = 1;
+ }
+ $nodes->add(new flat_navigation_node($this, $indent));
+ }
+ foreach ($this->children as $child) {
+ $child->build_flat_navigation_list($nodes);
+ }
+ }
+
/**
* Get the child of this node that has the given key + (optional) type.
*
// Use the parents constructor.... good good reuse
parent::__construct($properties);
+ $this->showinflatnavigation = true;
// Initalise and set defaults
$this->page = $page;
$this->load_course_sections($SITE, $this->rootnodes['site']);
$course = $this->page->course;
+ $this->load_courses_enrolled();
// $issite gets set to true if the current pages course is the sites frontpage course
$issite = ($this->page->course->id == $SITE->id);
+
// Determine if the user is enrolled in any course.
$enrolledinanycourse = enrol_user_sees_own_courses();
$this->rootnodes['currentcourse']->mainnavonly = true;
if ($enrolledinanycourse) {
$this->rootnodes['mycourses']->isexpandable = true;
+ $this->rootnodes['mycourses']->showinflatnavigation = true;
if ($CFG->navshowallcourses) {
// When we show all courses we need to show both the my courses and the regular courses branch.
$this->rootnodes['courses']->isexpandable = true;
// This is the name that will be shown for the course.
$coursename = empty($CFG->navshowfullcoursenames) ? $shortname : $fullname;
+ if ($coursetype == self::COURSE_CURRENT) {
+ if ($coursenode = $this->rootnodes['mycourses']->find($course->id, self::TYPE_COURSE)) {
+ return $coursenode;
+ } else {
+ $coursetype = self::COURSE_OTHER;
+ }
+ }
+
// Can the user expand the course to see its content.
$canexpandcourse = true;
if ($issite) {
}
$coursenode = $parent->add($coursename, $url, self::TYPE_COURSE, $shortname, $course->id);
+ $coursenode->showinflatnavigation = $coursetype == self::COURSE_MY;
$coursenode->hidden = (!$course->visible);
$coursenode->title(format_string($course->fullname, true, array('context' => $coursecontext, 'escape' => false)));
if ($canexpandcourse) {
if ($navoptions->badges) {
$url = new moodle_url('/badges/view.php', array('type' => 2, 'id' => $course->id));
- $coursenode->add(get_string('coursebadges', 'badges'), null,
- navigation_node::TYPE_CONTAINER, null, 'coursebadges');
- $coursenode->get('coursebadges')->add(get_string('badgesview', 'badges'), $url,
+ $coursenode->add(get_string('coursebadges', 'badges'), $url,
navigation_node::TYPE_SETTING, null, 'badgesview',
- new pix_icon('i/badge', get_string('badgesview', 'badges')));
+ new pix_icon('i/badge', get_string('coursebadges', 'badges')));
+ }
+
+ // Check access to the course and competencies page.
+ if ($navoptions->competencies) {
+ // Just a link to course competency.
+ $title = get_string('competencies', 'core_competency');
+ $path = new moodle_url("/admin/tool/lp/coursecompetencies.php", array('courseid' => $course->id));
+ $coursenode->add($title, $path, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/competencies', ''));
+ }
+ if ($navoptions->grades) {
+ $url = new moodle_url('/grade/report/index.php', array('id'=>$course->id));
+ $gradenode = $coursenode->add(get_string('grades'), $url, self::TYPE_SETTING, null, 'grades', new pix_icon('i/grades', ''));
}
return true;
* @return bool True for successfull generation
*/
public function add_front_page_course_essentials(navigation_node $coursenode, stdClass $course) {
- global $CFG;
+ global $CFG, $USER;
require_once($CFG->dirroot . '/course/lib.php');
if ($coursenode == false || $coursenode->get('frontpageloaded', navigation_node::TYPE_CUSTOM)) {
if ($navoptions->calendar) {
// Calendar
$calendarurl = new moodle_url('/calendar/view.php', array('view' => 'month'));
- $coursenode->add(get_string('calendar', 'calendar'), $calendarurl, self::TYPE_CUSTOM, null, 'calendar');
+ $node = $coursenode->add(get_string('calendar', 'calendar'), $calendarurl, self::TYPE_CUSTOM, null, 'calendar');
+ $node->showinflatnavigation = true;
+ }
+
+ if (isloggedin()) {
+ $usercontext = context_user::instance($USER->id);
+ if (has_capability('moodle/user:manageownfiles', $usercontext)) {
+ $url = new moodle_url('/user/files.php');
+ $node = $coursenode->add(get_string('privatefiles'), $url, self::TYPE_SETTING);
+ $node->display = false;
+ $node->showinflatnavigation = true;
+ }
}
return true;
public $includesettingsbase = false;
/** @var breadcrumb_navigation_node[] $prependchildren */
protected $prependchildren = array();
+
/**
* The almighty constructor
*
* @param moodle_page $page
*/
-
-
public function __construct(moodle_page $page) {
global $CFG;
if (during_initial_install()) {
$items = array_merge($items, array_reverse($this->prependchildren));
}
+ $last = reset($items);
+ if ($last) {
+ $last->set_last(true);
+ }
$this->items = array_reverse($items);
return $this->items;
}
*/
class breadcrumb_navigation_node extends navigation_node {
+ /** @var $last boolean A flag indicating this is the last item in the list of breadcrumbs. */
+ private $last = false;
+
/**
* A proxy constructor
*
}
}
+ /**
+ * Getter for "last"
+ * @return boolean
+ */
+ public function is_last() {
+ return $this->last;
+ }
+
+ /**
+ * Setter for "last"
+ * @param $val boolean
+ */
+ public function set_last($val) {
+ $this->last = $val;
+ }
+}
+
+/**
+ * Subclass of navigation_node allowing different rendering for the flat navigation
+ * in particular allowing dividers and indents.
+ *
+ * @package core
+ * @category navigation
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class flat_navigation_node extends navigation_node {
+
+ /** @var $indent integer The indent level */
+ private $indent = 0;
+
+ /** @var $showdivider bool Show a divider before this element */
+ private $showdivider = false;
+
+ /** @var $smscreenonly bool Only show this menu item on xs and sm screen sizes */
+ private $smscreenonly = false;
+
+ /**
+ * A proxy constructor
+ *
+ * @param mixed $navnode A navigation_node or an array
+ */
+ public function __construct($navnode, $indent) {
+ if (is_array($navnode)) {
+ parent::__construct($navnode);
+ } else if ($navnode instanceof navigation_node) {
+
+ // Just clone everything.
+ $objvalues = get_object_vars($navnode);
+ foreach ($objvalues as $key => $value) {
+ $this->$key = $value;
+ }
+ } else {
+ throw coding_exception('Not a valid flat_navigation_node');
+ }
+ $this->indent = $indent;
+ }
+
+ /**
+ * Getter for "showdivider"
+ * @return boolean
+ */
+ public function showdivider() {
+ return $this->showdivider;
+ }
+
+ /**
+ * Setter for "showdivider"
+ * @param $val boolean
+ */
+ public function set_showdivider($val) {
+ $this->showdivider = $val;
+ }
+
+ /**
+ * Getter for "indent"
+ * @return boolean
+ */
+ public function get_indent() {
+ return $this->indent;
+ }
+
+ /**
+ * Setter for "indent"
+ * @param $val boolean
+ */
+ public function set_indent($val) {
+ $this->indent = $val;
+ }
+
+ /**
+ * Getter for "smscreenonly"
+ * @return boolean
+ */
+ public function get_smscreenonly() {
+ return $this->smscreenonly;
+ }
+
+ /**
+ * Setter for "smscreenonly"
+ * @param $val boolean
+ */
+ public function set_smscreenonly($val) {
+ $this->smscreenonly = $val;
+ }
+}
+
+/**
+ * Class used to generate a collection of navigation nodes most closely related
+ * to the current page.
+ *
+ * @package core
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class flat_navigation extends navigation_node_collection {
+ /** @var moodle_page the moodle page that the navigation belongs to */
+ protected $page;
+
+ /**
+ * Constructor.
+ *
+ * @param moodle_page $page
+ */
+ public function __construct(moodle_page &$page) {
+ if (during_initial_install()) {
+ return false;
+ }
+ $this->page = $page;
+ }
+
+ /**
+ * Build the list of navigation nodes based on the current navigation and settings trees.
+ *
+ */
+ public function initialise() {
+ global $PAGE, $USER, $OUTPUT, $CFG;
+ if (during_initial_install()) {
+ return;
+ }
+
+ $current = false;
+
+ $course = $PAGE->course;
+
+ $PAGE->navigation->build_flat_navigation_list($this);
+
+ // First walk the nav tree looking for "flat_navigation" nodes.
+ if ($course->id > 1) {
+ // It's a real course.
+ // 'dh' is an unused param used to give this node a different url to the default.
+ // This is so we don't have 2 nodes in the flat have with the same url (both would be highlighted).
+ // 'dh' means "don't highlight".
+ $url = new moodle_url('/course/view.php', array('id' => $course->id, 'dh' => 1));
+ $flat = new flat_navigation_node(navigation_node::create($course->shortname, $url), 0);
+ $flat->key = 'coursehome';
+ $flat->set_showdivider(true);
+ $this->add($flat);
+
+ $coursenode = $PAGE->navigation->find_active_node();
+ if ($coursenode) {
+ foreach ($coursenode->children as $child) {
+ if ($child->action) {
+ $flat = new flat_navigation_node($child, 1);
+ $this->add($flat);
+ }
+ }
+ }
+
+ }
+ $admin = $PAGE->settingsnav->find('siteadministration', navigation_node::TYPE_SITE_ADMIN);
+ if (!$admin) {
+ // Try again - crazy nav tree!
+ $admin = $PAGE->settingsnav->find('root', navigation_node::TYPE_SITE_ADMIN);
+ }
+ if ($admin) {
+ $flat = new flat_navigation_node($admin, 0);
+ $flat->set_showdivider(true);
+ $flat->key = 'sitesettings';
+ $this->add($flat);
+ }
+
+ // Add the lang menu for small screens (it doesn't fit in the header).
+ if (!empty($CFG->langmenu)) {
+ if ($PAGE->course == SITEID || empty($PAGE->course->lang)) {
+ $langs = get_string_manager()->get_list_of_translations();
+ if (count($langs) >= 2) {
+ $first = true;
+ foreach ($langs as $lang => $name) {
+ $url = clone($PAGE->url);
+ $url->params(['lang' => $lang]);
+ $flat = new flat_navigation_node(navigation_node::create($name, $url), 0);
+ if ($first) {
+ $flat->set_showdivider(true);
+ $first = false;
+ }
+ $flat->set_smscreenonly(true);
+ $flat->key = $lang;
+ $this->add($flat);
+ }
+ }
+ }
+ }
+
+ // Add the custom menu for small screens (it doesn't fit in the header).
+ $customcount = 0;
+ if (!empty($CFG->custommenuitems)) {
+ $custommenus = custom_menu::convert_text_to_menu_nodes($CFG->custommenuitems, current_language());
+ $first = true;
+ foreach ($custommenus as $menu) {
+ if (preg_match("/^#+$/", $menu->get_text())) {
+ $first = true;
+ } else {
+ $url = $menu->get_url();
+ if ($url) {
+ $url = $url->out(false);
+ }
+ $flat = new flat_navigation_node(navigation_node::create($menu->get_text(), $url), 0);
+ if ($first) {
+ $flat->set_showdivider(true);
+ $first = false;
+ }
+ $flat->set_smscreenonly(true);
+ $flat->key = 'c-' . $customcount++;
+ $this->add($flat);
+ }
+ foreach ($menu->get_children() as $child) {
+ if (preg_match("/^#+$/", $child->get_text())) {
+ $first = true;
+ } else {
+ $url = $child->get_url();
+ if ($url) {
+ $url = $url->out(false);
+ }
+ $flat = new flat_navigation_node(navigation_node::create($child->get_text(), $url), 1);
+ $flat->set_smscreenonly(true);
+ $flat->key = 'c-' . $customcount++;
+ $this->add($flat);
+ }
+ }
+ }
+
+ }
+ }
+
}
/**
$this->cache = new navigation_cache(NAVIGATION_CACHE_NAME);
$this->children = new navigation_node_collection();
}
+
/**
* Initialise the settings navigation based on the current context
*
$adminsettings->remove();
$adminsettings = false;
}
- $siteadminnode = $this->add(get_string('administrationsite'), new moodle_url('/admin'), self::TYPE_SITE_ADMIN, null, 'siteadministration');
+ $siteadminnode = $this->add(get_string('administrationsite'), new moodle_url('/admin/search.php'), self::TYPE_SITE_ADMIN, null, 'siteadministration');
$siteadminnode->id = 'expandable_branch_'.$siteadminnode->type.'_'.clean_param($siteadminnode->key, PARAM_ALPHANUMEXT);
$siteadminnode->requiresajaxloading = 'true';
}
// Disable the navigation from automatically finding the active node
navigation_node::$autofindactive = false;
- $referencebranch = $this->add(get_string('administrationsite'), null, self::TYPE_SITE_ADMIN, null, 'root');
+ $referencebranch = $this->add(get_string('administrationsite'), '/admin/search.php', self::TYPE_SITE_ADMIN, null, 'root');
foreach ($adminroot->children as $adminbranch) {
$this->load_administration_settings($referencebranch, $adminbranch);
}
$coursenode->force_open();
}
- if ($this->page->user_allowed_editing()) {
- // Add the turn on/off settings
-
- if ($this->page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) {
- // We are on the course page, retain the current page params e.g. section.
- $baseurl = clone($this->page->url);
- $baseurl->param('sesskey', sesskey());
- } else {
- // Edit on the main course page.
- $baseurl = new moodle_url('/course/view.php', array('id'=>$course->id, 'return'=>$this->page->url->out_as_local_url(false), 'sesskey'=>sesskey()));
- }
-
- $editurl = clone($baseurl);
- if ($this->page->user_is_editing()) {
- $editurl->param('edit', 'off');
- $editstring = get_string('turneditingoff');
- } else {
- $editurl->param('edit', 'on');
- $editstring = get_string('turneditingon');
- }
- $coursenode->add($editstring, $editurl, self::TYPE_SETTING, null, 'turneditingonoff', new pix_icon('i/edit', ''));
- }
-
if ($adminoptions->update) {
// Add the course settings link
$url = new moodle_url('/course/edit.php', array('id'=>$course->id));
}
}
if (is_array($roles) && count($roles)>0) {
- $switchroles = $this->add(get_string('switchroleto'), null, self::TYPE_CONTAINER, null, 'switchroleto');
+ $url = new moodle_url('/course/switchrole.php', array('id'=>$course->id, 'switchrole'=>'-1', 'returnurl'=>$this->page->url->out_as_local_url(false)));
+ $switchroles = $coursenode->add(get_string('switchroleto'), $url, self::TYPE_CONTAINER, null, 'switchroleto');
if ((count($roles)==1 && array_key_exists(0, $roles))|| $assumedrole!==false) {
$switchroles->force_open();
}
if (($currentuser || is_siteadmin($USER) || !is_siteadmin($user)) &&
has_capability('moodle/user:update', $systemcontext)) {
$url = new moodle_url('/user/editadvanced.php', array('id'=>$user->id, 'course'=>$course->id));
- $useraccount->add(get_string('editmyprofile'), $url, self::TYPE_SETTING);
+ $useraccount->add(get_string('editmyprofile'), $url, self::TYPE_SETTING, null, 'editprofile');
} else if ((has_capability('moodle/user:editprofile', $usercontext) && !is_siteadmin($user)) ||
($currentuser && has_capability('moodle/user:editownprofile', $systemcontext))) {
if ($userauthplugin && $userauthplugin->can_edit_profile()) {
if (empty($url)) {
$url = new moodle_url('/user/edit.php', array('id'=>$user->id, 'course'=>$course->id));
}
- $useraccount->add(get_string('editmyprofile'), $url, self::TYPE_SETTING);
+ $useraccount->add(get_string('editmyprofile'), $url, self::TYPE_SETTING, null, 'editprofile');
}
}
}
$this->menutrigger = $trigger;
}
+ /**
+ * Return true if there is at least one visible link in the menu.
+ *
+ * @return bool
+ */
+ public function is_empty() {
+ return !count($this->primaryactions) && !count($this->secondaryactions);
+ }
+
/**
* Initialises JS required fore the action menu.
* The JS is only required once as it manages all action menu's on the page.
return $html;
}
- /**
- * Returns the header bar.
- *
- * @since Moodle 2.9
- * @param array $headerinfo An array of header information, dependant on what type of header is being displayed. The following
- * array example is user specific.
- * heading => Override the page heading.
- * user => User object.
- * usercontext => user context.
- * @param int $headinglevel What level the 'h' tag will be.
- * @return string HTML for the header bar.
- */
public function context_header($headerinfo = null, $headinglevel = 1) {
global $DB, $USER, $CFG;
$context = $this->page->context;
}
}
+ /**
+ * Render the login signup form into a nice template for the theme.
+ *
+ * @param mform $form
+ * @return string
+ */
+ public function render_login_signup_form($form) {
+ $context = $form->export_for_template($this);
+
+ return $this->render_from_template('core/signup_form_layout', $context);
+ }
+
/**
* Renders a progress bar.
*
*/
protected $_settingsnav = null;
+ /**
+ * @var flat_navigation Contains a list of nav nodes, most closely related to the current page.
+ */
+ protected $_flatnav = null;
+
/**
* @var navbar Contains the navbar structure.
*/
return $this->_settingsnav;
}
+ /**
+ * Returns the flat navigation object
+ * @return flat_navigation
+ */
+ protected function magic_get_flatnav() {
+ if ($this->_flatnav === null) {
+ $this->_flatnav = new flat_navigation($this);
+ $this->_flatnav->initialise();
+ }
+ return $this->_flatnav;
+ }
+
/**
* Returns request IP address.
*
--- /dev/null
+{{!
+ 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_admin/admin_settings_links
+
+ Displays the admin tree as a list of grouped links.
+
+ Example context (json):
+ {
+ "name": "test",
+ "id": "test0",
+ "checked": true,
+ "label": "Do you like crackers?"
+ }
+}}
+
+<div class="container">
+ <div class="row">
+ <div class="col-md-6 push-md-3">
+ <div class="card">
+ <div class="card-block">
+ {{#node}}
+ {{> core/settings_link_page_single }}
+ {{/node}}
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
--- /dev/null
+{{!
+ 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/settings_link_page_single
+
+ Displays the admin tree as a list of grouped links.
+
+ Example context (json):
+ {
+ }
+}}
+
+<ul class="nav m-l-2">
+ {{#has_action}}
+ <li class="nav-item"><a class="nav-link" href="{{{action}}}">{{text}}</a></li>
+ {{/has_action}}
+ {{^has_action}}
+ <li class="nav-item">{{text}}</li>
+ {{/has_action}}
+ {{#children.count}}
+ {{#children}}
+ {{> core/settings_link_page_single }}
+ {{/children}}
+ {{/children.count}}
+</ul>
--- /dev/null
+<h3>{{#str}}newaccount{{/str}}</h3>
+{{{formhtml}}}
$PAGE->navbar->add($login);
$PAGE->navbar->add($newaccount);
+$PAGE->set_pagelayout('login');
$PAGE->set_title($newaccount);
$PAGE->set_heading($SITE->fullname);
echo $OUTPUT->header();
-echo $OUTPUT->heading($newaccount);
-$mform_signup->display();
+
+echo $OUTPUT->render($mform_signup);
echo $OUTPUT->footer();
require_once($CFG->dirroot.'/user/profile/lib.php');
require_once($CFG->dirroot . '/user/editlib.php');
-class login_signup_form extends moodleform {
+class login_signup_form extends moodleform implements renderable, templatable {
function definition() {
global $USER, $CFG;
return $errors;
}
+
+ /**
+ * Export this data so it can be used as the context for a mustache template.
+ *
+ * @param renderer_base $output Used to do a final render of any components that need to be rendered for export.
+ * @return array
+ */
+ public function export_for_template(renderer_base $output) {
+ ob_start();
+ $this->display();
+ $formhtml = ob_get_contents();
+ ob_end_clean();
+ $context = [
+ 'formhtml' => $formhtml
+ ];
+ return $context;
+ }
}
--- /dev/null
+// 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/>.
+
+/**
+ * Contain the logic for a drawer.
+ *
+ * @package theme_boost
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/custom_interaction_events', 'core/notification'],
+ function($, CustomEvents, Notification) {
+
+ var SELECTORS = {
+ TOGGLE_REGION: '[data-region="drawer-toggle"]',
+ TOGGLE_ACTION: '[data-action="toggle-drawer"]',
+ TOGGLE_TARGET: 'aria-controls',
+ TOGGLE_SIDE: 'left',
+ BODY: 'body'
+ };
+
+ /**
+ * Constructor for the Drawer.
+ *
+ * @param {object} root The root jQuery element for the modal
+ */
+ var Drawer = function() {
+
+ if (!$(SELECTORS.TOGGLE_REGION).length) {
+ Notification.exception({message: 'Page is missing a drawer toggle region'});
+ }
+ if (!$(SELECTORS.TOGGLE_ACTION).length) {
+ Notification.exception({message: 'Page is missing a drawer toggle link'});
+ }
+ $(SELECTORS.TOGGLE_REGION).each(function(index, ele) {
+ var trigger = $(ele).find(SELECTORS.TOGGLE_ACTION);
+ var hidden = trigger.attr('aria-expanded') == 'false';
+ var side = trigger.attr('data-side');
+ var body = $(SELECTORS.BODY);
+
+ if (!hidden) {
+ body.addClass('drawer-open-' + side);
+ trigger.attr('aria-expanded', 'true');
+ } else {
+ trigger.attr('aria-expanded', 'false');
+ }
+ }.bind(this));
+
+ this.registerEventListeners();
+ };
+
+ Drawer.prototype.closeAll = function() {
+ $(SELECTORS.TOGGLE_REGION).each(function(index, ele) {
+ var trigger = $(ele).find(SELECTORS.TOGGLE_ACTION);
+ var side = trigger.attr('data-side');
+ var body = $(SELECTORS.BODY);
+ var drawerid = trigger.attr('aria-controls');
+ var drawer = $(document.getElementById(drawerid));
+ var preference = trigger.attr('data-preference');
+
+ trigger.attr('aria-expanded', 'false');
+ body.removeClass('drawer-open-' + side);
+ drawer.attr('aria-hidden', 'true');
+ drawer.addClass('closed');
+ M.util.set_user_preference(preference, 'false');
+ }.bind(this));
+ };
+
+ /**
+ * Open / close the blocks drawer.
+ *
+ * @method toggleDrawer
+ * @param {Event} e
+ */
+ Drawer.prototype.toggleDrawer = function(e) {
+ var trigger = $(e.target).closest('[data-action=toggle-drawer]');
+ var drawerid = trigger.attr('aria-controls');
+ var drawer = $(document.getElementById(drawerid));
+ var body = $(SELECTORS.BODY);
+ var side = trigger.attr('data-side');
+ var preference = trigger.attr('data-preference');
+
+ body.addClass('drawer-ease');
+ var open = trigger.attr('aria-expanded') == 'true';
+ if (!open) {
+ var small = $(document).width() < 512;
+ if (small) {
+ this.closeAll();
+ }
+ // Open.
+ trigger.attr('aria-expanded', 'true');
+ drawer.attr('aria-hidden', 'false');
+ body.addClass('drawer-open-' + side);
+ drawer.removeClass('closed');
+ M.util.set_user_preference(preference, 'true');
+ } else {
+ // Close.
+ body.removeClass('drawer-open-' + side);
+ trigger.attr('aria-expanded', 'false');
+ drawer.attr('aria-hidden', 'true');
+ drawer.addClass('closed');
+ M.util.set_user_preference(preference, 'false');
+ }
+ };
+
+ /**
+ * Set up all of the event handling for the modal.
+ *
+ * @method registerEventListeners
+ */
+ Drawer.prototype.registerEventListeners = function() {
+ var body = $(SELECTORS.BODY);
+
+ CustomEvents.define(body, [CustomEvents.events.activate]);
+
+ body.on(CustomEvents.events.activate, SELECTORS.TOGGLE_ACTION, function(e, data) {
+ this.toggleDrawer(data.originalEvent);
+ data.originalEvent.preventDefault();
+ }.bind(this));
+ };
+
+ return {
+ 'init': function() {
+ return new Drawer();
+ }
+ };
+});
use custom_menu_item;
use custom_menu;
use block_contents;
+use navigation_node;
+use action_link;
use stdClass;
use moodle_url;
use preferences_groups;
public function full_header() {
$html = html_writer::start_tag('header', array('id' => 'page-header', 'class' => 'row'));
$html .= html_writer::start_div('col-xs-12 p-t-1 p-b-1');
+ $html .= html_writer::div($this->context_header_settings_menu(), 'pull-xs-right context-header-settings-menu');
$html .= $this->context_header();
$html .= html_writer::start_div('clearfix', array('id' => 'page-navbar'));
$html .= html_writer::tag('div', $this->navbar(), array('class' => 'breadcrumb-nav'));
* @return string
*/
public function body_css_classes(array $additionalclasses = array()) {
- return $this->page->bodyclasses;
+ return $this->page->bodyclasses . ' ' . implode(' ', $additionalclasses);
}
/**
}
}
+ if ($menu->is_empty()) {
+ return '';
+ }
$context = $menu->export_for_template($this);
// We do not want the icon with the caret, the caret is added by Bootstrap.
}
return $this->render_from_template('core/pix_icon', $data);
}
+
+ /**
+ * Renders the login form.
+ *
+ * @param \core_auth\output\login $form The renderable.
+ * @return string
+ */
+ public function render_login(\core_auth\output\login $form) {
+ global $SITE;
+
+ $context = $form->export_for_template($this);
+
+ // Override because rendering is not supported in template yet.
+ $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
+ $context->errorformatted = $this->error_text($context->error);
+ $url = $this->get_logo_url();
+ if ($url) {
+ $url = $url->out(false);
+ }
+ $context->logourl = $url;
+ $context->sitename = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
+
+ return $this->render_from_template('core/login', $context);
+ }
+
+ /**
+ * Render the login signup form into a nice template for the theme.
+ *
+ * @param mform $form
+ * @return string
+ */
+ public function render_login_signup_form($form) {
+ global $SITE;
+
+ $context = $form->export_for_template($this);
+ $url = $this->get_logo_url();
+ if ($url) {
+ $url = $url->out(false);
+ }
+ $context['logourl'] = $url;
+ $context['sitename'] = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
+
+ return $this->render_from_template('core/signup_form_layout', $context);
+ }
+
+ /**
+ * This is an optional menu that can be added to a layout by a theme. It contains the
+ * menu for the course administration, only on the course main page.
+ *
+ * @return string
+ */
+ public function context_header_settings_menu() {
+ $context = $this->page->context;
+ $menu = new action_menu();
+ if ($context->contextlevel == CONTEXT_COURSE) {
+ // Get the course admin node from the settings navigation.
+ $items = $this->page->navbar->get_items();
+ $node = end($items);
+ if (($node->type == navigation_node::TYPE_COURSE)) {
+ $node = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
+ if ($node) {
+ // Build an action menu based on the visible nodes from this navigation tree.
+ $this->build_action_menu_from_navigation($menu, $node, false, true);
+
+ $text = get_string('courseadministration');
+ $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
+ $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
+ $menu->add_secondary_action($link);
+ }
+ }
+ } else if ($context->contextlevel == CONTEXT_USER) {
+ $items = $this->page->navbar->get_items();
+ $node = end($items);
+ if ($node->key === 'myprofile') {
+ // Get the course admin node from the settings navigation.
+ $node = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
+ if ($node) {
+ // Build an action menu based on the visible nodes from this navigation tree.
+ $this->build_action_menu_from_navigation($menu, $node);
+ }
+ }
+ }
+ return $this->render($menu);
+ }
+
+ /**
+ * This is an optional menu that can be added to a layout by a theme. It contains the
+ * menu for the most specific thing from the settings block. E.g. Module administration.
+ *
+ * @return string
+ */
+ public function region_main_settings_menu() {
+ $context = $this->page->context;
+ $menu = new action_menu();
+
+ if ($context->contextlevel == CONTEXT_MODULE) {
+
+ $node = $this->page->navigation->find_active_node();
+ if (($node->type == navigation_node::TYPE_ACTIVITY ||
+ $node->type == navigation_node::TYPE_RESOURCE)) {
+ // Get the course admin node from the settings navigation.
+ $node = $this->page->settingsnav->find('modulesettings', navigation_node::TYPE_SETTING);
+ if ($node) {
+ // Build an action menu based on the visible nodes from this navigation tree.
+ $this->build_action_menu_from_navigation($menu, $node);
+ }
+ }
+ }
+ return $this->render($menu);
+ }
+
+ /**
+ * Take a node in the nav tree and make an action menu out of it.
+ * The links are injected in the action menu.
+ *
+ * @param action_menu $menu
+ * @param navigation_node $node
+ * @param boolean $indent
+ * @param boolean $onlytopleafnodes
+ */
+ private function build_action_menu_from_navigation(action_menu $menu,
+ navigation_node $node,
+ $indent = false,
+ $onlytopleafnodes = false) {
+ // Build an action menu based on the visible nodes from this navigation tree.
+ foreach ($node->children as $menuitem) {
+ if ($menuitem->display) {
+ if ($onlytopleafnodes && $menuitem->children->count()) {
+ continue;
+ }
+ if ($menuitem->action) {
+ $text = $menuitem->text;
+ $link = new action_link($menuitem->action, $menuitem->text, null, null, $menuitem->icon);
+ if ($indent) {
+ $link->add_class('m-l-1');
+ }
+ } else {
+ if ($onlytopleafnodes) {
+ continue;
+ }
+ $link = $menuitem->text;
+ }
+ $menu->add_secondary_action($link);
+ $this->build_action_menu_from_navigation($menu, $menuitem, true);
+ }
+ }
+ }
+
}
'defaultregion' => 'side-pre',
),
'login' => array(
- 'file' => 'columns1.php',
+ 'file' => 'login.php',
'regions' => array(),
'options' => array('langmenu' => true),
),
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * A one column layout for the boost theme.
+ * A two column layout for the boost theme.
*
* @package theme_boost
* @copyright 2016 Damyon Wiese
defined('MOODLE_INTERNAL') || die();
+user_preference_allow_ajax_update('drawer-open-blocks', PARAM_ALPHA);
+user_preference_allow_ajax_update('drawer-open-nav', PARAM_ALPHA);
+
+$navdraweropen = (get_user_preferences('drawer-open-nav', 'true') == 'true');
+$blocksdraweropen = (get_user_preferences('drawer-open-blocks', 'true') == 'true');
+$extraclasses = [];
+if ($blocksdraweropen) {
+ $extraclasses[] = 'drawer-open-right';
+}
+if ($navdraweropen) {
+ $extraclasses[] = 'drawer-open-left';
+}
+$bodyattributes = $OUTPUT->body_attributes($extraclasses);
+
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, array('context' => context_course::instance(SITEID))),
- 'output' => $OUTPUT
+ 'output' => $OUTPUT,
+ 'sidepreblocks' => $OUTPUT->blocks('side-pre'),
+ 'bodyattributes' => $bodyattributes,
+ 'blocksdraweropen' => $blocksdraweropen,
+ 'navdraweropen' => $navdraweropen
];
+$templatecontext['flatnavigation'] = $PAGE->flatnav;
echo $OUTPUT->render_from_template('theme_boost/columns1', $templatecontext);
+
defined('MOODLE_INTERNAL') || die();
+user_preference_allow_ajax_update('drawer-open-blocks', PARAM_ALPHA);
+user_preference_allow_ajax_update('drawer-open-nav', PARAM_ALPHA);
+
+$navdraweropen = (get_user_preferences('drawer-open-nav', 'true') == 'true');
+$blocksdraweropen = (get_user_preferences('drawer-open-blocks', 'true') == 'true');
+$extraclasses = [];
+if ($blocksdraweropen) {
+ $extraclasses[] = 'drawer-open-right';
+}
+if ($navdraweropen) {
+ $extraclasses[] = 'drawer-open-left';
+}
+$bodyattributes = $OUTPUT->body_attributes($extraclasses);
+
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, array('context' => context_course::instance(SITEID))),
'output' => $OUTPUT,
- 'sidepreblocks' => $OUTPUT->blocks('side-pre', 'col-md-4 pull-md-8'),
+ 'sidepreblocks' => $OUTPUT->blocks('side-pre'),
+ 'bodyattributes' => $bodyattributes,
+ 'blocksdraweropen' => $blocksdraweropen,
+ 'navdraweropen' => $navdraweropen
];
+$templatecontext['flatnavigation'] = $PAGE->flatnav;
echo $OUTPUT->render_from_template('theme_boost/columns2', $templatecontext);
+
--- /dev/null
+<?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/>.
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * A two column layout for the boost theme.
+ *
+ * @package theme_boost
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$bodyattributes = $OUTPUT->body_attributes();
+
+$templatecontext = [
+ 'sitename' => format_string($SITE->shortname, true, array('context' => context_course::instance(SITEID))),
+ 'output' => $OUTPUT,
+ 'bodyattributes' => $bodyattributes
+];
+
+echo $OUTPUT->render_from_template('theme_boost/login', $templatecontext);
+
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, array('context' => context_course::instance(SITEID))),
'output' => $OUTPUT,
- 'sidepreblocks' => $OUTPUT->blocks('side-pre', 'col-md-4 pull-md-8 col-lg-3 pull-lg-9'),
- 'sidepostblocks' => $OUTPUT->blocks('side-post', 'col-md-3')
+ 'sidepreblocks' => $OUTPUT->blocks('side-pre'),
];
echo $OUTPUT->render_from_template('theme_boost/secure', $templatecontext);
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#373A3C;}
+</style>
+<path class="st0" d="M40,3.9v24.3c0,1-0.3,1.8-1,2.5s-1.5,1-2.5,1H3.6c-1,0-1.8-0.3-2.5-1s-1-1.5-1-2.5V3.9c0-1,0.3-1.8,1-2.5
+ s1.5-1,2.5-1h32.9c1,0,1.8,0.4,2.5,1C39.7,2.1,40,2.9,40,3.9z M37.1,28.2V9.6c0-0.2-0.1-0.4-0.2-0.5c-0.1-0.1-0.3-0.2-0.5-0.2H3.6
+ C3.4,8.9,3.2,9,3.1,9.1C2.9,9.3,2.9,9.4,2.9,9.6v18.6c0,0.2,0.1,0.4,0.2,0.5c0.1,0.1,0.3,0.2,0.5,0.2h32.9c0.2,0,0.4-0.1,0.5-0.2
+ S37.1,28.4,37.1,28.2z M8.6,12.5v1.4c0,0.2-0.1,0.4-0.2,0.5c-0.1,0.1-0.3,0.2-0.5,0.2H6.4c-0.2,0-0.4-0.1-0.5-0.2
+ c-0.1-0.1-0.2-0.3-0.2-0.5v-1.4c0-0.2,0.1-0.4,0.2-0.5s0.3-0.2,0.5-0.2h1.4c0.2,0,0.4,0.1,0.5,0.2C8.5,12.1,8.6,12.3,8.6,12.5z
+ M8.6,18.2v1.4c0,0.2-0.1,0.4-0.2,0.5c-0.1,0.1-0.3,0.2-0.5,0.2H6.4c-0.2,0-0.4-0.1-0.5-0.2s-0.2-0.3-0.2-0.5v-1.4
+ c0-0.2,0.1-0.4,0.2-0.5s0.3-0.2,0.5-0.2h1.4c0.2,0,0.4,0.1,0.5,0.2C8.5,17.9,8.6,18,8.6,18.2z M8.6,23.9v1.4c0,0.2-0.1,0.4-0.2,0.5
+ C8.3,25.9,8.1,26,7.9,26H6.4c-0.2,0-0.4-0.1-0.5-0.2s-0.2-0.3-0.2-0.5v-1.4c0-0.2,0.1-0.4,0.2-0.5s0.3-0.2,0.5-0.2h1.4
+ c0.2,0,0.4,0.1,0.5,0.2C8.5,23.6,8.6,23.7,8.6,23.9z M34.3,12.5v1.4c0,0.2-0.1,0.4-0.2,0.5c-0.1,0.1-0.3,0.2-0.5,0.2H12.1
+ c-0.2,0-0.4-0.1-0.5-0.2c-0.1-0.1-0.2-0.3-0.2-0.5v-1.4c0-0.2,0.1-0.4,0.2-0.5c0.1-0.1,0.3-0.2,0.5-0.2h21.4c0.2,0,0.4,0.1,0.5,0.2
+ C34.2,12.1,34.3,12.3,34.3,12.5z M34.3,18.2v1.4c0,0.2-0.1,0.4-0.2,0.5c-0.1,0.1-0.3,0.2-0.5,0.2H12.1c-0.2,0-0.4-0.1-0.5-0.2
+ s-0.2-0.3-0.2-0.5v-1.4c0-0.2,0.1-0.4,0.2-0.5c0.1-0.1,0.3-0.2,0.5-0.2h21.4c0.2,0,0.4,0.1,0.5,0.2C34.2,17.9,34.3,18,34.3,18.2z
+ M34.3,23.9v1.4c0,0.2-0.1,0.4-0.2,0.5C34,25.9,33.8,26,33.6,26H12.1c-0.2,0-0.4-0.1-0.5-0.2s-0.2-0.3-0.2-0.5v-1.4
+ c0-0.2,0.1-0.4,0.2-0.5c0.1-0.1,0.3-0.2,0.5-0.2h21.4c0.2,0,0.4,0.1,0.5,0.2C34.2,23.6,34.3,23.7,34.3,23.9z"/>
+</svg>
@import "moodle/icons";
@import "moodle/admin";
@import "moodle/blocks";
+@import "moodle/bootswatch";
@import "moodle/calendar";
@import "moodle/course";
+@import "moodle/drawer";
@import "moodle/filemanager";
@import "moodle/message";
@import "moodle/question";
@import "moodle/user";
@import "moodle/search";
@import "moodle/forms";
+@import "moodle/login";
@import "moodle/modules";
@import "moodle/chat";
@import "moodle/reports";
}
}
}
+
+#nav-drawer.closed {
+ left: -285px;
+}
+#blocks-drawer.closed {
+ right: -285px;
+}
+
+/* Use a variable for the drawer background colors. */
+$drawer-bg: $gray-lighter !default;
+
+[data-region="drawer"] {
+ position: fixed;
+ padding: 20px;
+ width: 265px;
+ top: ($navbar-padding-y * 2) + ($navbar-brand-padding-y * 2) + $font-size-lg * 1.5;
+ height: 100%;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ z-index: 100;
+ background-color: $drawer-bg;
+ -webkit-transition: right 0.5s ease, left 0.5s ease;
+ -moz-transition: right 0.5s ease, left 0.5s ease;
+ transition: right 0.5s ease, left 0.5s ease;
+}
+#nav-drawer {
+ right: auto;
+ left: 0px;
+}
+#blocks-drawer {
+ left: auto;
+ right: 0px;
+}
+body.drawer-ease {
+ -webkit-transition: margin-left 0.5s ease, margin-right 0.5s ease;
+ -moz-transition: margin-left 0.5s ease, margin-right 0.5s ease;
+ transition: margin-left 0.5s ease, margin-right 0.5s ease;
+}
+
+body.drawer-open-left {
+ @include media-breakpoint-up(md) {
+ margin-left: 265px;
+ }
+}
+body.drawer-open-right {
+ @include media-breakpoint-up(md) {
+ margin-right: 265px;
+ }
+}
--- /dev/null
+// Adjustments to make bootstrap 4 work better with some variables from bootstrap 3 bootswatches
+$navbar-height: 60px !default;
+
+.navbar {
+ max-height: $navbar-height;
+}
+
+.navbar-brand {
+ margin-top: (($font-size-base * $line-height-base) - ($font-size-lg * $line-height-base)) / 2;
+}
/* core.less */
+
+.context-header-settings-menu,
+.region-main-settings-menu {
+ float: right;
+ width: 4em;
+ height: 2em;
+ display: block;
+}
+
+.context-header-settings-menu .dropdown-toggle > .icon,
+.region-main-settings-menu .dropdown-toggle > .icon {
+ height: 24px;
+ width: auto;
+}
+
/** Page layout CSS starts **/
.layout-option-noheader #page-header,
.layout-option-nonavbar #page-navbar,
}
}
-/** Moodle modals. */
-.modal.show {
- display: block;
-}
-
/* Moodle Dialogue Settings (moodle-core-dialogue) */
.moodle-dialogue-base .moodle-dialogue-lightbox {
background-color: $gray;
.breadcrumb-nav .breadcrumb {
margin: 0;
}
-/** Navbar */
-.navbar-brand {
- .logo {
- display: inline-block;
- margin: -$navbar-brand-padding-y 0;
- }
-
- .site-name {
- display: inline-block;
- }
-
- &.has-logo {
- .site-name {
- margin-left: $spacer / 2;
- }
- }
-}
-
-@include media-breakpoint-down(xs) {
- .navbar {
- .navbar-brand {
- max-width: 80%;
- margin-right: 0;
-
- &.has-logo {
- .site-name {
- display: none;
- }
- }
- }
- }
-}
/** Page header */
#page-header {
}
}
}
+
+#region-flat-nav {
+ padding-right: 0;
+ padding-left: 0;
+ .nav {
+ margin-right: $grid-gutter-width / 2;
+ background-color: $card-bg;
+ }
+ @include media-breakpoint-down(sm) {
+ .nav {
+ margin-top: $grid-gutter-width;
+ margin-right: 0;
+ }
+ }
+}
&.right {
float: right;
+ clear: right;
}
+ margin-top: 0.5rem;
}
.spinner {
}
}
}
+
+.page-settings-menu .menubar > a > .icon {
+ width: auto;
+ height: 32px;
+}
--- /dev/null
+/* Anchor link offset fix. This makes hash links scroll 60px down to account for the fixed header. */
+$fixed-header-y: $navbar-height;
+
+$drawer-width: 285px;
+$drawer-padding-x: 20px;
+$drawer-padding-y: 20px;
+$drawer-offscreen-gutter: 20px;
+
+:target {
+ padding-top: ($fixed-header-y + 30px) ! important; /* negative fixed header height */
+ margin-top: -$fixed-header-y ! important; /* negative fixed header height */
+}
+
+#nav-drawer.closed {
+ left: - ($drawer-width + $drawer-offscreen-gutter);
+}
+#blocks-drawer.closed {
+ right: - ($drawer-width + $drawer-offscreen-gutter);
+}
+#page {
+ margin-top: $navbar-height;
+}
+
+/* Use a variable for the drawer background colors. */
+$drawer-bg: $gray-lighter !default;
+
+[data-region="drawer"] {
+ position: fixed;
+ padding: $drawer-padding-x $drawer-padding-y;
+ width: $drawer-width;
+ top: $fixed-header-y;
+ height: 100%;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ z-index: $zindex-dropdown - 1;
+ background-color: $drawer-bg;
+ -webkit-transition: right 0.5s ease, left 0.5s ease;
+ -moz-transition: right 0.5s ease, left 0.5s ease;
+ transition: right 0.5s ease, left 0.5s ease;
+ .dropdown-menu {
+ max-width: $drawer-width - $drawer-padding-x * 4;
+ }
+ .dropdown-item {
+ max-width: 100%;
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ }
+}
+#nav-drawer {
+ right: auto;
+ left: 0px;
+}
+#blocks-drawer {
+ left: auto;
+ right: 0px;
+}
+#page {
+ margin-top: $fixed-header-y;
+}
+body.drawer-ease {
+ -webkit-transition: margin-left 0.5s ease, margin-right 0.5s ease;
+ -moz-transition: margin-left 0.5s ease, margin-right 0.5s ease;
+ transition: margin-left 0.5s ease, margin-right 0.5s ease;
+}
+
+body.drawer-open-left {
+ @include media-breakpoint-up(lg) {
+ margin-left: $drawer-width;
+ }
+}
+body.drawer-open-right {
+ @include media-breakpoint-up(lg) {
+ margin-right: $drawer-width;
+ }
+}
margin-left: 0;
}
}
+
+[data-action=toggle-drawer] .icon {
+ margin: 0px;
+}
--- /dev/null
+.pagelayout-login .card-img-top {
+ max-width: 100%;
+}
+
+.pagelayout-login #region-main {
+ border: 0;
+ background-color: inherit;
+}
$brand-warning: #ff8800 !default;
$brand-danger: #ff4136 !default;
$brand-inverse: $gray-dark !default;
+$navbar-height: 50px !default;
// Spacing
$spacer: 1rem !default;
border-top: none;
}
-/**
- * Login page.
- */
-.pagelayout-login {
- &.notloggedin {
- #region-main {
- background-color: transparent;
- border: 0;
- padding: 0;
- }
- .login-wrapper {
- background-color: #fff;
- border: $border-width solid $card-border-color;
- }
- }
- #notice {
- text-align: center;
- }
-}
-
/**
* Dashboard styling.
*/
.form-inline .form-group {
margin-top: 0;
}
+
+
+// Custom transitions for open/close of menus.
+.dropdown-menu {
+ display: block;
+ max-height: 0px;
+ overflow: hidden;
+ opacity: 0;
+ -webkit-transition: max-height 1s ease, opacity 0.4s ease;
+ -moz-transition: max-height 1s ease, opacity 0.4s ease;
+ transition: max-height 1s ease, opacity 0.4s ease;
+}
+.open {
+ // Show the menu
+ > .dropdown-menu {
+ max-height: 2048px;
+ opacity: 100;
+ }
+}
+
--- /dev/null
+<div id="blocks-drawer" data-region="drawer" class="moodle-has-zindex {{^blocksdraweropen}}closed{{/blocksdraweropen}}" aria-hidden="{{#blocksdraweropen}}false{{/blocksdraweropen}}{{^blocksdraweropen}}true{{/blocksdraweropen}}">
+ {{{ sidepreblocks }}}
+</div>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
-<body {{{ output.body_attributes }}}>
+<body {{{ bodyattributes }}}>
<div id="page-wrapper">
{{>theme_boost/header}}
- <div id="page" class="container">
+ <div id="page" class="container-fluid">
{{{ output.full_header }}}
<div id="page-content" class="row">
- <div id="region-main-box" class="col-xs-12">
- <div class="row">
- <section id="region-main" class="col-xs-12">
- {{{ output.course_content_header }}}
- {{{ output.main_content }}}
- {{{ output.course_content_footer }}}
- </section>
- </div>
+ <div id="region-main-box">
+ <section id="region-main" class="col-xs-12">
+ <span class="pull-xs-right page-settings-menu">
+ {{{ output.page_settings_menu }}}
+ </span>
+ {{{ output.course_content_header }}}
+ {{{ output.main_content }}}
+ {{{ output.course_content_footer }}}
+ </section>
</div>
</div>
</div>
+ {{> theme_boost/blocks-drawer }}
+ {{> theme_boost/nav-drawer }}
</div>
<footer id="page-footer" class="p-y-1">
<div class="container">
{{{ output.login_info }}}
{{{ output.home_link }}}
{{{ output.standard_footer_html }}}
-
{{{ output.standard_end_of_body_html }}}
</div>
</footer>
</html>
{{#js}}
require(['theme_boost/loader'], function() {});
+require(['theme_boost/drawer'], function(mod) {mod.init();});
{{/js}}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
-<body {{{ output.body_attributes }}}>
+<body {{{ bodyattributes }}}>
<div id="page-wrapper">
{{>theme_boost/header}}
- <div id="page" class="container">
+ <div id="page" class="container-fluid">
{{{ output.full_header }}}
<div id="page-content" class="row">
- <div id="region-main-box" class="col-md-8 push-md-4">
- <div class="row">
- <section id="region-main" class="col-xs-12">
- {{{ output.course_content_header }}}
- {{{ output.main_content }}}
- {{{ output.course_content_footer }}}
- </section>
- </div>
+ <div id="region-main-box">
+ <section id="region-main" class="col-xs-12">
+ <span class="pull-xs-right region-main-settings-menu">
+ {{{ output.region_main_settings_menu }}}
+ </span>
+ {{{ output.course_content_header }}}
+ {{{ output.main_content }}}
+ {{{ output.course_content_footer }}}
+ </section>
</div>
- {{{ sidepreblocks }}}
</div>
-
</div>
+ {{> theme_boost/blocks-drawer }}
+ {{> theme_boost/nav-drawer }}
</div>
<footer id="page-footer" class="p-y-1">
<div class="container">
</html>
{{#js}}
require(['theme_boost/loader'], function() {});
+require(['theme_boost/drawer'], function(mod) {mod.init();});
{{/js}}
Moodle template for the login page.
}}
-<div class="container-fluid login-page">
+<div class="m-y-3 hidden-sm-down"></div>
<div class="row">
- <div class="col-sm-12 col-md-12 col-lg-10 offset-lg-1 col-xl-8 offset-xl-2 login-wrapper">
- <div class="row">
- {{#hasinstructions}}
- <div class="col-sm-6 p-b-1 login-form">
- {{/hasinstructions}}
- {{^hasinstructions}}
- <div class="col-sm-6 offset-sm-3 col-md-4 offset-md-4 p-b-1 login-form">
- {{/hasinstructions}}
-
- <h2 class="m-t-1">{{#str}} login {{/str}}</h2>
-
- {{#cansignup}}
- <div class="sr-only">
- <a href="{{signupurl}}">{{#str}} tocreatenewaccount {{/str}}</a>
- </div>
- {{/cansignup}}
-
- {{#error}}
- <div class="loginerrors m-t-1">
- <a href="#" id="loginerrormessage" class="accesshide">{{error}}</a>
- <div class="alert alert-danger" role="alert">{{error}}</div>
- </div>
- {{/error}}
+<div class="col-xl-6 push-xl-3 m-2-md col-sm-8 push-sm-2">
+<div class="card">
+ {{#logourl}}
+ <img class="card-img-top" src="{{logourl}}" alt="" role="presentation"/>
+ {{/logourl}}
+ <div class="card-block">
+ <div class="card-title">
+ <h2 class="m-t-1">{{sitename}}</h2>
+ </div>
+
+ {{#cansignup}}
+ <div class="sr-only">
+ <a href="{{signupurl}}">{{#str}} tocreatenewaccount {{/str}}</a>
+ </div>
+ {{/cansignup}}
+ {{#error}}
+ <div class="loginerrors m-t-1">
+ <a href="#" id="loginerrormessage" class="accesshide">{{error}}</a>
+ <div class="alert alert-danger" role="alert">{{error}}</div>
+ </div>
+ {{/error}}
+
+ <div class="row">
+ <div class="col-md-4 push-md-1">
<form class="m-t-1" action="{{loginurl}}" method="post" id="login" {{^passwordautocomplete}}autocomplete="off"{{/passwordautocomplete}}>
<input id="anchor" type="hidden" name="anchor" value="">
<script>document.getElementById('anchor').value = location.hash;</script>
{{/rememberusername}}
<button type="submit" class="btn btn-primary btn-block m-t-1" id="loginbtn">{{#str}}login{{/str}}</button>
-
- <div class="forgetpass m-t-1">
- <p><a href="{{forgotpasswordurl}}">{{#str}}forgotten{{/str}}</a></p>
- </div>
-
- <div class="m-t-1">
- {{#str}} cookiesenabled {{/str}}
- {{{cookieshelpiconformatted}}}
- </div>
-
</form>
+ </div>
- {{#canloginasguest}}
- <div class="m-t-2">
- <p>{{#str}}someallowguest{{/str}}</p>
- <form action="{{loginurl}}" method="post" id="guestlogin">
- <input type="hidden" name="username" value="guest" />
- <input type="hidden" name="password" value="guest" />
- <button class="btn btn-secondary btn-block" type="submit">{{#str}}loginguest{{/str}}</button>
- </form>
- </div>
- {{/canloginasguest}}
-
- {{#hasidentityproviders}}
- <h6 class="m-t-2">{{#str}} potentialidps, auth {{/str}}</h6>
- <div class="potentialidplist" class="m-t-1">
- {{#identityproviders}}
- <div class="potentialidp">
- <a href="{{url}}" title={{#quote}}{{name}}{{/quote}}>{{#icon}}{{>core/pix_icon}}{{/icon}}{{name}}</a>
- </div>
- {{/identityproviders}}
- </div>
- {{/hasidentityproviders}}
+ <div class="col-md-4 push-md-3">
+ <div class="forgetpass m-t-1">
+ <p><a href="{{forgotpasswordurl}}">{{#str}}forgotten{{/str}}</a></p>
+ </div>
+ <div class="m-t-1">
+ {{#str}} cookiesenabled {{/str}}
+ {{{cookieshelpiconformatted}}}
+ </div>
+ {{#canloginasguest}}
+ <div class="m-t-2">
+ <p>{{#str}}someallowguest{{/str}}</p>
+ <form action="{{loginurl}}" method="post" id="guestlogin">
+ <input type="hidden" name="username" value="guest" />
+ <input type="hidden" name="password" value="guest" />
+ <button class="btn btn-secondary btn-block" type="submit">{{#str}}loginguest{{/str}}</button>
+ </form>
+ </div>
+ {{/canloginasguest}}
+
+ {{#hasidentityproviders}}
+ <h6 class="m-t-2">{{#str}} potentialidps, auth {{/str}}</h6>
+ <div class="potentialidplist" class="m-t-1">
+ {{#identityproviders}}
+ <div class="potentialidp">
+ <a href="{{url}}" title={{#quote}}{{name}}{{/quote}}>{{#icon}}{{>core/pix_icon}}{{/icon}}{{name}}</a>
+ </div>
+ {{/identityproviders}}
+ </div>
+ {{/hasidentityproviders}}
</div>
+ </div>
+ </div>
+</div>
+</div>
+</div>
- {{#hasinstructions}}
- <div class="col-sm-6 p-b-1 login-instructions">
- <h2 class="m-t-1">{{#str}}firsttime{{/str}}</h2>
- <div>
- {{{instructions}}}
- {{#cansignup}}
- <form class="m-t-1" action="{{signupurl}}" method="get" id="signup">
- <button type="submit" class="btn btn-secondary">{{#str}}startsignup{{/str}}</button>
- </form>
- {{/cansignup}}
- </div>
- </div>
- {{/hasinstructions}}
+{{#hasinstructions}}
+<div class="row">
+<div class="col-xl-6 push-xl-3 m-2-md col-sm-8 push-sm-2">
+<div class="card">
+ <div class="card-block">
+ <div class="card-title">
+ <h2>{{#str}}firsttime{{/str}}</h2>
+ </div>
+ <div>
+ {{{instructions}}}
+ {{#cansignup}}
+ <form class="m-t-1" action="{{signupurl}}" method="get" id="signup">
+ <button type="submit" class="btn btn-secondary">{{#str}}startsignup{{/str}}</button>
+ </form>
+ {{/cansignup}}
</div>
</div>
</div>
</div>
+</div>
+{{/hasinstructions}}
+
{{#js}}
require(['jquery', 'core/yui'], function($, Y) {
<ol class="breadcrumb" role="navigation">
{{#get_items}}
{{#has_action}}
- <li class="breadcrumb-item {{#is_active}}active{{/is_active}}"><a href="{{{action}}}" {{#get_title}}title="{{get_title}}"{{/get_title}}>{{text}}</a></li>
+ <li class="breadcrumb-item"><a href="{{{action}}}" {{#get_title}}title="{{get_title}}"{{/get_title}}>{{text}}</a></li>
{{/has_action}}
{{^has_action}}
- <li class="breadcrumb-item {{#is_active}}active{{/is_active}}">{{text}}</li>
+ <li class="breadcrumb-item">{{text}}</li>
{{/has_action}}
{{/get_items}}
</ol>
--- /dev/null
+<div class="container-fluid">
+ <div class="row">
+ <div class="col-md-8 push-md-2 col-xl-6 push-xl-3">
+ <div class="card">
+ {{#logourl}}
+ <img class="card-img-top" src="{{logourl}}">
+ {{/logourl}}
+ <div class="card-block">
+ <div class="card-title">
+ <h3>{{#str}}newaccount{{/str}}</h3>
+ </div>
+ {{{formhtml}}}
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
--- /dev/null
+<nav class="nav nav-stacked nav-pills">
+{{# flatnavigation }}
+ {{#get_smscreenonly}}
+ <div class="hidden-lg-up">
+ {{/get_smscreenonly}}
+ {{#showdivider}}
+ <div class="nav-item"><hr></div>
+ {{/showdivider}}
+ {{#action}}
+ <div class="nav-item"><a class="nav-link {{#isactive}}active{{/isactive}} m-l-{{get_indent}}" href="{{{action}}}">{{text}}</a></div>
+ {{/action}}
+ {{^action}}
+ <div class="nav-item"><span class="nav-link m-l-{{get_indent}}">{{text}}</span></div>
+ {{/action}}
+ {{#get_smscreenonly}}
+ </div>
+ {{/get_smscreenonly}}
+{{/ flatnavigation }}
+</div>
{{!
Page header.
}}
-<header role="banner" class="navbar navbar-full navbar-light bg-faded navbar-static-top moodle-has-zindex">
+<header role="banner" class="pos-f-t navbar navbar-full navbar-light bg-faded navbar-static-top moodle-has-zindex">
- <div class="container">
+ <div class="container-fluid">
- <button class="navbar-toggler pull-xs-right hidden-sm-up" data-toggle="collapse" data-target="#bd-main-nav" aria-expanded="false" aria-controls="bd-main-nav" type="button">☰<span class="sr-only">{{#str}}expand{{/str}}</span></button>
+ <div data-region="drawer-toggle">
+ <button aria-expanded="{{#navdraweropen}}true{{/navdraweropen}}{{^navdraweropen}}false{{/navdraweropen}}" aria-controls="nav-drawer" type="button" class="btn pull-xs-left m-r-1 btn-secondary" data-action="toggle-drawer" data-side="left" data-preference="drawer-open-nav">☰<span class="sr-only">{{#str}}expand, core{{/str}}</span></button>
+ </div>
<a role="banner" href="{{{ config.wwwroot }}}" class="navbar-brand {{# output.should_display_navbar_logo }}has-logo{{/ output.should_display_navbar_logo }}">
{{# output.should_display_navbar_logo }}
- <div class="logo">
+ <span class="logo hidden-xs-down">
<img src="{{output.get_compact_logo_url}}" alt="{{sitename}}">
- </div>
+ </span>
{{/ output.should_display_navbar_logo }}
- <div class="site-name">{{{ sitename }}}</div>
+ <span class="site-name hidden-sm-down">{{{ sitename }}}</span>
</a>
+ <div data-region="drawer-toggle">
+ <button aria-expanded="{{#blocksdraweropen}}true{{/blocksdraweropen}}{{^blocksdraweropen}}false{{/blocksdraweropen}}" aria-controls="blocks-drawer" type="button" class="pull-xs-right m-l-1 btn btn-secondary" data-side="right" data-preference="drawer-open-blocks" data-action="toggle-drawer">{{#pix}}blocksdrawer, theme_boost{{/pix}}<span class="sr-only">{{#str}}expand, core{{/str}}</span></button>
+ </div>
+
<!-- user_menu -->
{{{ output.user_menu }}}
{{{ output.navbar_plugin_output }}}
<!-- search_box -->
+ <span class="hidden-md-down">
{{{ output.search_box }}}
-
- <div class="collapse navbar-toggleable-xs" id="bd-main-nav">
- <nav class="nav navbar-nav">
- <!-- custom_menu -->
- {{{ output.custom_menu }}}
- <!-- page_heading_menu -->
- {{{ output.page_heading_menu }}}
- </nav>
- </div>
+ </span>
+
+ <nav class="nav navbar-nav hidden-md-down">
+ <!-- custom_menu -->
+ {{{ output.custom_menu }}}
+ <!-- page_heading_menu -->
+ {{{ output.page_heading_menu }}}
+ </nav>
</div>
</header>
--- /dev/null
+{{{ 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">
+ <section id="region-main" class="col-xs-12">
+ {{{ output.course_content_header }}}
+ {{{ output.main_content }}}
+ {{{ output.course_content_footer }}}
+ </section>
+ </div>
+ </div>
+ </div>
+</div>
+<footer id="page-footer" class="p-y-1">
+ <div class="container">
+ <div id="course-footer">{{{ output.course_footer }}}</div>
+
+ {{# output.page_doc_link }}
+ <p class="helplink">{{{ output.page_doc_link }}}</p>
+ {{/ output.page_doc_link }}
+
+ {{{ output.login_info }}}
+ {{{ output.home_link }}}
+ {{{ output.standard_footer_html }}}
+ {{{ output.standard_end_of_body_html }}}
+ </div>
+</footer>
+
+</body>
+</html>
--- /dev/null
+<div id="nav-drawer" data-region="drawer" class="moodle-has-zindex {{^navdraweropen}}closed{{/navdraweropen}}" aria-hidden="{{#navdraweropen}}false{{/navdraweropen}}{{^navdraweropen}}true{{/navdraweropen}}">
+ {{> theme_boost/flat_navigation }}
+</div>
{{{ output.full_header }}}
<div id="page-content" class="row">
- <div id="region-main-box" class="col-md-9">
+ <div id="region-main-box" class="col-xs-12">
<div class="row">
- <section id="region-main" class="col-md-8 push-md-4 col-lg-9 push-lg-3">
+ <section id="region-main" class="col-xs-12">
{{{ output.main_content }}}
</section>
- {{{ sidepreblocks }}}
</div>
</div>
- {{{ sidepostblocks }}}
</div>
{{{ output.standard_end_of_body_html }}}
{{#js}}
require(['theme_boost/loader'], function() {});
{{/js}}
-