MDL-68796 core_contentbank: Store view preferences
authorBas Brands <bas@moodle.com>
Thu, 21 May 2020 14:53:12 +0000 (16:53 +0200)
committerBas Brands <bas@moodle.com>
Wed, 27 May 2020 15:27:23 +0000 (17:27 +0200)
includes privacy export, privacy unit test

12 files changed:
contentbank/amd/build/sort.min.js
contentbank/amd/build/sort.min.js.map
contentbank/amd/src/sort.js
contentbank/classes/output/bankcontent.php
contentbank/classes/privacy/provider.php
contentbank/lib.php [new file with mode: 0644]
contentbank/templates/bankcontent.mustache
contentbank/templates/bankcontent/toolbar.mustache
contentbank/tests/behat/view_preferences.feature [new file with mode: 0644]
contentbank/tests/privacy_test.php
lang/en/contentbank.php
lib/classes/user.php

index 5d0babf..bd655b7 100644 (file)
Binary files a/contentbank/amd/build/sort.min.js and b/contentbank/amd/build/sort.min.js differ
index 4609a9e..663a438 100644 (file)
Binary files a/contentbank/amd/build/sort.min.js.map and b/contentbank/amd/build/sort.min.js.map differ
index bfa61c8..24f4f79 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-import selectors from 'core_contentbank/selectors';
+import selectors from './selectors';
 import {get_string as getString} from 'core/str';
 import Prefetch from 'core/prefetch';
+import Ajax from 'core/ajax';
+import Notification from 'core/notification';
 
 /**
  * Set up the contentbank views.
@@ -59,6 +61,7 @@ const registerListenerEvents = (contentBank) => {
         contentBank.classList.add('view-grid');
         viewGrid.classList.add('active');
         viewList.classList.remove('active');
+        setViewListPreference(false);
     });
 
     viewList.addEventListener('click', () => {
@@ -66,6 +69,7 @@ const registerListenerEvents = (contentBank) => {
         contentBank.classList.add('view-list');
         viewList.classList.add('active');
         viewGrid.classList.remove('active');
+        setViewListPreference(true);
     });
 
     // Sort by file name alphabetical
@@ -97,6 +101,35 @@ const registerListenerEvents = (contentBank) => {
     });
 };
 
+
+/**
+ * Set the contentbank user preference in list view
+ *
+ * @param  {Bool} viewList view ContentBank as list.
+ * @return {Promise} Repository promise.
+ */
+const setViewListPreference = function(viewList) {
+
+    // If the given status is not hidden, the preference has to be deleted with a null value.
+    if (viewList === false) {
+        viewList = null;
+    }
+
+    const request = {
+        methodname: 'core_user_update_user_preferences',
+        args: {
+            preferences: [
+                {
+                    type: 'core_contentbank_view_list',
+                    value: viewList
+                }
+            ]
+        }
+    };
+
+    return Ajax.call([request])[0].catch(Notification.exception);
+};
+
 /**
  * Update the sort button view.
  *
index 6574b04..5ac92e9 100644 (file)
@@ -97,6 +97,7 @@ class bankcontent implements renderable, templatable {
                 'type' => $mimetype
             );
         }
+        $data->viewlist = get_user_preferences('core_contentbank_view_list');
         $data->contents = $contentdata;
         $data->tools = $this->toolbar;
         return $data;
index d654ab3..c0c49c5 100644 (file)
@@ -44,7 +44,8 @@ use context_course;
 class provider implements
     \core_privacy\local\metadata\provider,
     \core_privacy\local\request\core_userlist_provider,
-    \core_privacy\local\request\plugin\provider {
+    \core_privacy\local\request\plugin\provider,
+    \core_privacy\local\request\user_preference_provider {
 
     /**
      * Returns meta data about this system.
@@ -65,6 +66,26 @@ class provider implements
         return $collection;
     }
 
+    /**
+     * Export all user preferences for the contentbank
+     *
+     * @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('core_contentbank_view_list', null, $userid);
+        if (isset($preference)) {
+            writer::export_user_preference(
+                    'core_contentbank',
+                    'core_contentbank_view_list',
+                    $preference,
+                    get_string('privacy:request:preference:set', 'core_contentbank', (object) [
+                            'name' => 'core_contentbank_view_list',
+                            'value' => $preference,
+                    ])
+            );
+        }
+    }
+
     /**
      * Get the list of contexts that contain user information for the specified user.
      *
diff --git a/contentbank/lib.php b/contentbank/lib.php
new file mode 100644 (file)
index 0000000..e709df7
--- /dev/null
@@ -0,0 +1,39 @@
+<?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 contentbank
+ *
+ * @package   core_contentbank
+ * @copyright 2020 Bas Brands
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Get the current user preferences that are available
+ *
+ * @return Array preferences configuration
+ */
+function core_contentbank_user_preferences() {
+    return [
+        'core_contentbank_view_list' => [
+            'choices' => array(0, 1),
+            'type' => PARAM_INT,
+            'null' => NULL_NOT_ALLOWED,
+            'default' => 'none'
+        ],
+    ];
+}
index 0826a65..aaa3857 100644 (file)
@@ -48,7 +48,8 @@
     }
 
 }}
-<div class="content-bank-container view-grid" data-region="contentbank">
+<div class="content-bank-container {{#viewlist}}view-list{{/viewlist}} {{^viewlist}}view-grid{{/viewlist}}"
+data-region="contentbank">
     <div class="d-flex justify-content-between flex-column flex-sm-row">
         <div class="cb-search-container mb-2">
             {{>core_contentbank/bankcontent/search}}
