MDL-63063 recentlyaccesseditems: fully contained block
authorVíctor Déniz Falcón <victor@moodle.com>
Wed, 31 Oct 2018 11:53:02 +0000 (11:53 +0000)
committerVíctor Déniz Falcón <victor@moodle.com>
Wed, 31 Oct 2018 11:53:02 +0000 (11:53 +0000)
33 files changed:
blocks/recentlyaccesseditems/amd/build/main.min.js [new file with mode: 0644]
blocks/recentlyaccesseditems/amd/build/repository.min.js [new file with mode: 0644]
blocks/recentlyaccesseditems/amd/src/main.js [new file with mode: 0644]
blocks/recentlyaccesseditems/amd/src/repository.js [new file with mode: 0644]
blocks/recentlyaccesseditems/block_recentlyaccesseditems.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/external.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/external/recentlyaccesseditems_item_exporter.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/helper.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/observer.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/output/main.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/output/renderer.php [new file with mode: 0644]
blocks/recentlyaccesseditems/classes/privacy/provider.php [new file with mode: 0644]
blocks/recentlyaccesseditems/db/access.php [new file with mode: 0644]
blocks/recentlyaccesseditems/db/events.php [new file with mode: 0644]
blocks/recentlyaccesseditems/db/install.xml [new file with mode: 0644]
blocks/recentlyaccesseditems/db/services.php [new file with mode: 0644]
blocks/recentlyaccesseditems/lang/en/block_recentlyaccesseditems.php [new file with mode: 0644]
blocks/recentlyaccesseditems/pix/items.svg [new file with mode: 0644]
blocks/recentlyaccesseditems/templates/main.mustache [new file with mode: 0644]
blocks/recentlyaccesseditems/templates/no-items.mustache [new file with mode: 0644]
blocks/recentlyaccesseditems/templates/placeholder-item.mustache [new file with mode: 0644]
blocks/recentlyaccesseditems/templates/recentlyaccesseditems-view.mustache [new file with mode: 0644]
blocks/recentlyaccesseditems/templates/view-cards.mustache [new file with mode: 0644]
blocks/recentlyaccesseditems/tests/behat/block_recentlyaccesseditems_dashboard.feature [new file with mode: 0644]
blocks/recentlyaccesseditems/tests/externallib_test.php [new file with mode: 0644]
blocks/recentlyaccesseditems/tests/observer_test.php [new file with mode: 0644]
blocks/recentlyaccesseditems/version.php [new file with mode: 0644]
lib/classes/plugin_manager.php
theme/boost/scss/moodle/blocks.scss
theme/boost/style/moodle.css
theme/bootstrapbase/less/moodle/blocks.less
theme/bootstrapbase/style/moodle.css
version.php

