Merge branch 'MDL-63352-master' of git://github.com/peterRd/moodle

This commit is contained in:
Damyon Wiese
2018-10-15 14:50:10 +08:00
16 changed files with 488 additions and 39 deletions
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/custom_interaction_events","block_timeline/view"],function(a,b,c){var d={TIMELINE_DAY_FILTER:'[data-region="day-filter"]',TIMELINE_DAY_FILTER_OPTION:"[data-from]",TIMELINE_VIEW_SELECTOR:'[data-region="view-selector"]',DATA_DAYS_OFFSET:"[data-days-offset]",DATA_DAYS_LIMIT:"[data-days-limit]"},e=function(e,f){var g=e.find(d.TIMELINE_DAY_FILTER);b.define(g,[b.events.activate]),g.on(b.events.activate,d.TIMELINE_DAY_FILTER_OPTION,function(b,g){var h=a(b.target).closest(d.TIMELINE_DAY_FILTER_OPTION);if(!h.hasClass("active")){var i=h.attr("data-from"),j=h.attr("data-to"),k=e.find(d.DATA_DAYS_OFFSET);k.attr("data-days-offset",i),void 0!=j?k.attr("data-days-limit",j):k.removeAttr("data-days-limit"),c.reset(f),g.originalEvent.preventDefault()}})},f=function(a,b){a.find(d.TIMELINE_VIEW_SELECTOR).on("shown shown.bs.tab",function(){c.shown(b)})},g=function(b,c){b=a(b),e(b,c),f(b,c)};return{init:g}});
define(["jquery","core/custom_interaction_events","block_timeline/view","core/ajax","core/notification"],function(a,b,c,d,e){var f={TIMELINE_DAY_FILTER:'[data-region="day-filter"]',TIMELINE_DAY_FILTER_OPTION:"[data-from]",TIMELINE_VIEW_SELECTOR:'[data-region="view-selector"]',DATA_DAYS_OFFSET:"[data-days-offset]",DATA_DAYS_LIMIT:"[data-days-limit]"},g=function(a,b){var c={methodname:"core_user_update_user_preferences",args:{preferences:[{type:a,value:b}]}};d.call([c])[0].fail(e.exception)},h=function(d,e){var h=d.find(f.TIMELINE_DAY_FILTER);b.define(h,[b.events.activate]),h.on(b.events.activate,f.TIMELINE_DAY_FILTER_OPTION,function(b,h){var i=a(b.currentTarget).data("filtername"),j="block_timeline_user_filter_preference";g(j,i);var k=a(b.target).closest(f.TIMELINE_DAY_FILTER_OPTION);if(!k.hasClass("active")){var l=k.attr("data-from"),m=k.attr("data-to"),n=d.find(f.DATA_DAYS_OFFSET);n.attr("data-days-offset",l),void 0!=m?n.attr("data-days-limit",m):n.removeAttr("data-days-limit"),c.reset(e),h.originalEvent.preventDefault()}})},i=function(d,e){var h=d.find(f.TIMELINE_VIEW_SELECTOR);h.on("shown shown.bs.tab",function(){c.shown(e)}),b.define(h,[b.events.activate]),h.on(b.events.activate,"[data-toggle='tab']",function(b){var c=a(b.currentTarget).data("filtername"),d="block_timeline_user_sort_preference";g(d,c)})},j=function(b,c){b=a(b),h(b,c),i(b,c)};return{init:j}});
+45 -3
View File
@@ -25,12 +25,16 @@ define(
[
'jquery',
'core/custom_interaction_events',
'block_timeline/view'
'block_timeline/view',
'core/ajax',
'core/notification'
],
function(
$,
CustomEvents,
View
View,
Ajax,
Notification
) {
var SELECTORS = {
@@ -41,6 +45,29 @@ function(
DATA_DAYS_LIMIT: '[data-days-limit]',
};
/**
* Generic handler to persist user preferences
*
* @param {string} type The name of the attribute you're updating
* @param {string} value The value of the attribute you're updating
*/
var updateUserPreferences = function(type, value) {
var request = {
methodname: 'core_user_update_user_preferences',
args: {
preferences: [
{
type: type,
value: value
}
]
}
};
Ajax.call([request])[0]
.fail(Notification.exception);
};
/**
* Event listener for the day selector ("Next 7 days", "Next 30 days", etc).
*
@@ -55,6 +82,11 @@ function(
CustomEvents.events.activate,
SELECTORS.TIMELINE_DAY_FILTER_OPTION,
function(e, data) {
// Update the user preference
var filtername = $(e.currentTarget).data('filtername');
var type = 'block_timeline_user_filter_preference';
updateUserPreferences(type, filtername);
var option = $(e.target).closest(SELECTORS.TIMELINE_DAY_FILTER_OPTION);
if (option.hasClass('active')) {
@@ -94,11 +126,21 @@ function(
* @param {object} timelineViewRoot The root element for the timeline view
*/
var registerViewSelector = function(root, timelineViewRoot) {
var viewSelector = root.find(SELECTORS.TIMELINE_VIEW_SELECTOR);
// Listen for when the user changes tab so that we can show the first set of courses
// and load their events when they request the sort by courses view for the first time.
root.find(SELECTORS.TIMELINE_VIEW_SELECTOR).on('shown shown.bs.tab', function() {
viewSelector.on('shown shown.bs.tab', function() {
View.shown(timelineViewRoot);
});
// Event selector for user_sort
CustomEvents.define(viewSelector, [CustomEvents.events.activate]);
viewSelector.on(CustomEvents.events.activate, "[data-toggle='tab']", function(e) {
var filtername = $(e.currentTarget).data('filtername');
var type = 'block_timeline_user_sort_preference';
updateUserPreferences(type, filtername);
});
};
/**
+4 -1
View File
@@ -50,7 +50,10 @@ class block_timeline extends block_base {
return $this->content;
}
$renderable = new \block_timeline\output\main();
$sort = get_user_preferences('block_timeline_user_sort_preference');
$filter = get_user_preferences('block_timeline_user_filter_preference');
$renderable = new \block_timeline\output\main($sort, $filter);
$renderer = $this->page->get_renderer('block_timeline');
$this->content = (object) [
+92 -2
View File
@@ -30,6 +30,7 @@ use templatable;
use core_course\external\course_summary_exporter;
require_once($CFG->dirroot . '/course/lib.php');
require_once($CFG->dirroot . '/blocks/timeline/lib.php');
require_once($CFG->libdir . '/completionlib.php');
/**
@@ -43,6 +44,86 @@ class main implements renderable, templatable {
/** Number of courses to load per page */
const COURSES_PER_PAGE = 2;
/**
* @var string The current filter preference
*/
public $filter;
/**
* @var string The current sort/order preference
*/
public $order;
/**
* main constructor.
*
* @param string $order Constant sort value from ../timeline/lib.php
* @param string $filter Constant sort value from ../timeline/lib.php
*/
public function __construct($order, $filter) {
$this->order = $order ? $order : BLOCK_TIMELINE_SORT_BY_DATES;
$this->filter = $filter ? $filter : BLOCK_TIMELINE_FILTER_BY_7_DAYS;
}
/**
* Test the available filters with the current user preference and return an array with
* bool flags corresponding to which is active
*
* @return array
*/
protected function get_filters_as_booleans() {
$filters = [
BLOCK_TIMELINE_FILTER_BY_NONE => false,
BLOCK_TIMELINE_FILTER_BY_OVERDUE => false,
BLOCK_TIMELINE_FILTER_BY_7_DAYS => false,
BLOCK_TIMELINE_FILTER_BY_30_DAYS => false,
BLOCK_TIMELINE_FILTER_BY_3_MONTHS => false,
BLOCK_TIMELINE_FILTER_BY_6_MONTHS => false
];
// Set the selected filter to true.
$filters[$this->filter] = true;
return $filters;
}
/**
* Get the offset/limit values corresponding to $this->filter
* which are used to send through to the context as default values
*
* @return array
*/
private function get_filter_offsets() {
$limit = false;
if (in_array($this->filter, [BLOCK_TIMELINE_FILTER_BY_NONE, BLOCK_TIMELINE_FILTER_BY_OVERDUE])) {
$offset = -14;
if ($this->filter == BLOCK_TIMELINE_FILTER_BY_OVERDUE) {
$limit = 0;
}
} else {
$offset = 0;
$limit = 7;
switch($this->filter) {
case BLOCK_TIMELINE_FILTER_BY_30_DAYS:
$limit = 30;
break;
case BLOCK_TIMELINE_FILTER_BY_3_MONTHS:
$limit = 90;
break;
case BLOCK_TIMELINE_FILTER_BY_6_MONTHS:
$limit = 180;
break;
}
}
return [
'daysoffset' => $offset,
'dayslimit' => $limit
];
}
/**
* Export this data so it can be used as the context for a mustache template.
*
@@ -69,13 +150,22 @@ class main implements renderable, templatable {
return $exporter->export($output);
}, $inprogresscourses);
return [
$filters = $this->get_filters_as_booleans();
$offsets = $this->get_filter_offsets();
$contextvariables = [
'midnight' => usergetmidnight(time()),
'coursepages' => [$formattedcourses],
'urls' => [
'nocourses' => $nocoursesurl,
'noevents' => $noeventsurl
]
],
'sorttimelinedates' => $this->order == BLOCK_TIMELINE_SORT_BY_DATES,
'sorttimelinecourses' => $this->order == BLOCK_TIMELINE_SORT_BY_COURSES,
'selectedfilter' => $this->filter,
'hasdaysoffset' => true,
'hasdayslimit' => $offsets['dayslimit'] !== false ,
'nodayslimit' => $offsets['dayslimit'] === false ,
];
return array_merge($contextvariables, $filters, $offsets);
}
}
+32 -6
View File
@@ -25,6 +25,7 @@
namespace block_timeline\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
/**
* Privacy Subsystem for block_timeline.
@@ -32,15 +33,40 @@ defined('MOODLE_INTERNAL') || die();
* @copyright 2018 Ryan Wyllie <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\user_preference_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
* Returns meta-data information about the myoverview block.
*
* @return string
* @param \core_privacy\local\metadata\collection $collection A collection of meta-data.
* @return \core_privacy\local\metadata\collection Return the collection of meta-data.
*/
public static function get_reason() : string {
return 'privacy:metadata';
public static function get_metadata(collection $collection) : collection {
$collection->add_user_preference('block_timeline_user_sort_preference', 'privacy:metadata:timelinesortpreference');
$collection->add_user_preference('block_timeline_user_filter_preference', 'privacy:metadata:timelinefilterpreference');
return $collection;
}
/**
* Export all user preferences for the myoverview block
*
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences(int $userid) {
$preference = get_user_preferences('block_timeline_user_sort_preference', null, $userid);
if (isset($preference)) {
\core_privacy\local\request\writer::export_user_preference('block_timeline', 'block_timeline_user_sort_preference',
get_string($preference, 'block_timeline'),
get_string('privacy:metadata:timelinesortpreference', 'block_timeline')
);
}
$preference = get_user_preferences('block_timeline_user_filter_preference', null, $userid);
if (isset($preference)) {
\core_privacy\local\request\writer::export_user_preference('block_timeline', 'block_timeline_user_filter_preference',
get_string($preference, 'block_timeline'),
get_string('privacy:metadata:timelinefilterpreference', 'block_timeline')
);
}
}
}
+3 -1
View File
@@ -41,9 +41,11 @@ $string['next7days'] = 'Next 7 days';
$string['next3months'] = 'Next 3 months';
$string['next6months'] = 'Next 6 months';
$string['overdue'] = 'Overdue';
$string['all'] = 'All';
$string['pluginname'] = 'Timeline';
$string['sortbycourses'] = 'Sort by courses';
$string['sortbydates'] = 'Sort by dates';
$string['timeline'] = 'Timeline';
$string['viewcourse'] = 'View course';
$string['privacy:metadata'] = 'The timeline block does not store any personal data.';
$string['privacy:metadata:timelinesortpreference'] = 'The user sort preference for the timeline block.';
$string['privacy:metadata:timelinefilterpreference'] = 'The user day filter preference for the timeline block.';
+70
View File
@@ -0,0 +1,70 @@
<?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/>.
/**
* Library functions for timeline
*
* @package block_timeline
* @copyright 2018 Peter Dias
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Define constants to store the SORT user preference
*/
define('BLOCK_TIMELINE_SORT_BY_DATES', 'sortbydates');
define('BLOCK_TIMELINE_SORT_BY_COURSES', 'sortbycourses');
/**
* Define constants to store the FILTER user preference
*/
define('BLOCK_TIMELINE_FILTER_BY_NONE', 'all');
define('BLOCK_TIMELINE_FILTER_BY_OVERDUE', 'overdue');
define('BLOCK_TIMELINE_FILTER_BY_7_DAYS', 'next7days');
define('BLOCK_TIMELINE_FILTER_BY_30_DAYS', 'next30days');
define('BLOCK_TIMELINE_FILTER_BY_3_MONTHS', 'next3months');
define('BLOCK_TIMELINE_FILTER_BY_6_MONTHS', 'next6months');
/**
* Returns the name of the user preferences as well as the details this plugin uses.
*
* @return array
*/
function block_timeline_user_preferences() {
$preferences['block_timeline_user_sort_preference'] = array(
'null' => NULL_NOT_ALLOWED,
'default' => BLOCK_TIMELINE_SORT_BY_DATES,
'type' => PARAM_ALPHA,
'choices' => array(BLOCK_TIMELINE_SORT_BY_DATES, BLOCK_TIMELINE_SORT_BY_COURSES)
);
$preferences['block_timeline_user_filter_preference'] = array(
'null' => NULL_NOT_ALLOWED,
'default' => BLOCK_TIMELINE_FILTER_BY_30_DAYS,
'type' => PARAM_ALPHANUM,
'choices' => array(
BLOCK_TIMELINE_FILTER_BY_NONE,
BLOCK_TIMELINE_FILTER_BY_OVERDUE,
BLOCK_TIMELINE_FILTER_BY_7_DAYS,
BLOCK_TIMELINE_FILTER_BY_30_DAYS,
BLOCK_TIMELINE_FILTER_BY_3_MONTHS,
BLOCK_TIMELINE_FILTER_BY_6_MONTHS
)
);
return $preferences;
}
@@ -32,18 +32,20 @@
</button>
<div role="menu" class="dropdown-menu" data-show-active-item>
<a
class="dropdown-item"
class="dropdown-item {{#all}} active {{/all}}"
href="#"
data-from="-14"
data-filtername="all"
aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} all, core {{/str}}{{/str}}"
>
{{#str}} all, core {{/str}}
</a>
<a
class="dropdown-item"
class="dropdown-item {{#overdue}} active {{/overdue}}"
href="#"
data-from="-14"
data-to="0"
data-filtername="overdue"
aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} overdue, block_timeline {{/str}}{{/str}}"
>
{{#str}} overdue, block_timeline {{/str}}
@@ -51,37 +53,41 @@
<div class="dropdown-divider"></div>
<h6 class="dropdown-header">{{#str}} duedate, block_timeline {{/str}}</h6>
<a
class="dropdown-item"
class="dropdown-item {{#next7days}} active {{/next7days}}"
href="#"
data-from="0"
data-to="7"
data-filtername="next7days"
aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next7days, block_timeline {{/str}}{{/str}}"
>
{{#str}} next7days, block_timeline {{/str}}
</a>
<a
class="dropdown-item active"
class="dropdown-item {{#next30days}} active {{/next30days}}"
href="#"
data-from="0"
data-to="30"
data-filtername="next30days"
aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next30days, block_timeline {{/str}}{{/str}}"
>
{{#str}} next30days, block_timeline {{/str}}
</a>
<a
class="dropdown-item"
class="dropdown-item {{#next3months}} active {{/next3months}}"
href="#"
data-from="0"
data-to="90"
data-filtername="next3months"
aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next3months, block_timeline {{/str}}{{/str}}"
>
{{#str}} next3months, block_timeline {{/str}}
</a>
<a
class="dropdown-item"
class="dropdown-item {{#next6months}} active {{/next6months}}"
href="#"
data-from="0"
data-to="180"
data-filtername="next6months"
aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next6months, block_timeline {{/str}}{{/str}}"
>
{{#str}} next6months, block_timeline {{/str}}
@@ -26,23 +26,25 @@
<button type="button" class="btn btn-outline-secondary dropdown-toggle icon-no-margin" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{#pix}} i/filter {{/pix}}
<span class="sr-only">
{{#str}} ariaviewselector, block_timeline{{/str}}
<span data-active-item-text>{{#str}} sortbydates, block_timeline {{/str}}</span>
{{#sorttimelinecourses}}<span data-active-item-text>{{/sorttimelinecourses}}{{#str}} ariaviewselector, block_timeline{{/str}}{{#sorttimelinecourses}}</span>{{/sorttimelinecourses}}
{{#sorttimelinedates}}<span data-active-item-text>{{/sorttimelinedates}}{{#str}} sortbydates, block_timeline {{/str}}{{#sorttimelinedates}}</span>{{/sorttimelinedates}}
</span>
</button>
<div role="menu" class="dropdown-menu dropdown-menu-right list-group hidden" data-show-active-item data-skip-active-class="true">
<div role="menu" class="dropdown-menu dropdown-menu-right list-group hidden" data-show-active-item data-skip-active-class="true" >
<a
class="dropdown-item active"
class="dropdown-item {{#sorttimelinedates}}active{{/sorttimelinedates}}"
href="#view_dates_{{uniqid}}"
data-toggle="tab"
data-filtername="sortbydates"
aria-label="{{#str}} ariaviewselectoroption, block_timeline, {{#str}} sortbydates, block_timeline {{/str}}{{/str}}"
>
{{#str}} sortbydates, block_timeline {{/str}}
</a>
<a
class="dropdown-item"
class="dropdown-item {{#sorttimelinecourses}}active{{/sorttimelinecourses}}"
href="#view_courses_{{uniqid}}"
data-toggle="tab"
data-filtername="sortbycourses"
aria-label="{{#str}} ariaviewselectoroption, block_timeline, {{#str}} sortbycourses, block_timeline {{/str}}{{/str}}"
>
{{#str}} sortbycourses, block_timeline {{/str}}
+26 -3
View File
@@ -20,15 +20,38 @@
This template renders the timeline view for the timeline block.
Example context (json):
{}
{
"midnight": 1538954668,
"coursepages": [
{}
],
"urls": {
"nocourses": "#",
"noevents": "#"
},
"sorttimelinedates": true,
"sorttimelinecourses": false,
"selectedfilter": "all",
"hasdaysoffset": true,
"hasdayslimit": false,
"nodayslimit": true,
"all": true,
"overdue": false,
"next7days": false,
"next30days": false,
"next3months": false,
"next6months": false,
"daysoffset": -14,
"dayslimit": false
}
}}
<div data-region="timeline-view">
<div class="tab-content">
<div class="tab-pane active fade show" data-region="view-dates" id="view_dates_{{uniqid}}">
<div class="tab-pane {{#sorttimelinedates}}active show{{/sorttimelinedates}} fade" data-region="view-dates" id="view_dates_{{uniqid}}">
{{> block_timeline/view-dates }}
</div>
<div
class="tab-pane fade"
class="tab-pane {{#sorttimelinecourses}}active show{{/sorttimelinecourses}} fade"
data-region="view-courses"
data-midnight="{{midnight}}"
data-limit="2"
@@ -70,3 +70,22 @@ Feature: The timeline block allows users to see upcoming courses
And I should not see "Course 4" in the "Timeline" "block"
And I should not see "Test choice 2 closes" in the "Timeline" "block"
And I should not see "Test feedback 4 closes" in the "Timeline" "block"
Scenario: Persistent sort filter
Given I log in as "student1"
And I click on "Sort" "button" in the "Timeline" "block"
And I click on "Sort by dates" "link" in the "Timeline" "block"
And I click on "Sort" "button" in the "Timeline" "block"
And I click on "Sort by courses" "link" in the "Timeline" "block"
And I reload the page
Then I should see "Course 1" in the "Timeline" "block"
And I should see "Course 2" in the "Timeline" "block"
And I should see "More courses" in the "Timeline" "block"
And I should see "Test choice 1 closes" in the "Timeline" "block"
And I should see "Test feedback 1 closes" in the "Timeline" "block"
And I should not see "Course 3" in the "Timeline" "block"
And I should not see "Test choice 2 closes" in the "Timeline" "block"
And I should not see "Test choice 3 closes" in the "Timeline" "block"
And I should not see "Test feedback 2 closes" in the "Timeline" "block"
And I should not see "Test feedback 3 closes" in the "Timeline" "block"
And I should not see "Test assign 1 is due" in the "Timeline" "block"
@@ -86,3 +86,36 @@ Feature: The timeline block allows users to see upcoming activities
And I should see "Test feedback 3 closes" in the "Timeline" "block"
And I should see "Test feedback 2 closes" in the "Timeline" "block"
And I should not see "Test choice 2 closes" in the "Timeline" "block"
Scenario: Persistent All in date view
Given I log in as "student1"
And I click on "Next 30 days" "button" in the "Timeline" "block"
When I click on "All" "link" in the "Timeline" "block"
And I reload the page
Then I should see "Test assign 1 is due" in the "Timeline" "block"
And I should see "Test feedback 1 closes" in the "Timeline" "block"
And I should see "Test choice 1 closes" in the "Timeline" "block"
And I should see "Test choice 3 closes" in the "Timeline" "block"
And I should see "Test feedback 3 closes" in the "Timeline" "block"
And I should not see "Test choice 2 closes" in the "Timeline" "block"
And I should not see "Test feedback 2 closes" in the "Timeline" "block"
And I click on "[data-region='paging-bar'] [data-control='next']" "css_element" in the "Timeline" "block"
And I should see "Test feedback 2 closes" in the "Timeline" "block"
And I should not see "Test assign 1 is due" in the "Timeline" "block"
And I should not see "Test feedback 1 closes" in the "Timeline" "block"
And I should not see "Test choice 1 closes" in the "Timeline" "block"
And I should not see "Test choice 3 closes" in the "Timeline" "block"
And I should not see "Test feedback 3 closes" in the "Timeline" "block"
And I should not see "Test choice 2 closes" in the "Timeline" "block"
Scenario: Persistent Overdue in date view
Given I log in as "student1"
And I click on "Next 30 days" "button" in the "Timeline" "block"
When I click on "Overdue" "link" in the "Timeline" "block"
And I reload the page
Then I should see "Test assign 1 is due" in the "Timeline" "block"
And I should not see "Test choice 2 closes" in the "Timeline" "block"
And I should not see "Test feedback 1 closes" in the "Timeline" "block"
And I should not see "Test choice 1 closes" in the "Timeline" "block"
And I should not see "Test choice 3 closes" in the "Timeline" "block"
And I should not see "Test feedback 3 closes" in the "Timeline" "block"
+110
View File
@@ -0,0 +1,110 @@
<?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/>.
/**
* Unit tests for the block_timeline implementation of the privacy API.
*
* @package block_timeline
* @category test
* @copyright 2018 Peter Dias <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\request\writer;
use \block_timeline\privacy\provider;
/**
* Unit tests for the block_timeline implementation of the privacy API.
*
* @copyright 2018 Peter Dias <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_timeline_privacy_testcase extends \core_privacy\tests\provider_testcase {
/**
* Ensure that export_user_preferences returns no data if the user has not visited the myoverview block.
*/
public function test_export_user_preferences_no_pref() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$this->assertFalse($writer->has_any_data());
}
/**
* Test that the preference courses is exported properly.
*/
public function test_export_user_preferences_date_sort_preference() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
set_user_preference('block_timeline_user_sort_preference', 'sortbydates', $user);
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$blockpreferences = $writer->get_user_preferences('block_timeline');
$this->assertEquals('Sort by dates', $blockpreferences->block_timeline_user_sort_preference->value);
}
/**
* Test that the preference timeline is exported properly.
*/
public function test_export_user_preferences_course_sort_preference() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
set_user_preference('block_timeline_user_sort_preference', 'sortbycourses', $user);
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$blockpreferences = $writer->get_user_preferences('block_timeline');
$this->assertEquals('Sort by courses', $blockpreferences->block_timeline_user_sort_preference->value);
}
/**
* Test that the preference timeline is exported properly.
*/
public function test_export_user_preferences_7day_filter_preference() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
set_user_preference('block_timeline_user_filter_preference', 'next7days', $user);
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$blockpreferences = $writer->get_user_preferences('block_timeline');
$this->assertEquals('Next 7 days', $blockpreferences->block_timeline_user_filter_preference->value);
}
/**
* Test that the preference timeline is exported properly.
*/
public function test_export_user_preferences_all_filter_preference() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
set_user_preference('block_timeline_user_filter_preference', 'all', $user);
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$blockpreferences = $writer->get_user_preferences('block_timeline');
$this->assertEquals('All', $blockpreferences->block_timeline_user_filter_preference->value);
}
}
@@ -32,33 +32,33 @@
<span data-region="caret" class="caret"></span>
</button>
<ul role="menu" class="dropdown-menu" data-show-active-item>
<li class="dropdown-item" data-from="-14">
<li class="dropdown-item {{#all}} active {{/all}}" data-from="-14" data-filtername="all">
<a href="#" aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} all, core {{/str}}{{/str}}">
{{#str}} all, core {{/str}}
</a>
</li>
<li class="dropdown-item" data-from="-14" data-to="0">
<li class="dropdown-item {{#overdue}} active {{/overdue}}" data-from="-14" data-to="0" data-filtername="overdue">
<a href="#" aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} overdue, block_timeline {{/str}}{{/str}}">
{{#str}} overdue, block_timeline {{/str}}
</a>
</li>
<li class="divider"></li>
<li class="dropdown-item" data-from="0" data-to="7">
<li class="dropdown-item {{#next7days}} active {{/next7days}}" data-from="0" data-to="7" data-filtername="next7days">
<a href="#" aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next7days, block_timeline {{/str}}{{/str}}">
{{#str}} next7days, block_timeline {{/str}}
</a>
</li>
<li class="dropdown-item active" data-from="0" data-to="30">
<li class="dropdown-item {{#next30days}} active {{/next30days}}" data-from="0" data-to="30" data-filtername="next30days">
<a href="#" aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next30days, block_timeline {{/str}}{{/str}}">
{{#str}} next30days, block_timeline {{/str}}
</a>
</li>
<li class="dropdown-item" data-from="0" data-to="90">
<li class="dropdown-item {{#next3months}} active {{/next3months}}" data-from="0" data-to="90" data-filtername="next3months">
<a href="#" aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next3months, block_timeline {{/str}}{{/str}}">
{{#str}} next3months, block_timeline {{/str}}
</a>
</li>
<li class="dropdown-item" data-from="0" data-to="180">
<li class="dropdown-item {{#next6months}} active {{/next6months}}" data-from="0" data-to="180" data-filtername="next6months">
<a href="#" aria-label="{{#str}} ariadayfilteroption, block_timeline, {{#str}} next6months, block_timeline {{/str}}{{/str}}">
{{#str}} next6months, block_timeline {{/str}}
</a>
@@ -32,12 +32,12 @@
<span data-region="caret" class="caret"></span>
</button>
<ul role="menu" class="dropdown-menu dropdown-menu-right" data-show-active-item>
<li class="dropdown-item active" data-target="#view_dates_{{uniqid}}" data-toggle="tab">
<li class="dropdown-item {{#sorttimelinedates}}active{{/sorttimelinedates}}" data-target="#view_dates_{{uniqid}}" data-toggle="tab" data-filtername="sortbydates">
<a href="#" aria-label="{{#str}} ariaviewselectoroption, block_timeline, {{#str}} sortbydates, block_timeline {{/str}}{{/str}}">
{{#str}} sortbydates, block_timeline {{/str}}
</a>
</li>
<li class="dropdown-item" data-target="#view_courses_{{uniqid}}" data-toggle="tab">
<li class="dropdown-item {{#sorttimelinecourses}}active{{/sorttimelinecourses}}" data-target="#view_courses_{{uniqid}}" data-toggle="tab" data-filtername="sortbycourses">
<a href="#" aria-label="{{#str}} ariaviewselectoroption, block_timeline, {{#str}} sortbycourses, block_timeline {{/str}}{{/str}}">
{{#str}} sortbycourses, block_timeline {{/str}}
</a>
@@ -20,15 +20,38 @@
This template renders the timeline view for the timeline block.
Example context (json):
{}
{
"midnight": 1538954668,
"coursepages": [
{}
],
"urls": {
"nocourses": "#",
"noevents": "#"
},
"sorttimelinedates": true,
"sorttimelinecourses": false,
"selectedfilter": "all",
"hasdaysoffset": true,
"hasdayslimit": false,
"nodayslimit": true,
"all": true,
"overdue": false,
"next7days": false,
"next30days": false,
"next3months": false,
"next6months": false,
"daysoffset": -14,
"dayslimit": false
}
}}
<div data-region="timeline-view">
<div class="tab-content" style="overflow: visible">
<div class="tab-pane active fade in" data-region="view-dates" id="view_dates_{{uniqid}}">
<div class="tab-pane {{#sorttimelinedates}}active in{{/sorttimelinedates}} fade" data-region="view-dates" id="view_dates_{{uniqid}}">
{{> block_timeline/view-dates }}
</div>
<div
class="tab-pane fade"
class="tab-pane {{#sorttimelinecourses}}active in{{/sorttimelinecourses}} fade"
data-region="view-courses"
data-midnight="{{midnight}}"
data-limit="2"