MDL-68796 core_contentbank: Store view preferences
[moodle.git] / contentbank / amd / src / sort.js
CommitLineData
e695d9d0
BB
1// This file is part of Moodle - http://moodle.org/
2//
3// Moodle is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// Moodle is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15
16/**
17 * Content bank UI actions.
18 *
19 * @module core_contentbank/sort
20 * @package core_contentbank
21 * @copyright 2020 Bas Brands <bas@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
c393d818 25import selectors from './selectors';
e695d9d0
BB
26import {get_string as getString} from 'core/str';
27import Prefetch from 'core/prefetch';
c393d818
BB
28import Ajax from 'core/ajax';
29import Notification from 'core/notification';
e695d9d0 30
e695d9d0
BB
31/**
32 * Set up the contentbank views.
33 *
34 * @method init
35 */
36export const init = () => {
37 const contentBank = document.querySelector(selectors.regions.contentbank);
38 Prefetch.prefetchStrings('contentbank', ['sortbyx', 'sortbyxreverse', 'contentname',
39 'lastmodified', 'size', 'type']);
40 registerListenerEvents(contentBank);
41};
42
e695d9d0
BB
43/**
44 * Register contentbank related event listeners.
45 *
46 * @method registerListenerEvents
47 * @param {HTMLElement} contentBank The DOM node of the content bank
48 */
49const registerListenerEvents = (contentBank) => {
50
51 // The search.
52 const fileArea = document.querySelector(selectors.regions.filearea);
53 const shownItems = fileArea.querySelectorAll(selectors.elements.listitem);
54
55 // The view buttons.
56 const viewGrid = contentBank.querySelector(selectors.actions.viewgrid);
57 const viewList = contentBank.querySelector(selectors.actions.viewlist);
58
59 viewGrid.addEventListener('click', () => {
60 contentBank.classList.remove('view-list');
61 contentBank.classList.add('view-grid');
62 viewGrid.classList.add('active');
63 viewList.classList.remove('active');
c393d818 64 setViewListPreference(false);
e695d9d0
BB
65 });
66
67 viewList.addEventListener('click', () => {
68 contentBank.classList.remove('view-grid');
69 contentBank.classList.add('view-list');
70 viewList.classList.add('active');
71 viewGrid.classList.remove('active');
c393d818 72 setViewListPreference(true);
e695d9d0
BB
73 });
74
75 // Sort by file name alphabetical
76 const sortByName = contentBank.querySelector(selectors.actions.sortname);
77 sortByName.addEventListener('click', () => {
78 const ascending = updateSortButtons(contentBank, sortByName);
79 updateSortOrder(fileArea, shownItems, 'data-file', ascending);
80 });
81
82 // Sort by date.
83 const sortByDate = contentBank.querySelector(selectors.actions.sortdate);
84 sortByDate.addEventListener('click', () => {
85 const ascending = updateSortButtons(contentBank, sortByDate);
86 updateSortOrder(fileArea, shownItems, 'data-timemodified', ascending);
87 });
88
89 // Sort by size.
90 const sortBySize = contentBank.querySelector(selectors.actions.sortsize);
91 sortBySize.addEventListener('click', () => {
92 const ascending = updateSortButtons(contentBank, sortBySize);
93 updateSortOrder(fileArea, shownItems, 'data-bytes', ascending);
94 });
95
96 // Sort by type
97 const sortByType = contentBank.querySelector(selectors.actions.sorttype);
98 sortByType.addEventListener('click', () => {
99 const ascending = updateSortButtons(contentBank, sortByType);
100 updateSortOrder(fileArea, shownItems, 'data-type', ascending);
101 });
102};
103
c393d818
BB
104
105/**
106 * Set the contentbank user preference in list view
107 *
108 * @param {Bool} viewList view ContentBank as list.
109 * @return {Promise} Repository promise.
110 */
111const setViewListPreference = function(viewList) {
112
113 // If the given status is not hidden, the preference has to be deleted with a null value.
114 if (viewList === false) {
115 viewList = null;
116 }
117
118 const request = {
119 methodname: 'core_user_update_user_preferences',
120 args: {
121 preferences: [
122 {
123 type: 'core_contentbank_view_list',
124 value: viewList
125 }
126 ]
127 }
128 };
129
130 return Ajax.call([request])[0].catch(Notification.exception);
131};
132
e695d9d0
BB
133/**
134 * Update the sort button view.
135 *
136 * @method updateSortButtons
137 * @param {HTMLElement} contentBank The DOM node of the contentbank button
138 * @param {HTMLElement} sortButton The DOM node of the sort button
139 * @return {Bool} sort ascending
140 */
141const updateSortButtons = (contentBank, sortButton) => {
142 const sortButtons = contentBank.querySelectorAll(selectors.elements.sortbutton);
143
144 sortButtons.forEach((button) => {
145 if (button !== sortButton) {
146 button.classList.remove('dir-asc');
147 button.classList.remove('dir-desc');
148 button.classList.add('dir-none');
149
150 updateButtonTitle(button, false);
151 }
152 });
153
154 let ascending = true;
155
156 if (sortButton.classList.contains('dir-none')) {
157 sortButton.classList.remove('dir-none');
158 sortButton.classList.add('dir-asc');
159 } else if (sortButton.classList.contains('dir-asc')) {
160 sortButton.classList.remove('dir-asc');
161 sortButton.classList.add('dir-desc');
162 ascending = false;
163 } else if (sortButton.classList.contains('dir-desc')) {
164 sortButton.classList.remove('dir-desc');
165 sortButton.classList.add('dir-asc');
166 }
167
168 updateButtonTitle(sortButton, ascending);
169
170 return ascending;
171};
172
173/**
174 * Update the button title.
175 *
176 * @method updateButtonTitle
177 * @param {HTMLElement} button Button to update
178 * @param {Bool} ascending Sort direction
179 * @return {Promise} string promise
180 */
181const updateButtonTitle = (button, ascending) => {
182
183 const sortString = (ascending ? 'sortbyxreverse' : 'sortbyx');
184
185 return getString(button.dataset.string, 'contentbank')
186 .then(columnName => {
187 return getString(sortString, 'core', columnName);
188 })
189 .then(sortByString => {
190 button.setAttribute('title', sortByString);
191 return sortByString;
192 })
193 .catch();
194};
195
196/**
197 * Update the sort order of the itemlist and update the DOM
198 *
199 * @method updateSortOrder
200 * @param {HTMLElement} fileArea the Dom container for the itemlist
201 * @param {Array} itemList Nodelist of Dom elements
202 * @param {String} attribute, the attribut to sort on
203 * @param {Bool} ascending, Sort Ascending
204 */
205const updateSortOrder = (fileArea, itemList, attribute, ascending) => {
206 const sortList = [].slice.call(itemList).sort(function(a, b) {
207
208 let aa = a.getAttribute(attribute);
209 let bb = b.getAttribute(attribute);
210 if (!isNaN(aa)) {
211 aa = parseInt(aa);
212 bb = parseInt(bb);
213 }
214
215 if (ascending) {
216 return aa > bb ? 1 : -1;
217 } else {
218 return aa < bb ? 1 : -1;
219 }
220 });
cd08d856
AN
221 sortList.forEach(listItem => fileArea.appendChild(listItem));
222};