diff --git a/blocks/recentlyaccesseditems/amd/build/main.min.js b/blocks/recentlyaccesseditems/amd/build/main.min.js
new file mode 100644 (file)
index 0000000..d4daa0f
Binary files /dev/null and b/blocks/recentlyaccesseditems/amd/build/main.min.js differ
diff --git a/blocks/recentlyaccesseditems/amd/build/repository.min.js b/blocks/recentlyaccesseditems/amd/build/repository.min.js
new file mode 100644 (file)
index 0000000..fa504bb
Binary files /dev/null and b/blocks/recentlyaccesseditems/amd/build/repository.min.js differ
diff --git a/blocks/recentlyaccesseditems/amd/src/main.js b/blocks/recentlyaccesseditems/amd/src/main.js
new file mode 100644 (file)
index 0000000..5d4fd16
--- /dev/null
@@ -0,0 +1,105 @@
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Javascript to initialise the Recently accessed items block.
+ *
+ * @module     block_recentlyaccesseditems/main
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define(
+    [
+        'jquery',
+        'block_recentlyaccesseditems/repository',
+        'core/templates',
+        'core/notification'
+    ],
+    function(
+        $,
+        Repository,
+        Templates,
+        Notification
+    ) {
+
+        var NUM_ITEMS = 9;
+
+        var SELECTORS = {
+            CARDDECK_CONTAINER: '[data-region="recentlyaccesseditems-view"]',
+            CARDDECK: '[data-region="recentlyaccesseditems-view-content"]',
+        };
+
+        /**
+         * Get recent items from backend.
+         *
+         * @method getRecentItems
+         * @param {int} limit Only return this many results
+         * @return {array} Items user most recently has accessed
+         */
+        var getRecentItems = function(limit) {
+            return Repository.getRecentItems(limit);
+        };
+
+        /**
+         * Render the block content.
+         *
+         * @method renderItems
+         * @param {object} root The root element for the items view.
+         * @param {array} items containing array of returned items.
+         * @return {promise} Resolved with HTML and JS strings
+         */
+        var renderItems = function(root, items) {
+            if (items.length > 0) {
+                return Templates.render('block_recentlyaccesseditems/view-cards', {
+                    items: items
+                });
+            } else {
+                var noitemsimgurl = root.attr('data-noitemsimgurl');
+                return Templates.render('block_recentlyaccesseditems/no-items', {
+                    noitemsimgurl: noitemsimgurl
+                });
+            }
+        };
+
+        /**
+         * Get and show the recent items into the block.
+         *
+         * @param {object} root The root element for the items block.
+         */
+        var init = function(root) {
+            root = $(root);
+
+            var itemsContainer = root.find(SELECTORS.CARDDECK_CONTAINER);
+            var itemsContent = root.find(SELECTORS.CARDDECK);
+
+            var itemsPromise = getRecentItems(NUM_ITEMS);
+
+            itemsPromise.then(function(items) {
+                var pageContentPromise = renderItems(itemsContainer, items);
+
+                pageContentPromise.then(function(html, js) {
+                    return Templates.replaceNodeContents(itemsContent, html, js);
+                }).catch(Notification.exception);
+                return itemsPromise;
+            }).catch(Notification.exception);
+        };
+
+        return {
+            init: init
+        };
+    });
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/amd/src/repository.js b/blocks/recentlyaccesseditems/amd/src/repository.js
new file mode 100644 (file)
index 0000000..cd76802
--- /dev/null
@@ -0,0 +1,47 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * A javascript module to handle user ajax actions.
+ *
+ * @module     block_recentlyaccesseditems/repository
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['core/ajax'], function(Ajax) {
+
+    /**
+     * Get the list of items that the user has most recently accessed.
+     *
+     * @method getRecentItems
+     * @param {int} limit Only return this many results
+     * @return {promise} Resolved with an array of items
+     */
+    var getRecentItems = function(limit) {
+        var args = {};
+        if (typeof limit !== 'undefined') {
+            args.limit = limit;
+        }
+        var request = {
+            methodname: 'block_recentlyaccesseditems_get_recent_items',
+            args: args
+        };
+        return Ajax.call([request])[0];
+    };
+    return {
+        getRecentItems: getRecentItems
+    };
+});
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/block_recentlyaccesseditems.php b/blocks/recentlyaccesseditems/block_recentlyaccesseditems.php
new file mode 100644 (file)
index 0000000..d16c303
--- /dev/null
@@ -0,0 +1,65 @@
+<?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/>.
+/**
+ * Class definition for the Recently accessed items block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+/**
+ * Recently accessed items block class.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class block_recentlyaccesseditems extends block_base {
+    /**
+     * Initialize class member variables
+     */
+    public function init() {
+        $this->title = get_string('pluginname', 'block_recentlyaccesseditems');
+    }
+
+    /**
+     * Returns the contents.
+     *
+     * @return stdClass contents of block
+     */
+    public function get_content() {
+        if (isset($this->content)) {
+            return $this->content;
+        }
+        $renderable = new block_recentlyaccesseditems\output\main();
+        $renderer = $this->page->get_renderer('block_recentlyaccesseditems');
+
+        $this->content = new stdClass();
+        $this->content->text = $renderer->render($renderable);
+        $this->content->footer = '';
+        return $this->content;
+    }
+
+    /**
+     * Locations where block can be displayed.
+     *
+     * @return array
+     */
+    public function applicable_formats() {
+        return array('my' => true);
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/external.php b/blocks/recentlyaccesseditems/classes/external.php
new file mode 100644 (file)
index 0000000..dfeae51
--- /dev/null
@@ -0,0 +1,106 @@
+<?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/>.
+
+/**
+ * External API.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace block_recentlyaccesseditems;
+defined('MOODLE_INTERNAL') || die();
+
+require_once("$CFG->libdir/externallib.php");
+
+use block_recentlyaccesseditems\external\recentlyaccesseditems_item_exporter;
+use external_api;
+use external_function_parameters;
+use external_value;
+use external_multiple_structure;
+use context_user;
+use context_module;
+
+/**
+ * External API class.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class external extends external_api {
+
+    /**
+     * Returns description of method parameters
+     * @return external_function_parameters
+     */
+    public static function get_recent_items_parameters() {
+        return new external_function_parameters(
+                array(
+                        'limit' => new external_value(PARAM_INT, 'result set limit', VALUE_DEFAULT, 0)
+                )
+        );
+    }
+
+    /**
+     * Get last accessed items by the logged user (activities or resources).
+     *
+     * @param  int $limit Max num of items to return
+     * @return array List of items
+     * @since Moodle 3.6
+     */
+    public static function get_recent_items(int $limit = 0) {
+        global $USER, $PAGE;
+
+        $userid = $USER->id;
+
+        if ($userid != $USER->id) {
+            return array();
+        }
+
+        $params = self::validate_parameters(self::get_recent_items_parameters(),
+            array(
+                'limit' => $limit,
+            )
+        );
+
+        $limit = $params['limit'];
+
+        self::validate_context(context_user::instance($userid));
+
+        $items = helper::get_recent_items($limit);
+
+        $renderer = $PAGE->get_renderer('core');
+        $recentitems = array_map(function($item) use ($renderer) {
+            $context = context_module::instance($item->cmid);
+            $exporter = new recentlyaccesseditems_item_exporter($item, ['context' => $context]);
+            return $exporter->export($renderer);
+        }, $items);
+
+        return $recentitems;
+    }
+
+    /**
+     * Returns description of method result value
+     *
+     * @return external_description
+     * @since Moodle 3.6
+     */
+    public static function get_recent_items_returns() {
+        return new external_multiple_structure(recentlyaccesseditems_item_exporter::get_read_structure(),
+                'The most recently accessed activities/resources by the logged user');
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/external/recentlyaccesseditems_item_exporter.php b/blocks/recentlyaccesseditems/classes/external/recentlyaccesseditems_item_exporter.php
new file mode 100644 (file)
index 0000000..f26b43d
--- /dev/null
@@ -0,0 +1,114 @@
+<?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/>.
+/**
+ * Class for exporting the data needed to render a recent accessed item.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace block_recentlyaccesseditems\external;
+defined('MOODLE_INTERNAL') || die();
+
+use renderer_base;
+use moodle_url;
+
+/**
+ * Class for exporting the data needed to render a recent accessed item.
+ *
+ * @copyright  2018 Victor Deniz
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class recentlyaccesseditems_item_exporter extends \core\external\exporter {
+    /**
+     * Returns a list of objects that are related to this persistent.
+     *
+     */
+    protected static function define_related() {
+        // We cache the context so it does not need to be retrieved from the course.
+        return array('context' => '\\context');
+    }
+
+    /**
+     * Get the additional values to inject while exporting.
+     *
+     * @param renderer_base $output The renderer
+     * @return array Additional properties with values
+     */
+    protected function get_other_values(renderer_base $output) {
+        global $OUTPUT;
+
+        return array(
+                'viewurl' => (new moodle_url('/mod/'.$this->data->modname.'/view.php',
+                        array('id' => $this->data->cmid)))->out(false),
+                'courseviewurl' => (new moodle_url('/course/view.php', array('id' => $this->data->courseid)))->out(false),
+                'icon' => $OUTPUT->image_icon('icon', get_string('pluginname', $this->data->modname), $this->data->modname)
+        );
+    }
+
+    /**
+     * Return the list of properties.
+     *
+     * @return array Properties.
+     */
+    public static function define_properties() {
+        return array(
+            'id' => array(
+                'type' => PARAM_INT,
+            ),
+            'courseid' => array(
+                'type' => PARAM_INT,
+            ),
+            'cmid' => array(
+                'type' => PARAM_INT,
+            ),
+            'userid' => array(
+                'type' => PARAM_INT,
+            ),
+            'modname' => array(
+                'type' => PARAM_TEXT,
+            ),
+            'name' => array(
+                    'type' => PARAM_TEXT,
+            ),
+            'coursename' => array(
+                'type' => PARAM_TEXT,
+            ),
+            'timeaccess' => array(
+                'type' => PARAM_INT,
+            )
+        );
+    }
+
+    /**
+     * Return the list of additional properties.
+     *
+     * @return array Additional properties.
+     */
+    public static function define_other_properties() {
+        return array(
+            'viewurl' => array(
+                'type' => PARAM_TEXT,
+            ),
+            'courseviewurl' => array(
+                    'type' => PARAM_URL,
+            ),
+            'icon' => array(
+                'type' => PARAM_RAW,
+            )
+        );
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/helper.php b/blocks/recentlyaccesseditems/classes/helper.php
new file mode 100644 (file)
index 0000000..e7e204f
--- /dev/null
@@ -0,0 +1,93 @@
+<?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/>.
+
+/**
+ * Recently accessed items helper.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_recentlyaccesseditems;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Recently accessed items helper.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class helper {
+    /**
+     * Returns a list of the most recently items accessed by the logged user
+     *
+     * @param int $limit Restrict result set to this amount
+     * @return array List of recent items accessed by userid
+     */
+    public static function get_recent_items(int $limit = 0) {
+        global $USER, $DB;
+
+        $userid = $USER->id;
+
+        $courses = array();
+        $recentitems = array();
+
+        if (!isloggedin() or \core\session\manager::is_loggedinas() or isguestuser()) {
+            // No access tracking.
+            return $recentitems;
+        }
+
+        // Determine sort sql clause.
+        $sort = 'timeaccess DESC';
+
+        $paramsql = array('userid' => $userid);
+        $records = $DB->get_records('block_recentlyaccesseditems', $paramsql, $sort);
+        $order = 0;
+
+        // Get array of items by course. Use $order index to keep sql sorted results.
+        foreach ($records as $record) {
+            $courses[$record->courseid][$order++] = $record;
+        }
+
+        // Group by courses to reduce get_fast_modinfo requests.
+        foreach ($courses as $key => $items) {
+            $modinfo = get_fast_modinfo($key);
+            foreach ($items as $key => $item) {
+                // Exclude not visible items.
+                if (!$modinfo->cms[$item->cmid]->uservisible) {
+                    continue;
+                }
+                $item->modname = $modinfo->cms[$item->cmid]->modname;
+                $item->name = $modinfo->cms[$item->cmid]->name;
+                $item->coursename = get_course_display_name_for_list($modinfo->get_course());
+                $recentitems[$key] = $item;
+            }
+        }
+
+        ksort($recentitems);
+
+        // Apply limit.
+        if (!$limit) {
+            $limit = count($recentitems);
+        }
+        $recentitems = array_slice($recentitems, 0, $limit);
+
+        return $recentitems;
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/observer.php b/blocks/recentlyaccesseditems/classes/observer.php
new file mode 100644 (file)
index 0000000..700ced8
--- /dev/null
@@ -0,0 +1,105 @@
+<?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/>.
+
+/**
+ * Event observer.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_recentlyaccesseditems;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Events observer.
+ *
+ * Stores all actions about modules viewed in block_recentlyaccesseditems table.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class observer {
+
+    /**
+     * @var string Block table name.
+     */
+    private static $table = 'block_recentlyaccesseditems';
+
+    /**
+     * Register items views in block_recentlyaccesseditems table.
+     *
+     * When the item is view for the first time, a new record is created. If the item was viewed before, the time is
+     * updated.
+     *
+     * @param \core\event\base $event
+     */
+    public static function store(\core\event\base $event) {
+        global $DB;
+
+        if (!isloggedin() or \core\session\manager::is_loggedinas() or isguestuser()) {
+            // No access tracking.
+            return;
+        }
+
+        $conditions = [
+            'userid' => $event->userid
+        ];
+
+        $records = $DB->get_records(self::$table, $conditions, "timeaccess DESC");
+
+        foreach ($records as $record) {
+            if (($record->userid == $event->userid) && ($record->cmid == $event->contextinstanceid)) {
+                $conditions = [
+                        'userid' => $event->userid,
+                        'cmid' => $event->contextinstanceid
+                ];
+                $DB->set_field(self::$table, 'timeaccess', $event->timecreated, $conditions);
+                return;
+            }
+        }
+
+        if (count($records) >= 9) {
+            $conditions = [
+                    'id' => end($records)->id,
+            ];
+            $DB->delete_records(self::$table, $conditions);
+        }
+
+        $eventdata = new \stdClass();
+
+        $eventdata->cmid = $event->contextinstanceid;
+        $eventdata->timeaccess = $event->timecreated;
+        $eventdata->courseid = $event->courseid;
+        $eventdata->userid = $event->userid;
+
+        $DB->insert_record(self::$table, $eventdata);
+    }
+
+    /**
+     * Remove record when course module is deleted.
+     *
+     * @param \core\event\base $event
+     */
+    public static function remove(\core\event\base $event) {
+        global $DB;
+
+        $DB->delete_records(self::$table, array('cmid' => $event->contextinstanceid));
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/output/main.php b/blocks/recentlyaccesseditems/classes/output/main.php
new file mode 100644 (file)
index 0000000..2774196
--- /dev/null
@@ -0,0 +1,53 @@
+<?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/>.
+/**
+ * Class containing data for Recently accessed items block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_recentlyaccesseditems\output;
+defined('MOODLE_INTERNAL') || die();
+
+use renderable;
+use renderer_base;
+use templatable;
+
+/**
+ * Class containing data for Recently accessed items block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class main implements renderable, templatable {
+    /**
+     * Export this data so it can be used as the context for a mustache template.
+     *
+     * @param \renderer_base $output
+     * @return stdClass
+     */
+    public function export_for_template(renderer_base $output) {
+
+        $noitemsimgurl = $output->image_url('items', 'block_recentlyaccesseditems')->out();
+
+        return [
+            'noitemsimgurl' => $noitemsimgurl
+        ];
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/output/renderer.php b/blocks/recentlyaccesseditems/classes/output/renderer.php
new file mode 100644 (file)
index 0000000..ad69b66
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Recently accessed items block renderer
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace block_recentlyaccesseditems\output;
+
+defined('MOODLE_INTERNAL') || die;
+
+use plugin_renderer_base;
+
+/**
+ * Recently accessed items block renderer
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class renderer extends plugin_renderer_base {
+    /**
+     * Return the main content for the Recently accessed items block.
+     *
+     * @param \renderer_base $main The main renderable
+     * @return string HTML string
+     */
+    public function render_recentlyaccesseditems(renderer_base $main) {
+        return $this->render_from_template('block_recentlyaccesseditems/main', $main->export_for_template($this));
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/classes/privacy/provider.php b/blocks/recentlyaccesseditems/classes/privacy/provider.php
new file mode 100644 (file)
index 0000000..f56589b
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Privacy Subsystem implementation for Recently accessed items block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_recentlyaccesseditems\privacy;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \core_privacy\local\metadata\collection;
+use \core_privacy\local\request\transform;
+use \core_privacy\local\request\contextlist;
+use \core_privacy\local\request\approved_contextlist;
+use \core_privacy\local\request\writer;
+
+/**
+ * Privacy Subsystem for block_recentlyaccesseditems.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\subsystem\provider {
+
+    /**
+     * Returns information about the user data stored in this component.
+     *
+     * @param  collection $collection A list of information about this component
+     * @return collection The collection object filled out with information about this component.
+     */
+    public static function get_metadata(collection $collection) : collection {
+        $recentitems = [
+                'userid' => 'privacy:metadata:userid',
+                'courseid' => 'privacy:metadata:courseid',
+                'cmid' => 'privacy:metadata:cmid',
+                'timeaccess' => 'privacy:metadata:timeaccess'
+        ];
+
+        $collection->add_database_table('block_recentlyaccesseditems', $recentitems,
+                'privacy:metadata:block_recentlyaccesseditemstablesummary');
+
+        return $collection;
+    }
+
+    /**
+     * Get the list of contexts that contain user information for the specified user.
+     *
+     * @param   int $userid The user to search.
+     * @return  contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
+     */
+    public static function get_contexts_for_userid(int $userid) : contextlist {
+        $params = ['userid' => $userid, 'contextuser' => CONTEXT_USER];
+        $sql = "SELECT id
+                  FROM {context}
+                 WHERE instanceid = :userid and contextlevel = :contextuser";
+        $contextlist = new contextlist();
+        $contextlist->add_from_sql($sql, $params);
+        return $contextlist;
+    }
+
+    /**
+     * Export all user data for the specified user, in the specified contexts.
+     *
+     * @param approved_contextlist $contextlist The approved contexts to export information for.
+     */
+    public static function export_user_data(approved_contextlist $contextlist) {
+        $context = $contextlist->current();
+        $user = \core_user::get_user($contextlist->get_user()->id);
+        static::export_recentitems($user->id, $context);
+    }
+
+    /**
+     * Export information about the most recently accessed items.
+     *
+     * @param  int $userid The user ID.
+     * @param  \context $context The user context.
+     */
+    protected static function export_recentitems(int $userid, \context $context) {
+        global $DB;
+        $sql = "SELECT ra.id, c.fullname, ra.timeaccess, m.name, ra.cmid
+                  FROM {block_recentlyaccesseditems} ra
+                  JOIN {course} c ON c.id = ra.courseid
+                  JOIN {course_modules} cm on cm.id = ra.cmid
+                  JOIN {modules} m ON m.id = cm.module
+                 WHERE ra.userid = :userid";
+
+        $params = ['userid' => $userid];
+        $records = $DB->get_records_sql($sql, $params);
+        if (!empty($records)) {
+            $recentitems = (object) array_map(function($record) use($context) {
+                return [
+                        'course_name' => format_string($record->fullname, true, ['context' => $context]),
+                        'module_name' => format_string($record->name),
+                        'timeaccess' => transform::datetime($record->timeaccess)
+                ];
+            }, $records);
+            writer::with_context($context)->export_data([get_string('privacy:recentlyaccesseditemspath',
+                    'block_recentlyaccesseditems')], $recentitems);
+        }
+    }
+
+    /**
+     * Delete all data for all users in the specified context.
+     *
+     * @param context $context The specific context to delete data for.
+     */
+    public static function delete_data_for_all_users_in_context(\context $context) {
+        global $DB;
+
+        // Only delete data for a user context.
+        if ($context->contextlevel == CONTEXT_USER) {
+            // Delete recent items access.
+            $DB->delete_records('block_recentlyaccesseditems', ['userid' => $context->instanceid]);
+        }
+    }
+
+    /**
+     * Delete all user data for the specified user, in the specified contexts.
+     *
+     * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
+     */
+    public static function delete_data_for_user(approved_contextlist $contextlist) {
+        global $DB;
+
+        foreach ($contextlist as $context) {
+            // Let's be super certain that we have the right information for this user here.
+            if ($context->contextlevel == CONTEXT_USER && $contextlist->get_user()->id == $context->instanceid) {
+                $DB->delete_records('block_recentlyaccesseditems', ['userid' => $context->instanceid]);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/db/access.php b/blocks/recentlyaccesseditems/db/access.php
new file mode 100644 (file)
index 0000000..99ef6db
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Capabilities for the Recently accessed items block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+$capabilities = array(
+        'block/recentlyaccesseditems:myaddinstance' => array(
+                'captype' => 'write',
+                'contextlevel' => CONTEXT_SYSTEM,
+                'archetypes' => array(
+                        'user' => CAP_ALLOW
+                ),
+                'clonepermissionsfrom' => 'moodle/my:manageblocks'
+        ),
+        'block/recentlyaccesseditems:addinstance' => array(
+                'captype' => 'write',
+                'contextlevel' => CONTEXT_BLOCK,
+                'archetypes' => array(
+                        'manager' => CAP_ALLOW
+                ),
+                'clonepermissionsfrom' => 'moodle/site:manageblocks'
+        )
+);
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/db/events.php b/blocks/recentlyaccesseditems/db/events.php
new file mode 100644 (file)
index 0000000..8f08ced
--- /dev/null
@@ -0,0 +1,37 @@
+<?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/>.
+
+/**
+ * Recently accessed items event observer.
+ *
+ * @package   block_recentlyaccesseditems
+ * @category  event
+ * @copyright 2018 Victor Deniz <victor@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$observers = array (
+    array(
+            'eventname'   => '\core\event\course_module_viewed',
+            'callback'    => 'block_recentlyaccesseditems\observer::store',
+    ),
+    array(
+            'eventname'   => '\core\event\course_module_deleted',
+            'callback'    => 'block_recentlyaccesseditems\observer::remove'
+    ),
+);
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/db/install.xml b/blocks/recentlyaccesseditems/db/install.xml
new file mode 100644 (file)
index 0000000..2b6bf10
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="blocks/recentlyaccesseditems/db" VERSION="20181030" COMMENT="XMLDB file for Moodle blocks/recentlyaccesseditems"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+  <TABLES>
+    <TABLE NAME="block_recentlyaccesseditems" COMMENT="Most recently accessed items accessed by a user">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
+        <FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Course id the item belongs to"/>
+        <FIELD NAME="cmid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Item course module id"/>
+        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="User id that accessed the item"/>
+        <FIELD NAME="timeaccess" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time the user accessed the last time an item"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+        <KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
+        <KEY NAME="courseid" TYPE="foreign" FIELDS="courseid" REFTABLE="course" REFFIELDS="id"/>
+        <KEY NAME="cmid" TYPE="foreign" FIELDS="cmid" REFTABLE="course_modules" REFFIELDS="id"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="userid-courseid-cmid" UNIQUE="true" FIELDS="userid, courseid, cmid"/>
+      </INDEXES>
+    </TABLE>
+  </TABLES>
+</XMLDB>
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/db/services.php b/blocks/recentlyaccesseditems/db/services.php
new file mode 100644 (file)
index 0000000..6caf09f
--- /dev/null
@@ -0,0 +1,38 @@
+<?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/>.
+
+/**
+ * Web service for Recently accessed items block
+ *
+ * @package    block_recentlyaccesseditems
+ * @since      Moodle 3.6
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$functions = array(
+    'block_recentlyaccesseditems_get_recent_items' => array(
+        'classname' => 'block_recentlyaccesseditems\external',
+        'methodname' => 'get_recent_items',
+        'classpath' => '',
+        'description' => 'List of items a user has accessed most recently.',
+        'type' => 'read',
+        'ajax' => true,
+        'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+    ),
+);
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/lang/en/block_recentlyaccesseditems.php b/blocks/recentlyaccesseditems/lang/en/block_recentlyaccesseditems.php
new file mode 100644 (file)
index 0000000..d9238f5
--- /dev/null
@@ -0,0 +1,32 @@
+<?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/>.
+/**
+ * Strings for the Recently accessed items block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+$string['noitems'] = 'No recent items';
+$string['pluginname'] = 'Recently accessed items';
+$string['privacy:metadata:cmid'] = 'The course module id';
+$string['privacy:metadata:courseid'] = 'Course the item belongs to';
+$string['privacy:metadata:block_recentlyaccesseditemstablesummary'] = 'Information about the last time a user accessed an item.';
+$string['privacy:metadata:timeaccess'] = 'The time of the last access to the item by the user.';
+$string['privacy:metadata:userid'] = 'User who accessed the item';
+$string['privacy:recentlyaccesseditemspath'] = 'Recently accessed items';
+$string['recentlyaccesseditems:addinstance'] = 'Add a new recently accessed items block';
+$string['recentlyaccesseditems:myaddinstance'] = 'Add a new recently accessed items block to Dashboard';
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/pix/items.svg b/blocks/recentlyaccesseditems/pix/items.svg
new file mode 100644 (file)
index 0000000..ed7546a
--- /dev/null
@@ -0,0 +1,41 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="157 -1509 148 125" preserveAspectRatio="xMinYMid meet">
+  <defs>
+    <style>
+      .cls-1 {
+        clip-path: url(#clip-Activities);
+      }
+
+      .cls-2 {
+        fill: #eee;
+      }
+
+      .cls-3 {
+        fill: #c4c8cc;
+      }
+
+      .cls-4 {
+        fill: #fff;
+      }
+    </style>
+    <clipPath id="clip-Activities">
+      <rect x="157" y="-1509" width="148" height="125"/>
+    </clipPath>
+  </defs>
+  <g id="Activities" class="cls-1">
+    <g id="Group_42" data-name="Group 42" transform="translate(-268 -1985)">
+      <ellipse id="Ellipse_37" data-name="Ellipse 37" class="cls-2" cx="74" cy="14.785" rx="74" ry="14.785" transform="translate(425 571.43)"/>
+      <rect id="Rectangle_80" data-name="Rectangle 80" class="cls-3" width="94.182" height="110.215" transform="translate(451.909 476)"/>
+      <g id="Group_41" data-name="Group 41" transform="translate(467.043 493)">
+        <rect id="Rectangle_81" data-name="Rectangle 81" class="cls-4" width="44.456" height="5.625" transform="translate(21.16 0.549)"/>
+        <rect id="Rectangle_82" data-name="Rectangle 82" class="cls-4" width="33.342" height="5.625" transform="translate(21.16 11.652)"/>
+        <rect id="Rectangle_83" data-name="Rectangle 83" class="cls-4" width="44.456" height="5.625" transform="translate(21.16 30.772)"/>
+        <rect id="Rectangle_84" data-name="Rectangle 84" class="cls-4" width="33.342" height="5.625" transform="translate(21.16 41.875)"/>
+        <rect id="Rectangle_85" data-name="Rectangle 85" class="cls-4" width="44.456" height="5.625" transform="translate(21.16 61.291)"/>
+        <rect id="Rectangle_86" data-name="Rectangle 86" class="cls-4" width="33.342" height="5.625" transform="translate(21.16 72.393)"/>
+        <ellipse id="Ellipse_38" data-name="Ellipse 38" class="cls-4" cx="7.007" cy="7" rx="7.007" ry="7" transform="translate(0 0)"/>
+        <ellipse id="Ellipse_39" data-name="Ellipse 39" class="cls-4" cx="7.007" cy="7" rx="7.007" ry="7" transform="translate(0 31)"/>
+        <ellipse id="Ellipse_40" data-name="Ellipse 40" class="cls-4" cx="7.007" cy="7" rx="7.007" ry="7" transform="translate(0 61)"/>
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/blocks/recentlyaccesseditems/templates/main.mustache b/blocks/recentlyaccesseditems/templates/main.mustache
new file mode 100644 (file)
index 0000000..2f2ce75
--- /dev/null
@@ -0,0 +1,45 @@
+{{!
+    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 block_recentlyaccesseditems/main
+
+    This template renders the main content area for the Recently accessed itemes block.
+
+    Example context (json):
+    {}
+}}
+
+<div id="block-recentlyaccesseditems-{{uniqid}}" class="block-  recentlyaccesseditems" data-region="recentlyaccesseditems">
+    <div class="container-fluid p-0">
+        {{> block_recentlyaccesseditems/recentlyaccesseditems-view }}
+    </div>
+</div>
+{{#js}}
+require(
+[
+    'jquery',
+    'block_recentlyaccesseditems/main',
+],
+function(
+    $,
+    Main
+) {
+    var root = $('#block-recentlyaccesseditems-{{uniqid}}');
+
+    Main.init(root);
+});
+{{/js}}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/templates/no-items.mustache b/blocks/recentlyaccesseditems/templates/no-items.mustache
new file mode 100644 (file)
index 0000000..794f424
--- /dev/null
@@ -0,0 +1,34 @@
+{{!
+    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 block_recentlyaccesseditems/no-items
+
+    This template renders the no items message.
+
+    Example context (json):
+    {
+        "noitemsimgurl": "https://moodlesite/theme/image.php/boost/block_recentlyaccesseditems/1535727318/items"
+    }
+}}
+<div class="text-center mt-3" data-region="empty-message">
+    <img class="empty-placeholder-image-lg"
+        src="{{noitemsimgurl}}"
+        alt="{{#str}} noitems, block_recentlyaccesseditems {{/str}}"
+        role="presentation"
+    >
+    <p class="text-muted mt-3">{{#str}} noitems, block_recentlyaccesseditems {{/str}}</p>
+</div>
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/templates/placeholder-item.mustache b/blocks/recentlyaccesseditems/templates/placeholder-item.mustache
new file mode 100644 (file)
index 0000000..e1bf633
--- /dev/null
@@ -0,0 +1,33 @@
+{{!
+    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 block_recentlyaccesseditems/placeholder-item
+
+    This template renders a card item loading placeholder for the Recently accessed items block.
+
+    Example context (json):
+    {}
+}}
+<div class="card-body course-info-container">
+    <div class="d-flex flex-row align-items-center" style="height: 32px">
+        <div class="bg-pulse-grey rounded-circle" style="height: 32px; width: 32px;"></div>
+        <div class="w-100 line-height-3 ml-1">
+                <div class="bg-pulse-grey w-100" style="height: 15px;"></div>
+                <div class="bg-pulse-grey w-75 mt-1" style="height: 10px;"></div>
+        </div>
+    </div>
+</div>
diff --git a/blocks/recentlyaccesseditems/templates/recentlyaccesseditems-view.mustache b/blocks/recentlyaccesseditems/templates/recentlyaccesseditems-view.mustache
new file mode 100644 (file)
index 0000000..6e4494f
--- /dev/null
@@ -0,0 +1,40 @@
+{{!
+    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 block_recentlyaccesseditems/recentlyaccesseditems-view
+
+    This template renders the items view for the Recently accessed items block.
+
+    Example context (json):
+    {
+        "noitemsimgurl": "https://moodlesite/theme/image.php/boost/block_recentactivities/1535727318/items"
+    }
+}}
+<div id="recentlyaccesseditems-view-{{uniqid}}"
+     data-region="recentlyaccesseditems-view"
+     data-noitemsimgurl="{{noitemsimgurl}}">
+    <div data-region="recentlyaccesseditems-view-content">
+        <div data-region="recentlyaccesseditems-loading-placeholder">
+            <div class="card-deck dashboard-card-deck">
+                {{> block_recentlyaccesseditems/placeholder-item }}
+                {{> block_recentlyaccesseditems/placeholder-item }}
+                {{> block_recentlyaccesseditems/placeholder-item }}
+            </div>
+        </div>
+    </div>
+</div>
+
diff --git a/blocks/recentlyaccesseditems/templates/view-cards.mustache b/blocks/recentlyaccesseditems/templates/view-cards.mustache
new file mode 100644 (file)
index 0000000..8b3619c
--- /dev/null
@@ -0,0 +1,63 @@
+{{!
+    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 Licensebllsdsadfasfd
+    along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}
+{{!
+    @template block_recentlyaccesseditems/view-cards
+
+    This template renders the items cards of the Recently accessed items block.
+
+    Example context (json):
+    {
+        "items": [
+            {
+                "cmid": 64,
+                "courseid": 2,
+                "coursename": "Course",
+                "courseviewurl": "https://moodlesite/course/view.php?id=2",
+                "icon": "<img class=\"icon\" alt=\"Forum\" title=\"Forum\" src=\"http://moodlesite/theme/image.php/boost/forum/1539858121/icon\" />",
+                "name": "Assignment due 1",
+                "id": 17,
+                "modname": "Forum",
+                "name": "Forum",
+                "timeaccess": 1539848498,
+                "userid": 2,
+                "viewurl": "http://moodlesite/mod/forum?id=64"
+            }
+        ]
+    }
+}}
+
+<div class="card-deck dashboard-card-deck" role="list">
+    {{#items}}
+        <a
+                class="card dashboard-card py-2 pl-0 pr-0"
+                href="{{{viewurl}}}"
+                title="{{name}}"
+        >
+            <div class="card-body course-info-container">
+                <div class="d-flex">
+                    <div class="icon-size-4 d-flex align-self-center">
+                        {{{icon}}}
+                    </div>
+                    <div class="w-100 line-height-3 text-truncate">
+                        <h6 class="mb-0">{{{name}}}</h6>
+                        <small class="text-muted m-b-0">{{{coursename}}}</small>
+                    </div>
+                </div>
+            </div>
+        </a>
+    {{/items}}
+</div>
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/tests/behat/block_recentlyaccesseditems_dashboard.feature b/blocks/recentlyaccesseditems/tests/behat/block_recentlyaccesseditems_dashboard.feature
new file mode 100644 (file)
index 0000000..5aa383f
--- /dev/null
@@ -0,0 +1,38 @@
+@block @block_recentlyaccesseditems @javascript
+Feature: The recently accessed items block allows users to easily access their most recently visited items
+  In order to access the most recent items accessed
+  As a user
+  I can use the recently accessed items block in my dashboard
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email                |
+      | student1 | Student   | 1        | student1@example.com |
+    And the following "courses" exist:
+      | fullname | shortname |
+      | Course 1 | C1        |
+      | Course 2 | C2        |
+    And the following "course enrolments" exist:
+      | user     | course | role    |
+      | student1 | C1     | student |
+      | student1 | C2     | student |
+    And I log in as "admin"
+    And I am on "Course 1" course homepage
+    And I turn editing mode on
+    And I add a "Forum" to section "1" and I fill the form with:
+      | Forum name | Test forum name |
+      | Forum type | Standard forum for general use |
+      | Description | Test forum description |
+    And I log out
+    And I log in as "student1"
+    When I press "Customise this page"
+    And I add the "Recently accessed items" block
+
+  Scenario: User has not accessed any item
+    Then I should see "No recent items" in the "Recently accessed items" "block"
+
+  Scenario: User has accessed some items
+    Given I am on "Course 1" course homepage
+    When  I follow "Test forum name"
+    And I follow "Dashboard" in the user menu
+    Then I should see "Test forum name" in the "Recently accessed items" "block"
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/tests/externallib_test.php b/blocks/recentlyaccesseditems/tests/externallib_test.php
new file mode 100644 (file)
index 0000000..62de36a
--- /dev/null
@@ -0,0 +1,107 @@
+<?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/>.
+
+/**
+ * External block functions unit tests
+ *
+ * @package    block_recentlyaccesseditems
+ * @category   external
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      Moodle 3.6
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+require_once($CFG->dirroot . '/webservice/tests/helpers.php');
+
+/**
+ * Test Recently accessed items block external functions
+ *
+ * @package    block_recentlyaccesseditems
+ * @category   external
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      Moodle 3.6
+ */
+class block_recentlyaccesseditems_externallib_testcase extends externallib_advanced_testcase {
+
+    /**
+     * Test the get_recent_items function.
+     */
+    public function test_get_recent_items() {
+
+        $this->resetAfterTest();
+        $generator = $this->getDataGenerator();
+
+        // Add courses.
+        $courses = array();
+        for ($i = 1; $i < 4; $i++) {
+            $courses[] = $generator->create_course();
+        };
+
+        // Add users.
+        $student = $generator->create_user();
+        $teacher = $generator->create_user();
+
+        // Enrol users and add items to courses.
+        foreach ($courses as $course) {
+            $generator->enrol_user($student->id, $course->id, 'student');
+            $forum[] = $this->getDataGenerator()->create_module('forum', array('course' => $course));
+            $glossary[] = $this->getDataGenerator()->create_module('glossary', array('course' => $course));
+            $chat[] = $this->getDataGenerator()->create_module('chat', array('course' => $course));
+        }
+        $generator->enrol_user($teacher->id, $courses[0]->id, 'teacher');
+
+        $this->setUser($student);
+
+        // No recent items.
+        $result = \block_recentlyaccesseditems\external::get_recent_items();
+        $this->assertCount(0, $result);
+
+        // Student access all forums.
+        foreach ($forum as $module) {
+            $event = \mod_forum\event\course_module_viewed::create(array('context' => context_module::instance($module->cmid),
+                    'objectid' => $module->id));
+            $event->trigger();
+            $this->waitForSecond();
+        }
+
+        // Test that only access to forums are returned.
+        $result = \block_recentlyaccesseditems\external::get_recent_items();
+        $this->assertCount(count($forum), $result);
+
+        // Student access all assignments.
+        foreach ($chat as $module) {
+            $event = \mod_chat\event\course_module_viewed::create(array('context' => context_module::instance($module->cmid),
+                    'objectid' => $module->id));
+            $event->trigger();
+            $this->waitForSecond();
+        }
+
+        // Test that results are sorted by timeaccess DESC (default).
+        $result = \block_recentlyaccesseditems\external::get_recent_items();
+        $this->assertCount((count($forum) + count($chat)), $result);
+        foreach ($result as $key => $record) {
+            if ($key == 0) {
+                continue;
+            }
+            $this->assertTrue($record->timeaccess < $result[$key - 1]->timeaccess);
+        }
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/tests/observer_test.php b/blocks/recentlyaccesseditems/tests/observer_test.php
new file mode 100644 (file)
index 0000000..fcc0eb2
--- /dev/null
@@ -0,0 +1,160 @@
+<?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/>.
+
+/**
+ * Block recentlyaccesseditems observer tests.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      Moodle 3.6
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
+
+/**
+ * Block Recently accessed items observer tests.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      Moodle 3.6
+ */
+class block_recentlyaccesseditems_observer_testcase extends advanced_testcase {
+    use mod_assign_test_generator;
+
+    /**
+     * Set up for every test
+     */
+    public function setUp() {
+        global $DB;
+
+        $this->resetAfterTest();
+        $this->setAdminUser();
+
+        // Block table name.
+        $this->table = "block_recentlyaccesseditems";
+
+        // Setup test data.
+        $this->course = $this->getDataGenerator()->create_course();
+
+        // Create users.
+        $this->student = self::getDataGenerator()->create_user();
+        $this->teacher = self::getDataGenerator()->create_user();
+
+        // Users enrolments.
+        $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
+        $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
+        $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
+        $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
+
+        // Create items.
+        $this->forum = $this->getDataGenerator()->create_module('forum', array('course' => $this->course));
+        $this->glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $this->course));
+        $this->chat = $this->getDataGenerator()->create_module('chat', array('course' => $this->course));
+    }
+
+    /**
+     * Test items views are recorded
+     *
+     * When items events are triggered they are stored in the block_recentlyaccesseditems table.
+     */
+    public function test_item_view_recorded_testcase() {
+        global $DB;
+
+        // Empty table at the beggining.
+        $records = $DB->count_records($this->table, array());
+        $this->assertEquals(0, $records);
+
+        // Teacher access forum activity.
+        $this->setUser($this->teacher);
+        $event = \mod_forum\event\course_module_viewed::create(array('context' => context_module::instance($this->forum->cmid),
+                'objectid' => $this->forum->id));
+        $event->trigger();
+
+        // Student access chat activity.
+        $this->setUser($this->student);
+        $event1 = \mod_chat\event\course_module_viewed::create(array('context' => context_module::instance($this->chat->cmid),
+                'objectid' => $this->chat->id));
+        $event1->trigger();
+
+        $records = $DB->count_records($this->table, array('userid' => $this->teacher->id, 'courseid' => $this->course->id,
+                'cmid' => $this->forum->cmid));
+        $this->assertEquals(1, $records);
+
+        $records = $DB->count_records($this->table, array('userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' =>
+                $this->chat->cmid));
+        $this->assertEquals(1, $records);
+
+        $this->waitForSecond();
+        // Student access chat activity again after 1 second (no new record created, timeaccess updated).
+        $event2 = \mod_chat\event\course_module_viewed::create(array('context' => context_module::instance($this->chat->cmid),
+                'objectid' => $this->chat->id));
+        $event2->trigger();
+
+        $records = $DB->get_records($this->table, array('userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' =>
+                $this->chat->cmid));
+        $this->assertCount(1, $records);
+        $this->assertEquals($event2->timecreated, array_shift($records)->timeaccess);
+
+    }
+
+    /**
+     * Test removed items records are deleted.
+     *
+     * When a course module is removed, the records associated in the block_recentlyaccesseditems table are deleted.
+     */
+    public function test_item_delete_record_testcase() {
+        global $DB;
+
+        // Empty table at the beggining.
+        $records = $DB->count_records($this->table, array());
+        $this->assertEquals(0, $records);
+
+        // Teacher access forum activity.
+        $this->setUser($this->teacher);
+        $event = \mod_forum\event\course_module_viewed::create(array('context' => context_module::instance($this->forum->cmid),
+                'objectid' => $this->forum->id));
+        $event->trigger();
+
+        // Teacher access chat activity.
+        $event = \mod_chat\event\course_module_viewed::create(array('context' => context_module::instance($this->chat->cmid),
+                'objectid' => $this->chat->id));
+        $event->trigger();
+
+        // Student access chat activity.
+        $this->setUser($this->student);
+        $event = \mod_chat\event\course_module_viewed::create(array('context' => context_module::instance($this->chat->cmid),
+                'objectid' => $this->chat->id));
+        $event->trigger();
+
+        // Student access forum activity.
+        $event = \mod_forum\event\course_module_viewed::create(array('context' => context_module::instance($this->forum->cmid),
+                'objectid' => $this->forum->id));
+        $event->trigger();
+
+        $records = $DB->count_records($this->table, array('cmid' => $this->forum->cmid));
+        $this->assertEquals(2, $records);
+        course_delete_module($this->forum->cmid);
+        $records = $DB->count_records($this->table, array('cmid' => $this->forum->cmid));
+        $this->assertEquals(0, $records);
+        $records = $DB->count_records($this->table, array('cmid' => $this->chat->cmid));
+        $this->assertEquals(2, $records);
+    }
+}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/version.php b/blocks/recentlyaccesseditems/version.php
new file mode 100644 (file)
index 0000000..198c338
--- /dev/null
@@ -0,0 +1,27 @@
+<?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/>.
+/**
+ * Version details for the Recent activities block.
+ *
+ * @package    block_recentlyaccesseditems
+ * @copyright  2018 Victor Deniz <victor@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+
+$plugin->version   = 2018101705;            // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2018101900;            // Requires this Moodle version.
+$plugin->component = 'block_recentlyaccesseditems'; // Full name of the plugin (used for diagnostics).
index ca16fd4..cd695ba 100644 (file)
@@ -1718,7 +1718,7 @@ class core_plugin_manager {
                 'feedback', 'globalsearch', 'glossary_random', 'html',
                 'login', 'lp', 'mentees', 'mnet_hosts', 'myoverview', 'myprofile',
                 'navigation', 'news_items', 'online_users', 'participants',
-                'private_files', 'quiz_results', 'recent_activity',
+                'private_files', 'quiz_results', 'recent_activity', 'recentlyaccesseditems',
                 'rss_client', 'search_forums', 'section_links',
                 'selfcompletion', 'settings', 'site_main_menu',
                 'social_activities', 'tag_flickr', 'tag_youtube', 'tags', 'timeline'
index c4cc09b..90cfc3d 100644 (file)
@@ -116,6 +116,43 @@ $card-gutter : $card-deck-margin * 2;
     background-size: cover;
 }
 
+[data-region="blocks-column"] {
+    .block_recentlyaccesseditems {
+        .dashboard-card-deck {
+            height: unset;
+        }
+    }
+}
+
+.block_recentlyaccesseditems {
+    [data-region="recentlyaccesseditems-view-content"] {
+        overflow-x: hidden;
+    }
+    .dashboard-card {
+        height: 75px;
+    }
+    .dashboard-card-deck {
+        @include media-breakpoint-up(sm) {
+            height: 75px;
+            overflow: hidden;
+        }
+    }
+    .course-info-container {
+        padding: 0.8rem;
+    }
+    .empty-placeholder-image-lg {
+        height: 125px;
+    }
+    a,
+    a:hover {
+        text-decoration: none;
+        color: unset;
+    }
+    .block-controls ~ .content {
+        margin-top: 2rem !important;
+    }
+}
+
 .dashboard-card-deck .dashboard-card {
     margin-bottom: $card-gutter;
     flex-basis: 100%;
index a0e4db7..984b9ab 100644 (file)
@@ -11167,6 +11167,34 @@ div.editor_atto_toolbar button .icon {
   background-position: center;
   background-size: cover; }
 
+[data-region="blocks-column"] .block_recentlyaccesseditems .dashboard-card-deck {
+  height: unset; }
+
+.block_recentlyaccesseditems [data-region="recentlyaccesseditems-view-content"] {
+  overflow-x: hidden; }
+
+.block_recentlyaccesseditems .dashboard-card {
+  height: 75px; }
+
+@media (min-width: 576px) {
+  .block_recentlyaccesseditems .dashboard-card-deck {
+    height: 75px;
+    overflow: hidden; } }
+
+.block_recentlyaccesseditems .course-info-container {
+  padding: 0.8rem; }
+
+.block_recentlyaccesseditems .empty-placeholder-image-lg {
+  height: 125px; }
+
+.block_recentlyaccesseditems a,
+.block_recentlyaccesseditems a:hover {
+  text-decoration: none;
+  color: unset; }
+
+.block_recentlyaccesseditems .block-controls ~ .content {
+  margin-top: 2rem !important; }
+
 .dashboard-card-deck .dashboard-card {
   margin-bottom: 0.5rem;
   flex-basis: 100%;
index 10c58a6..c442d2d 100644 (file)
     }
 }
 
+.block_recentlyaccesseditems {
+    [data-region="recentlyaccesseditems-view-content"] {
+        overflow-x: hidden;
+    }
+    .dashboard-card {
+        height: 75px;
+    }
+    .dashboard-card-deck {
+        @media (min-width: 576px) {
+            height: 75px;
+            overflow: hidden;
+        }
+    }
+    .empty-placeholder-image-lg {
+        height: 125px;
+    }
+    .course-info-container {
+        flex: 1 1 auto;
+        padding: 0.8rem;
+    }
+    .icon-size-4 .icon {
+        height: auto;
+        width: auto;
+        background-image: unset;
+        box-sizing: unset;
+    }
+    .icon-size-4 {
+        background-image: unset;
+        height: unset;
+        width: unset;
+    }
+    .ml-1 {
+        margin-left: 10px;
+    }
+    h6 {
+        font-size: .9375rem;
+        margin-bottom: 0;
+    }
+    a,
+    a:hover {
+        text-decoration: none;
+        color: unset;
+    }
+}
+
 .dashboard-card-deck {
     box-sizing: border-box;
     *,
 }
 
 @media (min-width: 768px) {
-    #block-region-side-post .dashboard-card-deck {
+    #block-region-side-post .dashboard-card-deck,
+    #block-region-side-pre .dashboard-card-deck {
         margin: 0;
+        height: unset;
         .dashboard-card {
             flex-basis: 100%;
             margin-left: 0;
index 2fd008a..6d0d57c 100644 (file)
@@ -16597,6 +16597,48 @@ body {
     max-height: 7rem;
   }
 }
+.block_recentlyaccesseditems [data-region="recentlyaccesseditems-view-content"] {
+  overflow-x: hidden;
+}
+.block_recentlyaccesseditems .dashboard-card {
+  height: 75px;
+}
+@media (min-width: 576px) {
+  .block_recentlyaccesseditems .dashboard-card-deck {
+    height: 75px;
+    overflow: hidden;
+  }
+}
+.block_recentlyaccesseditems .empty-placeholder-image-lg {
+  height: 125px;
+}
+.block_recentlyaccesseditems .course-info-container {
+  flex: 1 1 auto;
+  padding: 0.8rem;
+}
+.block_recentlyaccesseditems .icon-size-4 .icon {
+  height: auto;
+  width: auto;
+  background-image: unset;
+  box-sizing: unset;
+}
+.block_recentlyaccesseditems .icon-size-4 {
+  background-image: unset;
+  height: unset;
+  width: unset;
+}
+.block_recentlyaccesseditems .ml-1 {
+  margin-left: 10px;
+}
+.block_recentlyaccesseditems h6 {
+  font-size: .9375rem;
+  margin-bottom: 0;
+}
+.block_recentlyaccesseditems a,
+.block_recentlyaccesseditems a:hover {
+  text-decoration: none;
+  color: unset;
+}
 .dashboard-card-deck {
   box-sizing: border-box;
   display: flex;
@@ -16634,10 +16676,13 @@ body {
   }
 }
 @media (min-width: 768px) {
-  #block-region-side-post .dashboard-card-deck {
+  #block-region-side-post .dashboard-card-deck,
+  #block-region-side-pre .dashboard-card-deck {
     margin: 0;
+    height: unset;
   }
-  #block-region-side-post .dashboard-card-deck .dashboard-card {
+  #block-region-side-post .dashboard-card-deck .dashboard-card,
+  #block-region-side-pre .dashboard-card-deck .dashboard-card {
     flex-basis: 100%;
     margin-left: 0;
     margin-right: 0;
index 815ceef..810a9f4 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2018103000.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2018103100.00;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 
-$release  = '3.6dev+ (Build: 20181027)'; // Human-friendly version name
+$release  = '3.6dev+ (Build: 20181031)'; // Human-friendly version name
 
 $branch   = '36';                       // This version's branch.
 $maturity = MATURITY_ALPHA;             // This version's maturity level.