From 68c46a28d67a9a7559623f2674f7cb0a8cd432c5 Mon Sep 17 00:00:00 2001 From: Simey Lameze Date: Tue, 21 Apr 2020 08:47:51 +0800 Subject: [PATCH] MDL-68462 core_table: add support for reset table preferences --- lib/table/amd/build/dynamic.min.js | 2 +- lib/table/amd/build/dynamic.min.js.map | 2 +- .../amd/build/local/dynamic/repository.min.js | 2 +- .../build/local/dynamic/repository.min.js.map | 2 +- lib/table/amd/src/dynamic.js | 20 ++- lib/table/amd/src/local/dynamic/repository.js | 5 +- lib/table/classes/external/dynamic/fetch.php | 19 ++- lib/tablelib.php | 155 +++++++++++++----- 8 files changed, 161 insertions(+), 46 deletions(-) diff --git a/lib/table/amd/build/dynamic.min.js b/lib/table/amd/build/dynamic.min.js index 69210d83352..127cd839585 100644 --- a/lib/table/amd/build/dynamic.min.js +++ b/lib/table/amd/build/dynamic.min.js @@ -1,2 +1,2 @@ -define ("core_table/dynamic",["exports","core_table/local/dynamic/repository","core_table/local/dynamic/selectors","./local/dynamic/events"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});Object.defineProperty(a,"Events",{enumerable:!0,get:function get(){return d.default}});a.getTableFromId=a.init=a.showColumn=a.hideColumn=a.setLastInitial=a.setFirstInitial=a.setPageSize=a.setPageNumber=a.setSortOrder=a.setFilters=a.updateTable=a.refreshTableContent=void 0;c=function(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}(c);d=function(a){return a&&a.__esModule?a:{default:a}}(d);function e(a){return h(a)||g(a)||f()}function f(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function g(a){if(Symbol.iterator in Object(a)||"[object Arguments]"===Object.prototype.toString.call(a))return Array.from(a)}function h(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b.\n\n/**\n * Module to handle dynamic table features.\n *\n * @module core_table/dynamic\n * @package core_table\n * @copyright 2020 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {fetch as fetchTableData} from 'core_table/local/dynamic/repository';\nimport * as Selectors from 'core_table/local/dynamic/selectors';\nimport Events from './local/dynamic/events';\n\nlet watching = false;\n\n/**\n * Ensure that a table is a dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Bool}\n */\nconst checkTableIsDynamic = tableRoot => {\n if (!tableRoot) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n if (!tableRoot.matches(Selectors.main.region)) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n return true;\n};\n\n/**\n * Get the filterset data from a known dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Object}\n */\nconst getFiltersetFromTable = tableRoot => {\n return JSON.parse(tableRoot.dataset.tableFilters);\n};\n\n/**\n * Update the specified table based on its current values.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Promise}\n */\nexport const refreshTableContent = tableRoot => {\n const filterset = getFiltersetFromTable(tableRoot);\n\n return fetchTableData(\n tableRoot.dataset.tableComponent,\n tableRoot.dataset.tableHandler,\n tableRoot.dataset.tableUniqueid,\n {\n sortBy: tableRoot.dataset.tableSortBy,\n sortOrder: tableRoot.dataset.tableSortOrder,\n joinType: filterset.jointype,\n filters: filterset.filters,\n firstinitial: tableRoot.dataset.tableFirstInitial,\n lastinitial: tableRoot.dataset.tableLastInitial,\n pageNumber: tableRoot.dataset.tablePageNumber,\n pageSize: tableRoot.dataset.tablePageSize,\n hiddenColumns: JSON.parse(tableRoot.dataset.tableHiddenColumns),\n }\n )\n .then(data => {\n const placeholder = document.createElement('div');\n placeholder.innerHTML = data.html;\n tableRoot.replaceWith(...placeholder.childNodes);\n\n // Update the tableRoot.\n return getTableFromId(tableRoot.dataset.tableUniqueid);\n }).then(tableRoot => {\n tableRoot.dispatchEvent(new CustomEvent(Events.tableContentRefreshed, {\n bubbles: true,\n }));\n\n return tableRoot;\n });\n};\n\nexport const updateTable = (tableRoot, {\n sortBy = null,\n sortOrder = null,\n filters = null,\n firstInitial = null,\n lastInitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = null,\n} = {}, refreshContent = true) => {\n checkTableIsDynamic(tableRoot);\n\n // Update sort fields.\n if (sortBy && sortOrder) {\n tableRoot.dataset.tableSortBy = sortBy;\n tableRoot.dataset.tableSortOrder = sortOrder;\n }\n\n // Update initials.\n if (firstInitial !== null) {\n tableRoot.dataset.tableFirstInitial = firstInitial;\n }\n\n if (lastInitial !== null) {\n tableRoot.dataset.tableLastInitial = lastInitial;\n }\n\n if (pageNumber !== null) {\n tableRoot.dataset.tablePageNumber = pageNumber;\n }\n\n if (pageSize !== null) {\n tableRoot.dataset.tablePageSize = pageSize;\n }\n\n // Update filters.\n if (filters) {\n tableRoot.dataset.tableFilters = JSON.stringify(filters);\n }\n\n // Update hidden columns.\n if (hiddenColumns) {\n tableRoot.dataset.tableHiddenColumns = JSON.stringify(hiddenColumns);\n }\n\n // Refresh.\n if (refreshContent) {\n return refreshTableContent(tableRoot);\n } else {\n return Promise.resolve(tableRoot);\n }\n};\n\n/**\n * Update the specified table using the new filters.\n *\n * @param {HTMLElement} tableRoot\n * @param {Object} filters\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setFilters = (tableRoot, filters, refreshContent = true) =>\n updateTable(tableRoot, {filters}, refreshContent);\n\n/**\n * Update the sort order.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} sortBy\n * @param {Number} sortOrder\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setSortOrder = (tableRoot, sortBy, sortOrder, refreshContent = true) =>\n updateTable(tableRoot, {sortBy, sortOrder}, refreshContent);\n\n/**\n * Set the page number.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} pageNumber\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setPageNumber = (tableRoot, pageNumber, refreshContent = true) =>\n updateTable(tableRoot, {pageNumber}, refreshContent);\n\n/**\n * Set the page size.\n *\n * @param {HTMLElement} tableRoot\n * @param {Number} pageSize\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setPageSize = (tableRoot, pageSize, refreshContent = true) =>\n updateTable(tableRoot, {pageSize, pageNumber: 0}, refreshContent);\n\n/**\n * Update the first initial to show.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} firstInitial\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setFirstInitial = (tableRoot, firstInitial, refreshContent = true) =>\n updateTable(tableRoot, {firstInitial}, refreshContent);\n\n/**\n * Update the last initial to show.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} lastInitial\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setLastInitial = (tableRoot, lastInitial, refreshContent = true) =>\n updateTable(tableRoot, {lastInitial}, refreshContent);\n\n/**\n * Hide a column in the participants table.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} columnToHide\n * @param {Bool} refreshContent\n */\nexport const hideColumn = (tableRoot, columnToHide, refreshContent = true) => {\n const hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);\n hiddenColumns.push(columnToHide);\n\n updateTable(tableRoot, {hiddenColumns}, refreshContent);\n};\n\n/**\n * Make a hidden column visible in the participants table.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} columnToShow\n * @param {Bool} refreshContent\n */\nexport const showColumn = (tableRoot, columnToShow, refreshContent = true) => {\n let hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);\n hiddenColumns = hiddenColumns.filter(columnName => columnName !== columnToShow);\n\n updateTable(tableRoot, {hiddenColumns}, refreshContent);\n};\n\n/**\n * Set up listeners to handle table updates.\n */\nexport const init = () => {\n if (watching) {\n // Already watching.\n return;\n }\n watching = true;\n\n document.addEventListener('click', e => {\n const tableRoot = e.target.closest(Selectors.main.region);\n\n if (!tableRoot) {\n return;\n }\n\n const sortableLink = e.target.closest(Selectors.table.links.sortableColumn);\n if (sortableLink) {\n e.preventDefault();\n\n setSortOrder(tableRoot, sortableLink.dataset.sortby, sortableLink.dataset.sortorder);\n }\n\n const firstInitialLink = e.target.closest(Selectors.initialsBar.links.firstInitial);\n if (firstInitialLink !== null) {\n e.preventDefault();\n\n setFirstInitial(tableRoot, firstInitialLink.dataset.initial);\n }\n\n const lastInitialLink = e.target.closest(Selectors.initialsBar.links.lastInitial);\n if (lastInitialLink !== null) {\n e.preventDefault();\n\n setLastInitial(tableRoot, lastInitialLink.dataset.initial);\n }\n\n const pageItem = e.target.closest(Selectors.paginationBar.links.pageItem);\n if (pageItem) {\n e.preventDefault();\n\n setPageNumber(tableRoot, pageItem.dataset.pageNumber);\n }\n\n const hide = e.target.closest(Selectors.table.links.hide);\n if (hide) {\n e.preventDefault();\n\n hideColumn(tableRoot, hide.dataset.column);\n }\n\n const show = e.target.closest(Selectors.table.links.show);\n if (show) {\n e.preventDefault();\n\n showColumn(tableRoot, show.dataset.column);\n }\n\n });\n};\n\n/**\n * Fetch the table via its table region id.\n *\n * @param {String} tableRegionId\n * @returns {HTMLElement}\n */\nexport const getTableFromId = tableRegionId => {\n const tableRoot = document.querySelector(Selectors.main.fromRegionId(tableRegionId));\n\n\n if (!tableRoot) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n return tableRoot;\n};\n\nexport {\n Events\n};\n"],"file":"dynamic.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/dynamic.js"],"names":["watching","checkTableIsDynamic","tableRoot","Error","matches","Selectors","main","region","getFiltersetFromTable","JSON","parse","dataset","tableFilters","refreshTableContent","resetContent","filterset","tableComponent","tableHandler","tableUniqueid","sortBy","tableSortBy","sortOrder","tableSortOrder","joinType","jointype","filters","firstinitial","tableFirstInitial","lastinitial","tableLastInitial","pageNumber","tablePageNumber","pageSize","tablePageSize","hiddenColumns","tableHiddenColumns","then","data","placeholder","document","createElement","innerHTML","html","replaceWith","childNodes","getTableFromId","dispatchEvent","CustomEvent","Events","tableContentRefreshed","bubbles","updateTable","firstInitial","lastInitial","refreshContent","stringify","Promise","resolve","setFilters","setSortOrder","setPageNumber","setPageSize","setFirstInitial","setLastInitial","hideColumn","columnToHide","push","showColumn","columnToShow","filter","columnName","resetTablePreferences","init","addEventListener","e","target","closest","sortableLink","table","links","sortableColumn","preventDefault","sortby","sortorder","firstInitialLink","initialsBar","initial","lastInitialLink","pageItem","paginationBar","hide","column","show","resetTablePreferencesLink","tableRegionId","querySelector","fromRegionId"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module to handle dynamic table features.\n *\n * @module core_table/dynamic\n * @package core_table\n * @copyright 2020 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {fetch as fetchTableData} from 'core_table/local/dynamic/repository';\nimport * as Selectors from 'core_table/local/dynamic/selectors';\nimport Events from './local/dynamic/events';\n\nlet watching = false;\n\n/**\n * Ensure that a table is a dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Bool}\n */\nconst checkTableIsDynamic = tableRoot => {\n if (!tableRoot) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n if (!tableRoot.matches(Selectors.main.region)) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n return true;\n};\n\n/**\n * Get the filterset data from a known dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Object}\n */\nconst getFiltersetFromTable = tableRoot => {\n return JSON.parse(tableRoot.dataset.tableFilters);\n};\n\n/**\n * Update the specified table based on its current values.\n *\n * @param {HTMLElement} tableRoot\n * @param {Bool} resetContent\n * @returns {Promise}\n */\nexport const refreshTableContent = (tableRoot, resetContent = false) => {\n const filterset = getFiltersetFromTable(tableRoot);\n\n return fetchTableData(\n tableRoot.dataset.tableComponent,\n tableRoot.dataset.tableHandler,\n tableRoot.dataset.tableUniqueid,\n {\n sortBy: tableRoot.dataset.tableSortBy,\n sortOrder: tableRoot.dataset.tableSortOrder,\n joinType: filterset.jointype,\n filters: filterset.filters,\n firstinitial: tableRoot.dataset.tableFirstInitial,\n lastinitial: tableRoot.dataset.tableLastInitial,\n pageNumber: tableRoot.dataset.tablePageNumber,\n pageSize: tableRoot.dataset.tablePageSize,\n hiddenColumns: JSON.parse(tableRoot.dataset.tableHiddenColumns),\n },\n resetContent,\n )\n .then(data => {\n const placeholder = document.createElement('div');\n placeholder.innerHTML = data.html;\n tableRoot.replaceWith(...placeholder.childNodes);\n\n // Update the tableRoot.\n return getTableFromId(tableRoot.dataset.tableUniqueid);\n }).then(tableRoot => {\n tableRoot.dispatchEvent(new CustomEvent(Events.tableContentRefreshed, {\n bubbles: true,\n }));\n\n return tableRoot;\n });\n};\n\nexport const updateTable = (tableRoot, {\n sortBy = null,\n sortOrder = null,\n filters = null,\n firstInitial = null,\n lastInitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = null,\n} = {}, refreshContent = true) => {\n checkTableIsDynamic(tableRoot);\n\n // Update sort fields.\n if (sortBy && sortOrder) {\n tableRoot.dataset.tableSortBy = sortBy;\n tableRoot.dataset.tableSortOrder = sortOrder;\n }\n\n // Update initials.\n if (firstInitial !== null) {\n tableRoot.dataset.tableFirstInitial = firstInitial;\n }\n\n if (lastInitial !== null) {\n tableRoot.dataset.tableLastInitial = lastInitial;\n }\n\n if (pageNumber !== null) {\n tableRoot.dataset.tablePageNumber = pageNumber;\n }\n\n if (pageSize !== null) {\n tableRoot.dataset.tablePageSize = pageSize;\n }\n\n // Update filters.\n if (filters) {\n tableRoot.dataset.tableFilters = JSON.stringify(filters);\n }\n\n // Update hidden columns.\n if (hiddenColumns) {\n tableRoot.dataset.tableHiddenColumns = JSON.stringify(hiddenColumns);\n }\n\n // Refresh.\n if (refreshContent) {\n return refreshTableContent(tableRoot);\n } else {\n return Promise.resolve(tableRoot);\n }\n};\n\n/**\n * Update the specified table using the new filters.\n *\n * @param {HTMLElement} tableRoot\n * @param {Object} filters\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setFilters = (tableRoot, filters, refreshContent = true) =>\n updateTable(tableRoot, {filters}, refreshContent);\n\n/**\n * Update the sort order.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} sortBy\n * @param {Number} sortOrder\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setSortOrder = (tableRoot, sortBy, sortOrder, refreshContent = true) =>\n updateTable(tableRoot, {sortBy, sortOrder}, refreshContent);\n\n/**\n * Set the page number.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} pageNumber\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setPageNumber = (tableRoot, pageNumber, refreshContent = true) =>\n updateTable(tableRoot, {pageNumber}, refreshContent);\n\n/**\n * Set the page size.\n *\n * @param {HTMLElement} tableRoot\n * @param {Number} pageSize\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setPageSize = (tableRoot, pageSize, refreshContent = true) =>\n updateTable(tableRoot, {pageSize, pageNumber: 0}, refreshContent);\n\n/**\n * Update the first initial to show.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} firstInitial\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setFirstInitial = (tableRoot, firstInitial, refreshContent = true) =>\n updateTable(tableRoot, {firstInitial}, refreshContent);\n\n/**\n * Update the last initial to show.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} lastInitial\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setLastInitial = (tableRoot, lastInitial, refreshContent = true) =>\n updateTable(tableRoot, {lastInitial}, refreshContent);\n\n/**\n * Hide a column in the participants table.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} columnToHide\n * @param {Bool} refreshContent\n */\nexport const hideColumn = (tableRoot, columnToHide, refreshContent = true) => {\n const hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);\n hiddenColumns.push(columnToHide);\n\n updateTable(tableRoot, {hiddenColumns}, refreshContent);\n};\n\n/**\n * Make a hidden column visible in the participants table.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} columnToShow\n * @param {Bool} refreshContent\n */\nexport const showColumn = (tableRoot, columnToShow, refreshContent = true) => {\n let hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);\n hiddenColumns = hiddenColumns.filter(columnName => columnName !== columnToShow);\n\n updateTable(tableRoot, {hiddenColumns}, refreshContent);\n};\n\n/**\n * Reset table preferences.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Promise}\n */\nconst resetTablePreferences = tableRoot => refreshTableContent(tableRoot, true);\n\n/**\n * Set up listeners to handle table updates.\n */\nexport const init = () => {\n if (watching) {\n // Already watching.\n return;\n }\n watching = true;\n\n document.addEventListener('click', e => {\n const tableRoot = e.target.closest(Selectors.main.region);\n\n if (!tableRoot) {\n return;\n }\n\n const sortableLink = e.target.closest(Selectors.table.links.sortableColumn);\n if (sortableLink) {\n e.preventDefault();\n\n setSortOrder(tableRoot, sortableLink.dataset.sortby, sortableLink.dataset.sortorder);\n }\n\n const firstInitialLink = e.target.closest(Selectors.initialsBar.links.firstInitial);\n if (firstInitialLink !== null) {\n e.preventDefault();\n\n setFirstInitial(tableRoot, firstInitialLink.dataset.initial);\n }\n\n const lastInitialLink = e.target.closest(Selectors.initialsBar.links.lastInitial);\n if (lastInitialLink !== null) {\n e.preventDefault();\n\n setLastInitial(tableRoot, lastInitialLink.dataset.initial);\n }\n\n const pageItem = e.target.closest(Selectors.paginationBar.links.pageItem);\n if (pageItem) {\n e.preventDefault();\n\n setPageNumber(tableRoot, pageItem.dataset.pageNumber);\n }\n\n const hide = e.target.closest(Selectors.table.links.hide);\n if (hide) {\n e.preventDefault();\n\n hideColumn(tableRoot, hide.dataset.column);\n }\n\n const show = e.target.closest(Selectors.table.links.show);\n if (show) {\n e.preventDefault();\n\n showColumn(tableRoot, show.dataset.column);\n }\n\n const resetTablePreferencesLink = e.target.closest('.resettable a');\n if (resetTablePreferencesLink) {\n e.preventDefault();\n\n resetTablePreferences(tableRoot);\n }\n });\n};\n\n/**\n * Fetch the table via its table region id.\n *\n * @param {String} tableRegionId\n * @returns {HTMLElement}\n */\nexport const getTableFromId = tableRegionId => {\n const tableRoot = document.querySelector(Selectors.main.fromRegionId(tableRegionId));\n\n\n if (!tableRoot) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n return tableRoot;\n};\n\nexport {\n Events\n};\n"],"file":"dynamic.min.js"} \ No newline at end of file diff --git a/lib/table/amd/build/local/dynamic/repository.min.js b/lib/table/amd/build/local/dynamic/repository.min.js index a377b54c266..ec438f14f75 100644 --- a/lib/table/amd/build/local/dynamic/repository.min.js +++ b/lib/table/amd/build/local/dynamic/repository.min.js @@ -1,2 +1,2 @@ -define ("core_table/local/dynamic/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.fetch=void 0;a.fetch=function fetch(a,c,d){var e=3.\n\n/**\n * A javascript module to handle calendar ajax actions.\n *\n * @module core_calendar/repository\n * @class repository\n * @package core_calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * Fetch table view.\n *\n * @method fetch\n * @param {String} component The component\n * @param {String} handler The name of the handler\n * @param {String} uniqueid The unique id of the table\n * @param {Object} filters The filters to apply when searching\n * @param {String} firstinitial The first name initial to filter on\n * @param {String} lastinitial The last name initial to filter on\n * @param {String} pageNumber The page number\n * @param {Number} pageSize The page size\n * @param {Number} params parameters to request table\n * @return {Promise} Resolved with requested table view\n */\nexport const fetch = (component, handler, uniqueid, {\n sortBy = null,\n sortOrder = null,\n joinType = null,\n filters = {},\n firstinitial = null,\n lastinitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = {}\n } = {}\n) => {\n return fetchMany([{\n methodname: `core_table_dynamic_fetch`,\n args: {\n component,\n handler,\n uniqueid,\n sortby: sortBy,\n sortorder: sortOrder,\n jointype: joinType,\n filters,\n firstinitial,\n lastinitial,\n pagenumber: pageNumber,\n pagesize: pageSize,\n hiddencolumns: hiddenColumns,\n },\n }])[0];\n};\n"],"file":"repository.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/dynamic/repository.js"],"names":["fetch","component","handler","uniqueid","sortBy","sortOrder","joinType","filters","firstinitial","lastinitial","pageNumber","pageSize","hiddenColumns","resetPreferences","methodname","args","sortby","sortorder","jointype","pagenumber","pagesize","hiddencolumns","resetpreferences"],"mappings":"yKA0CqB,QAARA,CAAAA,KAAQ,CAACC,CAAD,CAAYC,CAAZ,CAAqBC,CAArB,CAUoB,8DAAjC,EAAiC,KATjCC,MASiC,CATjCA,CASiC,YATxB,IASwB,OARjCC,SAQiC,CARjCA,CAQiC,YARrB,IAQqB,OAPjCC,QAOiC,CAPjCA,CAOiC,YAPtB,IAOsB,OANjCC,OAMiC,CANjCA,CAMiC,YANvB,EAMuB,OALjCC,YAKiC,CALjCA,CAKiC,YALlB,IAKkB,OAJjCC,WAIiC,CAJjCA,CAIiC,YAJnB,IAImB,OAHjCC,UAGiC,CAHjCA,CAGiC,YAHpB,IAGoB,OAFjCC,QAEiC,CAFjCA,CAEiC,YAFtB,IAEsB,OADjCC,aACiC,CADjCA,CACiC,YADjB,EACiB,GAA7BC,CAA6B,2DACrC,MAAO,WAAU,CAAC,CACdC,UAAU,2BADI,CAEdC,IAAI,CAAE,CACFd,SAAS,CAATA,CADE,CAEFC,OAAO,CAAPA,CAFE,CAGFC,QAAQ,CAARA,CAHE,CAIFa,MAAM,CAAEZ,CAJN,CAKFa,SAAS,CAAEZ,CALT,CAMFa,QAAQ,CAAEZ,CANR,CAOFC,OAAO,CAAPA,CAPE,CAQFC,YAAY,CAAZA,CARE,CASFC,WAAW,CAAXA,CATE,CAUFU,UAAU,CAAET,CAVV,CAWFU,QAAQ,CAAET,CAXR,CAYFU,aAAa,CAAET,CAZb,CAaFU,gBAAgB,CAAET,CAbhB,CAFQ,CAAD,CAAV,EAiBH,CAjBG,CAkBV,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle calendar ajax actions.\n *\n * @module core_calendar/repository\n * @class repository\n * @package core_calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * Fetch table view.\n *\n * @method fetch\n * @param {String} component The component\n * @param {String} handler The name of the handler\n * @param {String} uniqueid The unique id of the table\n * @param {Object} filters The filters to apply when searching\n * @param {String} firstinitial The first name initial to filter on\n * @param {String} lastinitial The last name initial to filter on\n * @param {String} pageNumber The page number\n * @param {Number} pageSize The page size\n * @param {Number} params parameters to request table\n * @param {Bool} resetPreferences\n * @return {Promise} Resolved with requested table view\n */\nexport const fetch = (component, handler, uniqueid, {\n sortBy = null,\n sortOrder = null,\n joinType = null,\n filters = {},\n firstinitial = null,\n lastinitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = {}\n } = {}, resetPreferences = false) => {\n return fetchMany([{\n methodname: `core_table_dynamic_fetch`,\n args: {\n component,\n handler,\n uniqueid,\n sortby: sortBy,\n sortorder: sortOrder,\n jointype: joinType,\n filters,\n firstinitial,\n lastinitial,\n pagenumber: pageNumber,\n pagesize: pageSize,\n hiddencolumns: hiddenColumns,\n resetpreferences: resetPreferences\n },\n }])[0];\n};\n"],"file":"repository.min.js"} \ No newline at end of file diff --git a/lib/table/amd/src/dynamic.js b/lib/table/amd/src/dynamic.js index aa1d030137b..18e35fbb91c 100644 --- a/lib/table/amd/src/dynamic.js +++ b/lib/table/amd/src/dynamic.js @@ -61,9 +61,10 @@ const getFiltersetFromTable = tableRoot => { * Update the specified table based on its current values. * * @param {HTMLElement} tableRoot + * @param {Bool} resetContent * @returns {Promise} */ -export const refreshTableContent = tableRoot => { +export const refreshTableContent = (tableRoot, resetContent = false) => { const filterset = getFiltersetFromTable(tableRoot); return fetchTableData( @@ -80,7 +81,8 @@ export const refreshTableContent = tableRoot => { pageNumber: tableRoot.dataset.tablePageNumber, pageSize: tableRoot.dataset.tablePageSize, hiddenColumns: JSON.parse(tableRoot.dataset.tableHiddenColumns), - } + }, + resetContent, ) .then(data => { const placeholder = document.createElement('div'); @@ -246,6 +248,14 @@ export const showColumn = (tableRoot, columnToShow, refreshContent = true) => { updateTable(tableRoot, {hiddenColumns}, refreshContent); }; +/** + * Reset table preferences. + * + * @param {HTMLElement} tableRoot + * @returns {Promise} + */ +const resetTablePreferences = tableRoot => refreshTableContent(tableRoot, true); + /** * Set up listeners to handle table updates. */ @@ -305,6 +315,12 @@ export const init = () => { showColumn(tableRoot, show.dataset.column); } + const resetTablePreferencesLink = e.target.closest('.resettable a'); + if (resetTablePreferencesLink) { + e.preventDefault(); + + resetTablePreferences(tableRoot); + } }); }; diff --git a/lib/table/amd/src/local/dynamic/repository.js b/lib/table/amd/src/local/dynamic/repository.js index 344de98e171..a8e61416753 100644 --- a/lib/table/amd/src/local/dynamic/repository.js +++ b/lib/table/amd/src/local/dynamic/repository.js @@ -37,6 +37,7 @@ import {call as fetchMany} from 'core/ajax'; * @param {String} pageNumber The page number * @param {Number} pageSize The page size * @param {Number} params parameters to request table + * @param {Bool} resetPreferences * @return {Promise} Resolved with requested table view */ export const fetch = (component, handler, uniqueid, { @@ -49,8 +50,7 @@ export const fetch = (component, handler, uniqueid, { pageNumber = null, pageSize = null, hiddenColumns = {} - } = {} -) => { + } = {}, resetPreferences = false) => { return fetchMany([{ methodname: `core_table_dynamic_fetch`, args: { @@ -66,6 +66,7 @@ export const fetch = (component, handler, uniqueid, { pagenumber: pageNumber, pagesize: pageSize, hiddencolumns: hiddenColumns, + resetpreferences: resetPreferences }, }])[0]; }; diff --git a/lib/table/classes/external/dynamic/fetch.php b/lib/table/classes/external/dynamic/fetch.php index 890efb58706..15b95835294 100644 --- a/lib/table/classes/external/dynamic/fetch.php +++ b/lib/table/classes/external/dynamic/fetch.php @@ -123,6 +123,12 @@ class fetch extends external_api { null ) ), + 'resetpreferences' => new external_value( + PARAM_BOOL, + 'Whether the table preferences should be reset', + VALUE_REQUIRED, + null + ), ]); } @@ -140,6 +146,8 @@ class fetch extends external_api { * @param string $lastinitial The last name initial to filter on * @param int $pagenumber The page number. * @param int $pagesize The number of records. + * @param string $jointype The join type. + * @param bool $resetpreferences Whether it is resetting table preferences or not. * * @return array */ @@ -155,7 +163,8 @@ class fetch extends external_api { ?string $lastinitial = null, ?int $pagenumber = null, ?int $pagesize = null, - ?array $hiddencolumns = null + ?array $hiddencolumns = null, + ?bool $resetpreferences = null ) { global $PAGE; @@ -173,6 +182,7 @@ class fetch extends external_api { 'pagenumber' => $pagenumber, 'pagesize' => $pagesize, 'hiddencolumns' => $hiddencolumns, + 'resetpreferences' => $resetpreferences, ] = self::validate_parameters(self::execute_parameters(), [ 'component' => $component, 'handler' => $handler, @@ -186,6 +196,7 @@ class fetch extends external_api { 'pagenumber' => $pagenumber, 'pagesize' => $pagesize, 'hiddencolumns' => $hiddencolumns, + 'resetpreferences' => $resetpreferences, ]); $tableclass = "\\{$component}\\table\\{$handler}"; @@ -238,6 +249,12 @@ class fetch extends external_api { $instance->set_hidden_columns($hiddencolumns); } + if ($resetpreferences === true) { + $instance->mark_table_to_reset(); + } + + $PAGE->set_url($instance->baseurl); + ob_start(); $instance->out($pagesize, true); $tablehtml = ob_get_contents(); diff --git a/lib/tablelib.php b/lib/tablelib.php index 55a83c2c719..8a131644527 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -158,6 +158,9 @@ class flexible_table { /** @var array $hiddencolumns List of hidden columns. */ protected $hiddencolumns; + /** @var $resetting bool Whether the table preferences is resetting. */ + protected $resetting; + /** * @var filterset The currently applied filerset * This is required for dynamic tables, but can be used by other tables too if desired. @@ -485,6 +488,26 @@ class flexible_table { $this->helpforheaders = $helpicons; } + /** + * Mark the table preferences to be reset. + */ + public function mark_table_to_reset(): void { + $this->resetting = true; + } + + /** + * Is the table marked for reset preferences? + * + * @return bool True if the table is marked to reset, false otherwise. + */ + protected function is_resetting_preferences(): bool { + if ($this->resetting === null) { + $this->resetting = optional_param($this->request[TABLE_VAR_RESET], false, PARAM_BOOL); + } + + return $this->resetting; +} + /** * Must be called after table is defined. Use methods above first. Cannot * use functions below till after calling this method. @@ -497,43 +520,7 @@ class flexible_table { return false; } - // Load any existing user preferences. - if ($this->persistent) { - $this->prefs = json_decode(get_user_preferences('flextable_' . $this->uniqueid), true); - $oldprefs = $this->prefs; - } else if (isset($SESSION->flextable[$this->uniqueid])) { - $this->prefs = $SESSION->flextable[$this->uniqueid]; - $oldprefs = $this->prefs; - } - - // Set up default preferences if needed. - if (!$this->prefs or optional_param($this->request[TABLE_VAR_RESET], false, PARAM_BOOL)) { - $this->prefs = array( - 'collapse' => array(), - 'sortby' => array(), - 'i_first' => '', - 'i_last' => '', - 'textsort' => $this->column_textsort, - ); - } - - if (!isset($oldprefs)) { - $oldprefs = $this->prefs; - } - - $this->set_hide_show_preferences(); - $this->set_sorting_preferences(); - $this->set_initials_preferences(); - - // Save user preferences if they have changed. - if ($this->prefs != $oldprefs) { - if ($this->persistent) { - set_user_preference('flextable_' . $this->uniqueid, json_encode($this->prefs)); - } else { - $SESSION->flextable[$this->uniqueid] = $this->prefs; - } - } - unset($oldprefs); + $this->initialise_table_preferences(); if (empty($this->baseurl)) { debugging('You should set baseurl when using flexible_table.'); @@ -1413,6 +1400,100 @@ class flexible_table { $this->hiddencolumns = $columns; } + /** + * Initialise table preferences. + */ + protected function initialise_table_preferences(): void { + + // Load any existing user preferences. + if ($this->persistent) { + $this->prefs = json_decode(get_user_preferences('flextable_' . $this->uniqueid), true); + $oldprefs = $this->prefs; + } else if (isset($SESSION->flextable[$this->uniqueid])) { + $this->prefs = $SESSION->flextable[$this->uniqueid]; + $oldprefs = $this->prefs; + } + + // Set up default preferences if needed. + if (!$this->prefs || $this->is_resetting_preferences()) { + $this->prefs = [ + 'collapse' => [], + 'sortby' => [], + 'i_first' => '', + 'i_last' => '', + 'textsort' => $this->column_textsort, + ]; + } + + if (!isset($oldprefs)) { + $oldprefs = $this->prefs; + } + + // Save user preferences if they have changed. + if ($this->is_resetting_preferences()) { + $this->sortorder = null; + $this->sortby = null; + $this->ifirst = null; + $this->ilast = null; + } + + 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'; + } + } + + // 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_sorting_preferences(); + $this->set_initials_preferences(); + + if (empty($this->baseurl)) { + debugging('You should set baseurl when using flexible_table.'); + global $PAGE; + $this->baseurl = $PAGE->url; + } + + if ($this->currpage == null) { + $this->currpage = optional_param($this->request[TABLE_VAR_PAGE], 0, PARAM_INT); + } + + $this->save_preferences($oldprefs); + } + + /** + * Save preferences. + * + * @param array $oldprefs Old preferences to compare against. + */ + protected function save_preferences($oldprefs): void { + if ($this->prefs != $oldprefs) { + if ($this->persistent) { + set_user_preference('flextable_' . $this->uniqueid, json_encode($this->prefs)); + } else { + $SESSION->flextable[$this->uniqueid] = $this->prefs; + } + } + unset($oldprefs); + } + /** * Set the preferred table sorting attributes. *