MDL-19430 My Moodle: Merged Netspot My Course Overview Block for Moodle 2

This commit is contained in:
Adam Olley
2012-07-19 15:30:37 +08:00
committed by Rajesh Taneja
parent 3294034b80
commit 83ea0cc17e
19 changed files with 984 additions and 70 deletions
+33
View File
@@ -0,0 +1,33 @@
My Course Overview Block for Moodle 2
== Main feautres ==
Provides a user configurable list of the courses a user is enrolled in on their My Moodle page.
The user can set the number of courses to have visible.
Courses can be reordered in editing mode via drag and drop (with appropriate fallback when ajax disabled for the user).
Each course can be expanded to show a list of activity icons alerting the user to updated modules or modules requiring attention.
Optionally can display the shortnames of child courses under the heading of the course (site-wide option).
Optionally can display a welcome area above the courses that welcomes the user and alerts them of any pending messages.
== Installing and configuring ==
Place the code for the block under /blocks/my_course_overview and install the block via the Moodle upgrade process.
== Credits ==
Coding: NetSpot (http://www.netspot.com.au)
Jointly Funded and Designed by:
- Flinders University (http://www.flinders.edu.au)
- University of Canberra (http://www.canberra.edu.au)
== See also ==
[https://github.com/netspotau/moodle-block_my_course_overview Github page]
[[Category: Contributed code]]
@@ -1,5 +1,4 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -18,21 +17,19 @@
/**
* Course overview block
*
* Currently, just a copy-and-paste from the old My Moodle.
*
* @package blocks
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package block
* @subpackage course_overview
* @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot.'/lib/weblib.php');
require_once($CFG->dirroot . '/lib/formslib.php');
require_once($CFG->dirroot.'/blocks/course_overview/locallib.php');
class block_course_overview extends block_base {
/**
* block initializations
*/
public function init() {
$this->title = get_string('pluginname', 'block_course_overview');
$this->title = get_string('displaytitle', 'block_course_overview');
}
/**
@@ -41,82 +38,53 @@ class block_course_overview extends block_base {
* @return object
*/
public function get_content() {
global $USER, $CFG;
global $USER, $CFG, $DB;
require_once($CFG->dirroot.'/user/profile/lib.php');
if($this->content !== NULL) {
return $this->content;
}
$config = get_config('block_course_overview');
$this->content = new stdClass();
$this->content->text = '';
$this->content->footer = '';
$content = array();
// limits the number of courses showing up
$courses_limit = 21;
// FIXME: this should be a block setting, rather than a global setting
if (isset($CFG->mycoursesperpage)) {
$courses_limit = $CFG->mycoursesperpage;
$moving = optional_param('course_moveid', 0, PARAM_INT);
$updatemynumber = optional_param('mynumber', null, PARAM_INT);
if (!is_null($updatemynumber)) {
block_course_overview_update_mynumber($updatemynumber);
}
$morecourses = false;
if ($courses_limit > 0) {
$courses_limit = $courses_limit + 1;
profile_load_custom_fields($USER);
list($courses_sorted, $courses_total) = block_course_overview_get_sorted_courses();
$overviews = block_course_overview_get_overviews($courses_sorted);
$renderer = $this->page->get_renderer('block_course_overview');
if (!isset($config->showwelcomearea) || $config->showwelcomearea) {
$this->content->text = $renderer->welcome_area();
}
$courses = enrol_get_my_courses('id, shortname, modinfo', 'visible DESC,sortorder ASC', $courses_limit);
$site = get_site();
$course = $site; //just in case we need the old global $course hack
if (is_enabled_auth('mnet')) {
$remote_courses = get_my_remotecourses();
}
if (empty($remote_courses)) {
$remote_courses = array();
//number of sites to display
if ($this->page->user_is_editing()) {
$count = count(enrol_get_my_courses('id'));
$this->content->text .= $renderer->editing_bar_head($count);
}
if (($courses_limit > 0) && (count($courses)+count($remote_courses) >= $courses_limit)) {
// get rid of any remote courses that are above the limit
$remote_courses = array_slice($remote_courses, 0, $courses_limit - count($courses), true);
if (count($courses) >= $courses_limit) {
//remove the 'marker' course that we retrieve just to see if we have more than $courses_limit
array_pop($courses);
}
$morecourses = true;
}
if (array_key_exists($site->id,$courses)) {
unset($courses[$site->id]);
}
foreach ($courses as $c) {
if (isset($USER->lastcourseaccess[$c->id])) {
$courses[$c->id]->lastaccess = $USER->lastcourseaccess[$c->id];
} else {
$courses[$c->id]->lastaccess = 0;
}
}
if (empty($courses) && empty($remote_courses)) {
$content[] = get_string('nocourses','my');
if (empty($courses_sorted)) {
$this->content->text .= get_string('nocourses','my');
} else {
ob_start();
require_once $CFG->dirroot."/course/lib.php";
print_overview($courses, $remote_courses);
$content[] = ob_get_contents();
ob_end_clean();
//for each course, build category cache
$this->content->text .= $renderer->course_overview($courses_sorted, $overviews, $moving);
$this->content->text .= $renderer->hidden_courses($courses_total - count($courses_sorted));
if ($this->page->user_is_editing() && ajaxenabled() && !$moving) {
$this->page->requires->js_init_call('M.block_course_overview.add_handles');
}
}
// if more than 20 courses
if ($morecourses) {
$content[] = '<br />...';
}
$this->content->text = implode($content);
return $this->content;
}
@@ -126,7 +94,7 @@ class block_course_overview extends block_base {
* @return boolean
*/
public function has_config() {
return false;
return true;
}
/**
@@ -135,7 +103,15 @@ class block_course_overview extends block_base {
* @return array
*/
public function applicable_formats() {
return array('my-index'=>true);
return array('my-index' => true);
}
public function instance_can_be_hidden() {
return false;
}
public function hide_header() {
return true;
}
}
?>
+28
View File
@@ -0,0 +1,28 @@
<?php
function xmldb_block_course_overview_install() {
global $DB;
//setup user info fields
if (!$DB->get_record('user_info_field', array('shortname' => 'mynumber'))) {
$field = new stdClass();
$field->shortname = 'mynumber';
$field->name = 'Number of courses on My Moodle';
$field->datatype = 'text';
$field->visible = 1;
$field->categoryid = 1;
$DB->insert_record('user_info_field', $field);
}
if (!$DB->get_record('user_info_field', array('shortname' => 'myorder'))) {
$field = new stdClass();
$field->shortname = 'myorder';
$field->name = 'Order of courses on My Moodle';
$field->datatype = 'text';
$field->visible = 0;
$field->categoryid = 1;
$DB->insert_record('user_info_field', $field);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
function xmldb_block_course_overview_upgrade($oldversion) {
global $DB;
if ($oldversion < 2012062800) {
//setup user info fields
if (!$DB->get_record('user_info_field', array('shortname' => 'mynumber'))) {
$field = new stdClass();
$field->shortname = 'mynumber';
$field->name = 'Number of courses on My Moodle';
$field->datatype = 'text';
$field->visible = 1;
$field->categoryid = 1;
$DB->insert_record('user_info_field', $field);
}
if (!$DB->get_record('user_info_field', array('shortname' => 'myorder'))) {
$field = new stdClass();
$field->shortname = 'myorder';
$field->name = 'Order of courses on My Moodle';
$field->datatype = 'text';
$field->visible = 0;
$field->categoryid = 1;
$DB->insert_record('user_info_field', $field);
}
upgrade_block_savepoint(true, 2012062800, 'course_overview');
}
return true;
}
@@ -1,2 +1,28 @@
<?php
$string['pluginname'] = 'Course overview';
$string['activity_assignment'] = 'You have assignments that need attention';
$string['activity_forum'] = 'There are new forum posts';
$string['activity_quiz'] = 'You have quizzes that are due';
$string['activityoverview'] = 'You have {$a}s that need attention';
$string['alwaysshowall'] = 'Always Show All';
$string['collapseall'] = 'Collapse All Course Lists';
$string['configotherexpanded'] = 'If enabled, Other Courses will be expanded by default unless overriden by user preferences.';
$string['configpreservestates'] = 'If enabled, the collapsed/expanded states set by the user are stored and used on each load.';
$string['displaytitle'] = 'learnonline: My Home';
$string['expandall'] = 'Expand All Course Lists';
$string['hiddencoursecount'] = 'You have {$a} hidden course';
$string['hiddencoursecountplural'] = 'You have {$a} hidden courses';
$string['movecoursehere'] = 'Move course here';
$string['numtodisplay'] = 'Number of courses to display: ';
$string['otherexpanded'] = 'Other Courses Expanded';
$string['preservestates'] = 'Preserve Expanded States';
$string['message'] = 'message';
$string['messages'] = 'messages';
$string['showchildren'] = 'Show Children';
$string['showchildren_desc'] = 'Should child courses be listed underneath the main course title?';
$string['showwelcomearea'] = 'Show welcome area';
$string['showwelcomearea_desc'] = 'Show the welcome area above the course list?';
$string['view_edit_profile'] = '(View and edit your profile.)';
$string['welcome'] = 'Welcome {$a}';
$string['you_have_messages'] = 'You have {$a} unread ';
$string['you_have_no_messages'] = 'You have no unread ';
+167
View File
@@ -0,0 +1,167 @@
<?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/>.
function block_course_overview_get_overviews($courses) {
global $CFG, $USER, $DB, $OUTPUT;
$htmlarray = array();
if ($modules = $DB->get_records('modules')) {
foreach ($modules as $mod) {
if (file_exists(dirname(__FILE__).'/../../mod/'.$mod->name.'/lib.php')) {
include_once(dirname(__FILE__).'/../../mod/'.$mod->name.'/lib.php');
$fname = $mod->name.'_print_overview';
if (function_exists($fname)) {
$fname($courses,$htmlarray);
}
}
}
}
return $htmlarray;
}
function block_course_overview_update_mynumber($number) {
global $DB, $USER;
if ($field = $DB->get_record('user_info_field', array('shortname' => 'mynumber'))) {
if ($data = $DB->get_record('user_info_data', array('fieldid' => $field->id, 'userid' => $USER->id))) {
$data->data = $number;
$DB->update_record('user_info_data', $data);
} else {
$data = new stdClass();
$data->fieldid = $field->id;
$data->userid = $USER->id;
$data->data = $number;
$DB->insert_record('user_info_data', $data);
}
}
}
function block_course_overview_update_myorder($sortorder) {
global $DB, $USER;
if ($field = $DB->get_record('user_info_field', array('shortname' => 'myorder'))) {
if ($data = $DB->get_record('user_info_data', array('fieldid' => $field->id, 'userid' => $USER->id))) {
$oldlist = explode(',', $data->data);
$newlist = explode(',', $sortorder);
foreach ($oldlist as $oldentry) {
if (!in_array($oldentry, $newlist)) {
$newlist[] = $oldentry;
}
}
$sortorder = implode(',', $newlist);
$data->data = $sortorder;
$DB->update_record('user_info_data', $data);
} else {
$data = new stdClass();
$data->fieldid = $field->id;
$data->userid = $USER->id;
$data->data = $sortorder;
$DB->insert_record('user_info_data', $data);
}
}
}
function block_course_overview_get_child_shortnames($courseid) {
global $COURSE, $DB, $OUTPUT;
$sql = "SELECT c.shortname
FROM {enrol} AS e
JOIN {course} AS c ON (c.id = e.customint1)
WHERE e.courseid = :courseid AND e.enrol = :method ORDER BY e.sortorder";
$params = array('method' => 'meta', 'courseid' => $courseid);
if ($results = $DB->get_records_sql($sql, $params)) {
$shortnames = array();
foreach ($results as $res) {
$shortnames[] = $res->shortname;
}
$total = count($shortnames);
$suffix = '';
if ($total > 10) {
$shortnames = array_slice($shortnames, 0, 10);
$diff = $total - count($shortnames);
$plural = $diff > 1 ? 's' : '';
$suffix = " (and $diff other$plural)";
}
$shortnames = 'includes '.implode('; ', $shortnames).$suffix;
}
return isset($shortnames) ? $shortnames : false;
}
function block_course_overview_get_sorted_courses() {
global $USER;
$limit = 71; //TODO: Make this a block setting
if (isset($USER->profile['mynumber']) && intval($USER->profile['mynumber']) > 0) {
$limit = intval($USER->profile['mynumber']);
} else {
$USER->profile['mynumber'] = 0;
}
$courses = enrol_get_my_courses('id, shortname, fullname, modinfo');
$site = get_site();
if (array_key_exists($site->id,$courses)) {
unset($courses[$site->id]);
}
foreach ($courses as $c) {
if (isset($USER->lastcourseaccess[$c->id])) {
$courses[$c->id]->lastaccess = $USER->lastcourseaccess[$c->id];
} else {
$courses[$c->id]->lastaccess = 0;
}
}
$order = array();
if (isset($USER->profile['myorder'])) {
$order = explode(',', $USER->profile['myorder']);
}
$courses_sorted = array();
//unsorted courses top of the list
foreach ($courses as $c) {
if (count($courses_sorted) >= $limit) {
break;
}
if (!in_array($c->id, $order)) {
$courses_sorted[$c->id] = $c;
}
}
//get courses in sort order into list
foreach ($order as $o) {
if (count($courses_sorted) >= $limit) {
break;
}
if (isset($courses[intval($o)])) {
$courses_sorted[$o] = $courses[$o];
}
}
//append the remaining courses onto the end of the list
foreach ($courses as $c) {
if (count($courses_sorted) >= $limit) {
break;
}
if (!isset($courses_sorted[$c->id])) {
$courses_sorted[$c->id] = $c;
}
}
return array($courses_sorted, count($courses));
}
+226
View File
@@ -0,0 +1,226 @@
M.block_course_overview = {}
M.block_course_overview.add_handles = function(Y) {
M.block_course_overview.Y = Y;
YUI().use('dd-constrain', 'dd-proxy', 'dd-drop', 'dd-plugin', function(Y) {
//Static Vars
var goingUp = false, lastY = 0;
var list = Y.Node.all('#course_list .coursebox');
list.each(function(v, k) {
var dd = new Y.DD.Drag({
node: v,
target: {
padding: '0 0 0 20'
}
}).plug(Y.Plugin.DDProxy, {
moveOnEnd: false
}).plug(Y.Plugin.DDConstrained, {
constrain2node: '#course_list'
});
dd.addHandle('.course_title .move');
});
var drops = Y.Node.all('#coursebox');
drops.each(function(v, k) {
var tar = new Y.DD.Drop({
node: v
});
});
Y.DD.DDM.on('drag:start', function(e) {
//Get our drag object
var drag = e.target;
//Set some styles here
drag.get('node').setStyle('opacity', '.25');
drag.get('dragNode').addClass('block_course_overview');
drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
drag.get('dragNode').setStyles({
opacity: '.5',
borderColor: drag.get('node').getStyle('borderColor'),
backgroundColor: drag.get('node').getStyle('backgroundColor')
});
});
Y.DD.DDM.on('drag:end', function(e) {
var drag = e.target;
//Put our styles back
drag.get('node').setStyles({
visibility: '',
opacity: '1'
});
M.block_course_overview.save(Y);
});
Y.DD.DDM.on('drag:drag', function(e) {
//Get the last y point
var y = e.target.lastXY[1];
//is it greater than the lastY var?
if (y < lastY) {
//We are going up
goingUp = true;
} else {
//We are going down.
goingUp = false;
}
//Cache for next check
lastY = y;
});
Y.DD.DDM.on('drop:over', function(e) {
//Get a reference to our drag and drop nodes
var drag = e.drag.get('node'),
drop = e.drop.get('node');
//Are we dropping on a li node?
if (drop.hasClass('coursebox')) {
//Are we not going up?
if (!goingUp) {
drop = drop.get('nextSibling');
}
//Add the node to this list
e.drop.get('node').get('parentNode').insertBefore(drag, drop);
//Resize this nodes shim, so we can drop on it later.
e.drop.sizeShim();
}
});
Y.DD.DDM.on('drag:drophit', function(e) {
var drop = e.drop.get('node'),
drag = e.drag.get('node');
//if we are not on an li, we must have been dropped on a ul
if (!drop.hasClass('coursebox')) {
if (!drop.contains(drag)) {
drop.appendChild(drag);
}
}
});
});
}
M.block_course_overview.save = function() {
var Y = M.block_course_overview.Y;
var sortorder = Y.one('#course_list').get('children').getAttribute('id');
for (var i = 0; i < sortorder.length; i++) {
sortorder[i] = sortorder[i].substring(7);
}
var params = {
sesskey : M.cfg.sesskey,
sortorder : sortorder
};
Y.io(M.cfg.wwwroot+'/blocks/course_overview/save.php', {
method: 'POST',
data: build_querystring(params),
context: this
});
}
/**
* Init a collapsible region, see print_collapsible_region in weblib.php
* @param {YUI} Y YUI3 instance with all libraries loaded
* @param {String} id the HTML id for the div.
* @param {String} userpref the user preference that records the state of this box. false if none.
* @param {String} strtooltip
*/
M.block_course_overview.collapsible = function(Y, id, userpref, strtooltip) {
if (userpref) {
M.block_course_overview.userpref = true;
}
Y.use('anim', function(Y) {
new M.block_course_overview.CollapsibleRegion(Y, id, userpref, strtooltip);
});
};
/**
* Object to handle a collapsible region : instantiate and forget styled object
*
* @class
* @constructor
* @param {YUI} Y YUI3 instance with all libraries loaded
* @param {String} id The HTML id for the div.
* @param {String} userpref The user preference that records the state of this box. false if none.
* @param {String} strtooltip
*/
M.block_course_overview.CollapsibleRegion = function(Y, id, userpref, strtooltip) {
// Record the pref name
this.userpref = userpref;
// Find the divs in the document.
this.div = Y.one('#'+id);
// Get the caption for the collapsible region
var caption = this.div.one('#'+id + '_caption');
caption.setAttribute('title', strtooltip);
// Create a link
var a = Y.Node.create('<a href="#"></a>');
// Create a local scoped lamba function to move nodes to a new link
var movenode = function(node){
node.remove();
a.append(node);
};
// Apply the lamba function on each of the captions child nodes
caption.get('children').each(movenode, this);
caption.prepend(a);
// Get the height of the div at this point before we shrink it if required
var height = this.div.get('offsetHeight');
if (this.div.hasClass('collapsed')) {
// Shrink the div as it is collapsed by default
this.div.setStyle('height', caption.get('offsetHeight')+'px');
}
// Create the animation.
var animation = new Y.Anim({
node: this.div,
duration: 0.3,
easing: Y.Easing.easeBoth,
to: {height:caption.get('offsetHeight')},
from: {height:height}
});
// Handler for the animation finishing.
animation.on('end', function() {
this.div.toggleClass('collapsed');
}, this);
// Hook up the event handler.
caption.on('click', function(e, animation) {
e.preventDefault();
// Animate to the appropriate size.
if (animation.get('running')) {
animation.stop();
}
animation.set('reverse', this.div.hasClass('collapsed'));
// Update the user preference.
if (this.userpref) {
M.util.set_user_preference(this.userpref, !this.div.hasClass('collapsed'));
}
animation.run();
}, this, animation);
};
M.block_course_overview.userpref = false;
/**
* The user preference that stores the state of this box.
* @property userpref
* @type String
*/
M.block_course_overview.CollapsibleRegion.prototype.userpref = null;
/**
* The key divs that make up this
* @property div
* @type Y.Node
*/
M.block_course_overview.CollapsibleRegion.prototype.div = null;
/**
* The key divs that make up this
* @property icon
* @type Y.Node
*/
M.block_course_overview.CollapsibleRegion.prototype.icon = null;
+58
View File
@@ -0,0 +1,58 @@
<?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/>.
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->dirroot.'/user/profile/lib.php');
require_login();
$source = required_param('source', PARAM_INT);
$target = required_param('target', PARAM_INT);
profile_load_custom_fields($USER);
//get current sortorder
$sortorder = array();
if (isset($USER->profile['myorder'])) {
$mysortorder = explode(',', $USER->profile['myorder']);
}
$courses_sorted = block_course_overview_get_sorted_courses();
$sortorder = array_keys($courses_sorted);
//now resort based on new weight for chosen course
$neworder = array();
reset($sortorder);
foreach ($sortorder as $key => $value) {
if ($value == $source) {
unset($sortorder[$key]);
break;
}
}
for ($i = 0; $i <= count($sortorder) + 1; $i++) {
if ($i == $target) {
$neworder[] = $source;
}
if (isset($sortorder[$i])) {
$neworder[] = $sortorder[$i];
}
}
$neworder = implode(',', $neworder);
block_course_overview_update_myorder($neworder);
redirect(new moodle_url('/my/index.php'));
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

+240
View File
@@ -0,0 +1,240 @@
<?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;
require_once($CFG->dirroot.'/message/lib.php');
class block_course_overview_renderer extends plugin_renderer_base {
public function course_overview($courses, $overviews, $moving = 0) {
global $OUTPUT;
$html = '';
$config = get_config('block_course_overview');
$html .= html_writer::start_tag('div', array('id' => 'course_list'));
$weight = 0;
$keylist = array_keys($courses);
if ($this->page->user_is_editing() && $moving && $keylist[0] != $moving) {
$html .= $this->course_move_target($moving, $weight);
$weight++;
}
foreach ($courses as $course) {
$cursor = ajaxenabled() && !$moving ? ' cursor' : '';
$html .= $OUTPUT->box_start('coursebox', "course-{$course->id}");
$html .= html_writer::start_tag('div', array('class' => 'course_title'));
if ($this->page->user_is_editing()) {
// Move icon.
$icon = ajaxenabled() ? 'i/move_2d' : 't/move';
$control = array('url' => new moodle_url('/my/index.php', array('course_moveid' => $course->id)),
'icon' => $icon, 'caption' => get_string('move'));
if (ajaxenabled()) {
$html .= html_writer::tag('div',
html_writer::empty_tag('img',
array('src' => $this->pix_url($control['icon'])->out(false),
'alt' => $control['caption'], 'class' => 'icon cursor',
'title' => $control['caption'])
), array('class' => 'move')
);
} else {
$html .= html_writer::tag('a',
html_writer::empty_tag('img', array('src' => $this->pix_url($control['icon'])->out(false), 'alt' => $control['caption'])),
array('class' => 'icon move','title' => $control['caption'], 'href' => $control['url']));
}
}
$link = html_writer::link(new moodle_url('/course/view.php', array('id' => $course->id)), $course->fullname);
$html .= $OUTPUT->heading($link, 2, 'title');
$html .= $OUTPUT->box('', 'flush');
$html .= html_writer::end_tag('div');
if (isset($config->showchildren) && $config->showchildren) {
//list children here
if ($children = block_course_overview_get_child_shortnames($course->id)) {
$html .= html_writer::tag('span', $children, array('class' => 'coursechildren'));
}
}
if (isset($overviews[$course->id])) {
$html .= $this->activity_display($course->id, $overviews[$course->id]);
}
$html .= $OUTPUT->box('', 'flush');
$html .= $OUTPUT->box_end();
if ($this->page->user_is_editing() && $moving && $course->id != $moving) {
//check if next is the course we're moving
$okay = true;
if (isset($keylist[$weight])) {
if ($courses[$keylist[$weight]]->id == $moving) {
$okay = false;
}
}
if ($okay) {
$html .= $this->course_move_target($moving, $weight);
}
}
$weight++;
}
$html .= html_writer::end_tag('div');
return $html;
}
protected function course_move_target($cid, $weight) {
$url = new moodle_url('/blocks/course_overview/move.php', array('source' => $cid, 'target' => $weight));
return html_writer::tag('a', html_writer::tag('span', get_string('movecoursehere', 'block_course_overview'),
array('class' => 'accesshide')), array('href' => $url, 'class' => 'coursemovetarget'));
}
protected function activity_display($cid, $overview) {
global $OUTPUT;
$output = html_writer::start_tag('div', array('class' => 'activity_info'));
foreach (array_keys($overview) as $module) {
$output .= html_writer::start_tag('div', array('class' => 'activity_overview'));
$url = new moodle_url("/mod/$module/index.php", array('id' => $cid));
$icontext = html_writer::link($url, $OUTPUT->pix_icon('icon', get_string('modulename', $module), 'mod_'.$module, array('class'=>'icon')).' ');
if (get_string_manager()->string_exists("activity_$module", 'block_course_overview')) {
$icontext .= get_string("activity_$module", 'block_course_overview');
} else {
$icontext .= get_string("activityoverview", 'block_course_overview', $module);
}
//add collapsible region with overview text in it
$output .= $this->collapsible_region($overview[$module], '', 'region_'.$cid.'_'.$module, $icontext, '', true);
$output .= html_writer::end_tag('div');
}
$output .= html_writer::end_tag('div');
return $output;
}
public function editing_bar_head($max = 0) {
global $OUTPUT, $USER;
$output = $OUTPUT->box_start('notice');
$options = array('0' => get_string('alwaysshowall', 'block_course_overview'));
for ($i = 1; $i <= $max; $i++) {
$options[$i] = $i;
}
$url = new moodle_url('/my/index.php');
$select = new single_select($url, 'mynumber', $options, $USER->profile['mynumber'], array());
$select->set_label(get_string('numtodisplay', 'block_course_overview'));
$output .= $OUTPUT->render($select);
$output .= $OUTPUT->box_end();
return $output;
}
public function hidden_courses($total) {
global $OUTPUT;
if ($total <= 0) {
return;
}
$output = $OUTPUT->box_start('notice');
$plural = $total > 1 ? 'plural' : '';
$output .= get_string('hiddencoursecount'.$plural, 'block_course_overview', $total);
$output .= $OUTPUT->box_end();
return $output;
}
protected function collapsible_region($contents, $classes, $id, $caption, $userpref = '', $default = false) {
$output = $this->collapsible_region_start($classes, $id, $caption, $userpref, $default);
$output .= $contents;
$output .= $this->collapsible_region_end();
return $output;
}
/**
* Print (or return) the start of a collapsible region, that has a caption that can
* be clicked to expand or collapse the region. If JavaScript is off, then the region
* will always be expanded.
*
* @param string $classes class names added to the div that is output.
* @param string $id id added to the div that is output. Must not be blank.
* @param string $caption text displayed at the top. Clicking on this will cause the region to expand or contract.
* @param string $userpref the name of the user preference that stores the user's preferred default state.
* (May be blank if you do not wish the state to be persisted.
* @param boolean $default Initial collapsed state to use if the user_preference it not set.
* @param boolean $return if true, return the HTML as a string, rather than printing it.
*/
protected function collapsible_region_start($classes, $id, $caption, $userpref = '', $default = false) {
global $CFG, $PAGE, $OUTPUT;
// Work out the initial state.
if (!empty($userpref) and is_string($userpref)) {
user_preference_allow_ajax_update($userpref, PARAM_BOOL);
$collapsed = get_user_preferences($userpref, $default);
} else {
$collapsed = $default;
$userpref = false;
}
if ($collapsed) {
$classes .= ' collapsed';
}
$output = '';
$output .= '<div id="' . $id . '" class="collapsibleregion ' . $classes . '">';
$output .= '<div id="' . $id . '_sizer">';
$output .= '<div id="' . $id . '_caption" class="collapsibleregioncaption">';
$output .= $caption . ' ';
$output .= '</div><div id="' . $id . '_inner" class="collapsibleregioninner">';
$this->page->requires->js_init_call('M.block_course_overview.collapsible', array($id, $userpref, get_string('clicktohideshow')));
return $output;
}
/**
* Close a region started with print_collapsible_region_start.
*
* @param boolean $return if true, return the HTML as a string, rather than printing it.
*/
protected function collapsible_region_end() {
$output = '</div></div></div>';
return $output;
}
public function welcome_area() {
global $OUTPUT, $USER;
$output = $OUTPUT->box_start('welcome_area');
$picture = $OUTPUT->user_picture($USER, array('size' => 75, 'class' => 'welcome_userpicture'));
$output .= html_writer::tag('div', $picture, array('class' => 'profilepicture'));
$output .= $OUTPUT->box_start('welcome_message');
$output .= $OUTPUT->heading(get_string('welcome', 'block_course_overview', $USER->firstname));
//messages
$count = message_count_unread_messages($USER);
$plural = 's';
if ($count > 0) {
$output .= get_string('you_have_messages', 'block_course_overview', $count);
} else {
$output .= get_string('you_have_no_messages', 'block_course_overview');
if ($count == 1) {
$plural = '';
}
}
$output .= html_writer::link(new moodle_url('/message/index.php'), get_string('message'.$plural, 'block_course_overview'));
$output .= $OUTPUT->box_end();
$output .= $OUTPUT->box('', 'flush');
$output .= $OUTPUT->box_end();
return $output;
}
}
+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/>.
define('AJAX_SCRIPT', true);
/** Include config */
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
if (!confirm_sesskey()) {
throw new moodle_exception('invalidsesskey', 'error');
}
$sortorder = required_param('sortorder', PARAM_INT);
$sortorder = implode(',', $sortorder);
block_course_overview_update_myorder($sortorder);
+16
View File
@@ -0,0 +1,16 @@
<?php
defined('MOODLE_INTERNAL') || die;
if ($ADMIN->fulltree) {
$configs = array();
$configs[] = new admin_setting_configcheckbox('showchildren', get_string('showchildren', 'block_course_overview'),
get_string('showchildren_desc', 'block_course_overview'), '');
$configs[] = new admin_setting_configcheckbox('showwelcomearea', get_string('showwelcomearea', 'block_course_overview'),
get_string('showwelcomearea_desc', 'block_course_overview'), 1);
foreach ($configs as $config) {
$config->plugin = 'block_course_overview';
$settings->add($config);
}
}
+83
View File
@@ -0,0 +1,83 @@
.pagelayout-mydashboard #region-main .region-content .block_course_overview .header,
.pagelayout-mydashboard #region-main .region-content .block_course_overview .block_action,
.pagelayout-mydashboard #region-main .region-content .block_course_overview .commands {
display: none;
}
.block_course_overview .coursechildren {
font-size: 12px;
font-weight: normal;
font-style: italic;
}
.block_course_overview .content {
margin-left: 20px;
}
.block_course_overview .profilepicture {
float: left;
}
.block_course_overview .welcome_area {
width: 100%;
padding-bottom: 5px;
}
.block_course_overview .welcome_message {
float: left;
padding: 10px;
vertical-align: middle;
border-collapse: separate;
clear: none;
}
.block_course_overview h2.title {
float: left;
font-size: 1.5em !important;
margin-bottom: 0;
margin-top: 0;
position: relative;
}
.block_course_overview .course_title {
position: relative;
}
.editing .block_course_overview h2.title {
left: 20px;
}
.editing .block_course_overview .coursebox .cursor {
cursor: move;
margin-bottom: 2px;
}
.editing .block_course_overview .move {
float: left;
position: absolute;
width: 20px;
}
.block_course_overview #course_list {
width: 100%;
}
.block_course_overview div.flush {
clear: both;
}
.block_course_overview .activity_info {
clear: both;
}
.block_course_overview .activity_overview {
padding: 2px;
}
.block_course_overview .singleselect {
text-align: left;
margin: 0;
}
.block_course_overview .coursemovetarget {display: block;height: 1em;margin-bottom: 1em;border-width: 2px;border-style: dashed;}
+2 -2
View File
@@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2012061700; // The current plugin version (Date: YYYYMMDDXX)
$plugin->version = 2012062800; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2012061700; // Requires this Moodle version
$plugin->component = 'block_course_overview'; // Full name of the plugin (used for diagnostics)
$plugin->component = 'block_course_overview'; // Full name of the plugin (used for diagnostics)