MDL-67915 core_table: add support for hide and show of columns
authorSimey Lameze <simey@moodle.com>
Fri, 17 Apr 2020 00:33:40 +0000 (08:33 +0800)
committerSimey Lameze <simey@moodle.com>
Fri, 24 Apr 2020 10:23:34 +0000 (18:23 +0800)
12 files changed:
lib/table/amd/build/dynamic.min.js
lib/table/amd/build/dynamic.min.js.map
lib/table/amd/build/local/dynamic/repository.min.js
lib/table/amd/build/local/dynamic/repository.min.js.map
lib/table/amd/build/local/dynamic/selectors.min.js
lib/table/amd/build/local/dynamic/selectors.min.js.map
lib/table/amd/src/dynamic.js
lib/table/amd/src/local/dynamic/repository.js
lib/table/amd/src/local/dynamic/selectors.js
lib/table/classes/external/dynamic/fetch.php
lib/table/tests/external/dynamic/fetch_test.php
lib/tablelib.php

index 96cc2ca..4632a52 100644 (file)
Binary files a/lib/table/amd/build/dynamic.min.js and b/lib/table/amd/build/dynamic.min.js differ
index d457b4f..3aef14a 100644 (file)
Binary files a/lib/table/amd/build/dynamic.min.js.map and b/lib/table/amd/build/dynamic.min.js.map differ
index db1dc71..a377b54 100644 (file)
Binary files a/lib/table/amd/build/local/dynamic/repository.min.js and b/lib/table/amd/build/local/dynamic/repository.min.js differ
index d1d3f8b..1f58475 100644 (file)
Binary files a/lib/table/amd/build/local/dynamic/repository.min.js.map and b/lib/table/amd/build/local/dynamic/repository.min.js.map differ
index f4dc44a..2844c55 100644 (file)
Binary files a/lib/table/amd/build/local/dynamic/selectors.min.js and b/lib/table/amd/build/local/dynamic/selectors.min.js differ
index 73059fc..7a6ed15 100644 (file)
Binary files a/lib/table/amd/build/local/dynamic/selectors.min.js.map and b/lib/table/amd/build/local/dynamic/selectors.min.js.map differ
index c3f264f..3c87591 100644 (file)
@@ -78,6 +78,7 @@ export const refreshTableContent = tableRoot => {
             lastinitial: tableRoot.dataset.tableLastInitial,
             pageNumber: tableRoot.dataset.tablePageNumber,
             pageSize: tableRoot.dataset.tablePageSize,
+            hiddenColumns: JSON.parse(tableRoot.dataset.tableHiddenColumns),
         }
     )
     .then(data => {
@@ -97,6 +98,7 @@ export const updateTable = (tableRoot, {
     lastInitial = null,
     pageNumber = null,
     pageSize = null,
+    hiddenColumns = null,
 } = {}, refreshContent = true) => {
     checkTableIsDynamic(tableRoot);
 
@@ -128,6 +130,11 @@ export const updateTable = (tableRoot, {
         tableRoot.dataset.tableFilters = JSON.stringify(filters);
     }
 
+    // Update hidden columns.
+    if (hiddenColumns) {
+        tableRoot.dataset.tableHiddenColumns = JSON.stringify(hiddenColumns);
+    }
+
     // Refresh.
     if (refreshContent) {
         return refreshTableContent(tableRoot);
@@ -203,6 +210,34 @@ export const setFirstInitial = (tableRoot, firstInitial, refreshContent = true)
 export const setLastInitial = (tableRoot, lastInitial, refreshContent = true) =>
     updateTable(tableRoot, {lastInitial}, refreshContent);
 
+/**
+ * Hide a column in the participants table.
+ *
+ * @param {HTMLElement} tableRoot
+ * @param {String} columnToHide
+ * @param {Bool} refreshContent
+ */
+export const hideColumn = (tableRoot, columnToHide, refreshContent = true) => {
+    const hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);
+    hiddenColumns.push(columnToHide);
+
+    updateTable(tableRoot, {hiddenColumns}, refreshContent);
+};
+
+/**
+ * Make a hidden column visible in the participants table.
+ *
+ * @param {HTMLElement} tableRoot
+ * @param {String} columnToShow
+ * @param {Bool} refreshContent
+ */
+export const showColumn = (tableRoot, columnToShow, refreshContent = true) => {
+    let hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);
+    hiddenColumns = hiddenColumns.filter(columnName => columnName !== columnToShow);
+
+    updateTable(tableRoot, {hiddenColumns}, refreshContent);
+};
+
 /**
  * Set up listeners to handle table updates.
  */
@@ -247,5 +282,20 @@ export const init = () => {
 
             setPageNumber(tableRoot, pageItem.dataset.pageNumber);
         }
+
+        const hide = e.target.closest(Selectors.table.links.hide);
+        if (hide) {
+            e.preventDefault();
+
+            hideColumn(tableRoot, hide.dataset.column);
+        }
+
+        const show = e.target.closest(Selectors.table.links.show);
+        if (show) {
+            e.preventDefault();
+
+            showColumn(tableRoot, show.dataset.column);
+        }
+
     });
 };