index 04c762a..76fe087 100644 (file)
         {{#pix}} {{{ icon }}} {{/pix}} {{{ name }}}
     </a>
 {{/tools}}
-<button class="icon-no-margin btn btn-secondary active ml-2"
+<button class="icon-no-margin btn btn-secondary {{^viewlist}}active{{/viewlist}} ml-2"
 title="{{#str}}  displayicons, contentbank  {{/str}}"
 data-action="viewgrid">
     {{#pix}}a/view_icon_active, core, {{#str}} displayicons, contentbank {{/str}} {{/pix}}
 </button>
-<button class="icon-no-margin btn btn-secondary"
+<button class="icon-no-margin btn btn-secondary {{#viewlist}}active{{/viewlist}}"
 title="{{#str}} displaydetails, contentbank {{/str}}"
 data-action="viewlist">
     {{#pix}}t/viewdetails, core, {{#str}} displaydetails, contentbank {{/str}} {{/pix}}
diff --git a/contentbank/tests/behat/view_preferences.feature b/contentbank/tests/behat/view_preferences.feature
new file mode 100644 (file)
index 0000000..a5d9911
--- /dev/null
@@ -0,0 +1,28 @@
+@core @core_contentbank @contentbank_h5p @javascript
+Feature: Store the content bank view preference
+  In order to consistantly view the content bank in icons or details view
+  As an admin
+  I need to be able to store my view preference
+
+  Background:
+    Given the following "contentbank content" exist:
+        | contextlevel | reference | contenttype       | user  | contentname          |
+        | System       |           | contenttype_h5p   | admin | filltheblanks.h5p    |
+        | System       |           | contenttype_h5p   | admin | mathsbook.h5p        |
+
+  Scenario: Admins can order content in the content bank
+    Given I log in as "admin"
+    And I am on site homepage
+    And I turn editing mode on
+    And I add the "Navigation" block if not present
+    And I expand "Site pages" node
+    And I click on "Content bank" "link"
+    When I click on "Display contentbank with file details" "button"
+    And I should see "Last modified"
+    And I follow "filltheblanks.h5p"
+    And I click on "Content bank" "link"
+    And I should see "Last modified"
+    And I click on "Display contentbank with icons" "button"
+    And I follow "filltheblanks.h5p"
+    And I click on "Content bank" "link"
+    And I should not see "Last modified"
index e737117..3717d40 100644 (file)
@@ -29,6 +29,7 @@ use stdClass;
 use context_system;
 use context_coursecat;
 use context_course;
+use context_user;
 use core_contentbank\privacy\provider;
 use core_privacy\local\request\approved_contextlist;
 use core_privacy\local\request\writer;
@@ -361,4 +362,50 @@ class core_contentbank_privacy_testcase extends provider_testcase {
 
         return $scenario;
     }
+
+    /**
+     * Ensure that export_user_preferences returns no data if the user has not visited any content bank.
+     */
+    public function test_export_user_preferences_no_pref() {
+        global $DB;
+
+        $this->resetAfterTest();
+        $user = $this->getDataGenerator()->create_user();
+        $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
+        $this->getDataGenerator()->role_assign($managerroleid, $user->id);
+
+        provider::export_user_preferences($user->id);
+        $writer = writer::with_context(context_system::instance());
+        $this->assertFalse($writer->has_any_data());
+    }
+
+    /**
+     * Test for provider::test_export_user_preferences().
+     */
+    public function test_export_user_preferences() {
+        global $DB;
+
+        // Test setup.
+        $this->resetAfterTest(true);
+        $user = $this->getDataGenerator()->create_user();
+        $this->setUser($user);
+
+        set_user_preference('core_contentbank_view_list', 1);
+        // Test the user preferences export contains 1 user preference record for the User.
+        provider::export_user_preferences($user->id);
+        $contextuser = context_user::instance($user->id);
+        $writer = writer::with_context($contextuser);
+        $this->assertTrue($writer->has_any_data());
+
+        $prefs = $writer->get_user_preferences('core_contentbank');
+        $this->assertCount(1, (array) $prefs);
+        $this->assertEquals(1, $prefs->core_contentbank_view_list->value);
+        $this->assertEquals(
+                get_string('privacy:request:preference:set', 'core_contentbank', (object) [
+                        'name' => 'core_contentbank_view_list',
+                        'value' => $prefs->core_contentbank_view_list->value,
+                ]),
+                $prefs->core_contentbank_view_list->description
+        );
+    }
 }
index 55108d3..f66a9fd 100644 (file)
@@ -55,6 +55,7 @@ $string['privacy:metadata:content:usercreated'] = 'The user has created the cont
 $string['privacy:metadata:content:usermodified'] = 'The last user who modified the content.';
 $string['privacy:metadata:contentbankcontent'] = 'Stores the content of the content bank.';
 $string['privacy:metadata:userid'] = 'The ID of the user creating or modifying content bank content.';
+$string['privacy:request:preference:set'] = 'The value of the setting \'{$a->name}\' was \'{$a->value}\'';
 $string['rename'] = 'Rename';
 $string['renamecontent'] = 'Rename content';
 $string['searchcontentbankbyname'] = 'Search for content by name';
index 40d99ac..7013287 100644 (file)
@@ -997,7 +997,7 @@ class core_user {
         // Core components that may want to define their preferences.
         // List of core components implementing callback is hardcoded here for performance reasons.
         // TODO MDL-58184 cache list of core components implementing a function.
-        $corecomponents = ['core_message', 'core_calendar'];
+        $corecomponents = ['core_message', 'core_calendar', 'core_contentbank'];
         foreach ($corecomponents as $component) {
             if (($pluginpreferences = component_callback($component, 'user_preferences')) && is_array($pluginpreferences)) {
                 $preferences += $pluginpreferences;