Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Report builder columns sorting editor
18
 *
19
 * @module      core_reportbuilder/local/editor/sorting
20
 * @copyright   2021 David Matamoros <davidmc@moodle.com>
21
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
"use strict";
25
 
26
import $ from 'jquery';
27
import 'core/inplace_editable';
28
import Notification from 'core/notification';
29
import Pending from 'core/pending';
30
import {subscribe} from 'core/pubsub';
31
import SortableList from 'core/sortable_list';
32
import {getString} from 'core/str';
33
import {add as addToast} from 'core/toast';
34
import * as reportSelectors from 'core_reportbuilder/local/selectors';
35
import {reorderColumnSorting, toggleColumnSorting} from 'core_reportbuilder/local/repository/sorting';
36
import Templates from 'core/templates';
37
import {dispatchEvent} from 'core/event_dispatcher';
38
import * as reportEvents from 'core_reportbuilder/local/events';
39
 
40
// These constants match PHP consts SORT_ASC, SORT_DESC.
41
const SORTORDER = {
42
    ASCENDING: 4,
43
    DESCENDING: 3,
44
};
45
 
46
/**
47
 * Reload sorting settings region
48
 *
49
 * @param {Object} context
50
 * @return {Promise}
51
 */
52
const reloadSettingsSortingRegion = context => {
53
    const pendingPromise = new Pending('core_reportbuilder/sorting:reload');
54
    const settingsSortingRegion = document.querySelector(reportSelectors.regions.settingsSorting);
55
 
56
    return Templates.renderForPromise('core_reportbuilder/local/settings/sorting', {sorting: context})
57
        .then(({html, js}) => {
58
            Templates.replaceNode(settingsSortingRegion, html, js);
59
            return pendingPromise.resolve();
60
        });
61
};
62
 
63
/**
64
 * Updates column sorting
65
 *
66
 * @param {Element} reportElement
67
 * @param {Element} element
68
 * @param {Number} sortenabled
69
 * @param {Number} sortdirection
70
 * @return {Promise}
71
 */
72
const updateSorting = (reportElement, element, sortenabled, sortdirection) => {
73
    const reportId = reportElement.dataset.reportId;
74
    const listElement = element.closest('li');
75
    const columnId = listElement.dataset.columnSortId;
76
    const columnName = listElement.dataset.columnSortName;
77
 
78
    return toggleColumnSorting(reportId, columnId, sortenabled, sortdirection)
79
        .then(reloadSettingsSortingRegion)
80
        .then(() => getString('columnsortupdated', 'core_reportbuilder', columnName))
81
        .then(addToast)
82
        .then(() => {
83
            dispatchEvent(reportEvents.tableReload, {}, reportElement);
84
            return null;
85
        });
86
};
87
 
88
/**
89
 * Initialise module
90
 *
91
 * @param {Boolean} initialized Ensure we only add our listeners once
92
 */
93
export const init = (initialized) => {
94
    if (initialized) {
95
        return;
96
    }
97
 
98
    // Update sorting region each time report columns are updated (added or removed).
99
    subscribe(reportEvents.publish.reportColumnsUpdated, data => reloadSettingsSortingRegion(data)
100
        .catch(Notification.exception)
101
    );
102
 
103
    document.addEventListener('click', event => {
104
 
105
        // Enable/disable sorting on columns.
106
        const toggleSorting = event.target.closest(reportSelectors.actions.reportToggleColumnSort);
107
        if (toggleSorting) {
108
            event.preventDefault();
109
 
110
            const pendingPromise = new Pending('core_reportbuilder/sorting:toggle');
111
            const reportElement = toggleSorting.closest(reportSelectors.regions.report);
112
            const sortdirection = parseInt(toggleSorting.closest('li').dataset.columnSortDirection);
113
 
114
            updateSorting(reportElement, toggleSorting, toggleSorting.checked, sortdirection)
115
                .then(() => {
116
                    // Re-focus the toggle sorting element after reloading the region.
117
                    const toggleSortingElement = document.getElementById(toggleSorting.id);
118
                    toggleSortingElement?.focus();
119
                    return pendingPromise.resolve();
120
                })
121
                .catch(Notification.exception);
122
        }
123
 
124
        // Change column sort direction.
125
        const toggleSortDirection = event.target.closest(reportSelectors.actions.reportToggleColumnSortDirection);
126
        if (toggleSortDirection) {
127
            event.preventDefault();
128
 
129
            const pendingPromise = new Pending('core_reportbuilder/sorting:direction');
130
            const reportElement = toggleSortDirection.closest(reportSelectors.regions.report);
131
            const listElement = toggleSortDirection.closest('li');
132
            const toggleSorting = listElement.querySelector(reportSelectors.actions.reportToggleColumnSort);
133
 
134
            let sortdirection = parseInt(listElement.dataset.columnSortDirection);
135
            if (sortdirection === SORTORDER.ASCENDING) {
136
                sortdirection = SORTORDER.DESCENDING;
137
            } else if (sortdirection === SORTORDER.DESCENDING) {
138
                sortdirection = SORTORDER.ASCENDING;
139
            }
140
 
141
            updateSorting(reportElement, toggleSortDirection, toggleSorting.checked, sortdirection)
142
                .then(() => {
143
                    // Re-focus the toggle sort direction element after reloading the region.
144
                    const toggleSortDirectionElement = document.getElementById(toggleSortDirection.id);
145
                    toggleSortDirectionElement?.focus();
146
                    return pendingPromise.resolve();
147
                })
148
                .catch(Notification.exception);
149
        }
150
    });
151
 
152
    // Initialize sortable list to handle column sorting moving (note JQuery dependency, see MDL-72293 for resolution).
153
    var columnsSortingSortableList = new SortableList(`${reportSelectors.regions.settingsSorting} ul`, {isHorizontal: false});
154
    columnsSortingSortableList.getElementName = element => Promise.resolve(element.data('columnSortName'));
155
 
156
    $(document).on(SortableList.EVENTS.DROP, `${reportSelectors.regions.report} li[data-column-sort-id]`, (event, info) => {
157
        if (info.positionChanged) {
158
            const pendingPromise = new Pending('core_reportbuilder/sorting:reorder');
159
            const reportElement = event.target.closest(reportSelectors.regions.report);
160
            const columnId = info.element.data('columnSortId');
161
            const columnPosition = info.element.data('columnSortPosition');
162
 
163
            // Select target position, if moving to the end then count number of element siblings.
164
            let targetColumnSortPosition = info.targetNextElement.data('columnSortPosition') || info.element.siblings().length + 2;
165
            if (targetColumnSortPosition > columnPosition) {
166
                targetColumnSortPosition--;
167
            }
168
 
169
            // Re-order column sorting, giving drop event transition time to finish.
170
            const reorderPromise = reorderColumnSorting(reportElement.dataset.reportId, columnId, targetColumnSortPosition);
171
            Promise.all([reorderPromise, new Promise(resolve => setTimeout(resolve, 1000))])
172
                .then(([data]) => reloadSettingsSortingRegion(data))
173
                .then(() => getString('columnsortupdated', 'core_reportbuilder', info.element.data('columnSortName')))
174
                .then(addToast)
175
                .then(() => {
176
                    dispatchEvent(reportEvents.tableReload, {}, reportElement);
177
                    return pendingPromise.resolve();
178
                })
179
                .catch(Notification.exception);
180
        }
181
    });
182
};