index 9083c6f..344de98 100644 (file)
@@ -48,6 +48,7 @@ export const fetch = (component, handler, uniqueid, {
         lastinitial = null,
         pageNumber = null,
         pageSize = null,
+        hiddenColumns = {}
     } = {}
 ) => {
     return fetchMany([{
@@ -64,6 +65,7 @@ export const fetch = (component, handler, uniqueid, {
             lastinitial,
             pagenumber: pageNumber,
             pagesize: pageSize,
+            hiddencolumns: hiddenColumns,
         },
     }])[0];
 };
index 118f328..2a52d91 100644 (file)
@@ -28,6 +28,8 @@ export default {
     table: {
         links: {
             sortableColumn: 'a[data-sortable="1"]',
+            hide: 'a[data-action="hide"]',
+            show: 'a[data-action="show"]',
         },
     },
     initialsBar: {
index f49b6b4..6e117e9 100644 (file)
@@ -115,6 +115,14 @@ class fetch extends external_api {
                 VALUE_REQUIRED,
                 null
             ),
+            'hiddencolumns' => new external_multiple_structure(
+                new external_value(
+                    PARAM_ALPHANUMEXT,
+                    'Name of column',
+                    VALUE_REQUIRED,
+                    null
+                )
+            ),
         ]);
     }
 
