Proyectos de Subversion Moodle

Rev

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