@@ -146,7 +154,8 @@ class fetch extends external_api {
         ?string $firstinitial = null,
         ?string $lastinitial = null,
         ?int $pagenumber = null,
-        ?int $pagesize = null
+        ?int $pagesize = null,
+        ?array $hiddencolumns = null
     ) {
 
         global $PAGE;
@@ -163,6 +172,7 @@ class fetch extends external_api {
             'lastinitial' => $lastinitial,
             'pagenumber' => $pagenumber,
             'pagesize' => $pagesize,
+            'hiddencolumns' => $hiddencolumns,
         ] = self::validate_parameters(self::execute_parameters(), [
             'component' => $component,
             'handler' => $handler,
@@ -175,6 +185,7 @@ class fetch extends external_api {
             'lastinitial' => $lastinitial,
             'pagenumber' => $pagenumber,
             'pagesize' => $pagesize,
+            'hiddencolumns' => $hiddencolumns,
         ]);
 
         $tableclass = "\\{$component}\\table\\{$handler}";
@@ -221,6 +232,10 @@ class fetch extends external_api {
             $pagesize = 20;
         }
 
+        if ($hiddencolumns !== null) {
+            $instance->set_hidden_columns($hiddencolumns);
+        }
+
         $context = $instance->get_context();
         self::validate_context($context);
         $PAGE->set_url($instance->get_base_url());
index b5ae343..111b221 100644 (file)
@@ -65,7 +65,8 @@ class fetch_test extends advanced_testcase {
         $this->resetAfterTest();
 
         $this->expectException(\UnexpectedValueException::class);
-        fetch::execute("core_users", "participants", "", "email", "4", [], "1");
+        fetch::execute("core_users", "participants", "", "email", "4", [], (string)filter::JOINTYPE_ANY,
+            null, null, null, null, []);
     }
 
     /**
@@ -79,7 +80,8 @@ class fetch_test extends advanced_testcase {
         $this->expectExceptionMessage("Table handler class {$handler} not found. Please make sure that your table handler class is under the \\core_user\\table namespace.");
 
         // Tests that invalid users_participants_table class gets an exception.
-        fetch::execute("core_user", "users_participants_table", "", "email", "4", [], "1");
+        fetch::execute("core_user", "users_participants_table", "", "email", "4", [], (string)filter::JOINTYPE_ANY,
+            null, null, null, null, []);
     }
 
     /**
@@ -129,7 +131,9 @@ class fetch_test extends advanced_testcase {
         ];
 
         $participantstable = fetch::execute("core_user", "participants",
-            "user-index-participants-{$course->id}", "firstname", "4", $filter, (string)filter::JOINTYPE_ANY);
+            "user-index-participants-{$course->id}", "firstname", "4", $filter, (string)filter::JOINTYPE_ANY,
+            null, null, null, null, []);
+
         $html = $participantstable['html'];
 
         $this->assertStringContainsString($user1->email, $html);
index 33375eb..7e669a2 100644 (file)
@@ -154,6 +154,9 @@ class flexible_table {
     /** @var $filename */
     protected $filename;
 
+    /** @var array $hiddencolumns List of hidden columns. */
+    protected $hiddencolumns;
+
     /**
      * Constructor
      * @param string $uniqueid all tables have to have a unique id, this is used
@@ -511,25 +514,7 @@ class flexible_table {
             $oldprefs = $this->prefs;
         }
 
-        if (($showcol = optional_param($this->request[TABLE_VAR_SHOW], '', PARAM_ALPHANUMEXT)) &&
-                isset($this->columns[$showcol])) {
-            $this->prefs['collapse'][$showcol] = false;
-
-        } else if (($hidecol = optional_param($this->request[TABLE_VAR_HIDE], '', PARAM_ALPHANUMEXT)) &&
-                isset($this->columns[$hidecol])) {
-            $this->prefs['collapse'][$hidecol] = true;
-            if (array_key_exists($hidecol, $this->prefs['sortby'])) {
-                unset($this->prefs['sortby'][$hidecol]);
-            }
-        }
-
-        // Now, update the column attributes for collapsed columns
-        foreach (array_keys($this->columns) as $column) {
-            if (!empty($this->prefs['collapse'][$column])) {
-                $this->column_style[$column]['width'] = '10px';
-            }
-        }
-
+        $this->set_hide_show_preferences();
         $this->set_sorting_preferences();
         $this->set_initials_preferences();
 
@@ -1205,14 +1190,18 @@ class flexible_table {
         if (!empty($this->prefs['collapse'][$column])) {
             $linkattributes = array('title' => get_string('show') . ' ' . strip_tags($this->headers[$index]),
                                     'aria-expanded' => 'false',
-                                    'aria-controls' => $ariacontrols);
+                                    'aria-controls' => $ariacontrols,
+                                    'data-action' => 'show',
+                                    'data-column' => $column);
             return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_SHOW] => $column)),
                     $OUTPUT->pix_icon('t/switch_plus', get_string('show')), $linkattributes);
 
         } else if ($this->headers[$index] !== NULL) {
             $linkattributes = array('title' => get_string('hide') . ' ' . strip_tags($this->headers[$index]),
                                     'aria-expanded' => 'true',
-                                    'aria-controls' => $ariacontrols);
+                                    'aria-controls' => $ariacontrols,
+                                    'data-action' => 'hide',
+                                    'data-column' => $column);
             return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_HIDE] => $column)),
                     $OUTPUT->pix_icon('t/switch_minus', get_string('hide')), $linkattributes);
         }
@@ -1380,6 +1369,43 @@ class flexible_table {
 
     }
 
+    /**
+     * Set hide and show preferences.
+     */
+    protected function set_hide_show_preferences(): void {
+
+        if ($this->hiddencolumns !== null) {
+            $this->prefs['collapse'] = array_fill_keys(array_filter($this->hiddencolumns, function($column) {
+                return array_key_exists($column, $this->columns);
+            }), true);
+        } else {
+            if ($column = optional_param($this->request[TABLE_VAR_HIDE], '', PARAM_ALPHANUMEXT)) {
+                if (isset($this->columns[$column])) {
+                    $this->prefs['collapse'][$column] = true;
+                }
+            }
+        }
+
+        if ($column = optional_param($this->request[TABLE_VAR_SHOW], '', PARAM_ALPHANUMEXT)) {
+            unset($this->prefs['collapse'][$column]);
+        }
+
+        foreach (array_keys($this->prefs['collapse']) as $column) {
+            if (array_key_exists($column, $this->prefs['sortby'])) {
+                unset($this->prefs['sortby'][$column]);
+            }
+        }
+    }
+
+    /**
+     * Set the list of hidden columns.
+     *
+     * @param array $columns The list of hidden columns.
+     */
+    public function set_hidden_columns(array $columns): void {
+        $this->hiddencolumns = $columns;
+    }
+
     /**
      * Set the preferred table sorting attributes.
      *
@@ -1540,6 +1566,7 @@ class flexible_table {
                 'data-table-last-initial' => $this->prefs['i_last'],
                 'data-table-page-number' => $this->currpage + 1,
                 'data-table-page-size' => $this->pagesize,
+                'data-table-hidden-columns' => json_encode(array_keys($this->prefs['collapse'])),
             ]);
         }