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
 * Module for auto-linking glossary entries.
18
 *
19
 * @module     filter_glossary/autolinker
20
 * @copyright  2023 Mihail Geshoski <mihail@moodle.com>
21
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
import Ajax from 'core/ajax';
25
import ModalCancel from "core/modal_cancel";
26
import Templates from 'core/templates';
27
import {getString} from 'core/str';
28
 
29
/** @constant {Object} The object containing the relevant selectors. */
30
const Selectors = {
31
    glossaryEntryAutoLink: 'a.glossary.autolink.concept',
32
};
33
 
34
/**
35
 * Register the event listeners for the glossary entry auto-linker.
36
 *
37
 * @return {void}
38
 */
39
const registerEventListeners = () => {
40
    document.addEventListener('click', async(e) => {
41
        const glossaryEntryAutoLink = e.target.closest(Selectors.glossaryEntryAutoLink);
42
        if (glossaryEntryAutoLink) {
43
            e.preventDefault();
44
            const entryId = glossaryEntryAutoLink.dataset.entryid;
45
            await showGlossaryEntry(entryId);
46
            await glossaryEntryViewed(entryId);
47
        }
48
    });
49
};
50
 
51
/**
52
 * Show the linked glossary entry in a modal.
53
 *
54
 * @method showGlossaryEntry
55
 * @param {int} entryId The id of the linked glossary entry.
56
 * @returns {Promise} The modal promise.
57
 */
58
const showGlossaryEntry = async(entryId) => {
59
    const entryData = await fetchGlossaryEntry(entryId);
60
    // Obtain the HTML and JS used for rendering the auto-linked glossary entry.
61
    const {html, js} = await Templates.renderForPromise('filter_glossary/linked_glossary_entry', {
62
        definition: entryData.entry.definition,
63
        taglistdata: await generateTagListData(entryData.entry.tags),
64
        hasattachments: Boolean(entryData.entry.attachment),
65
        attachments: entryData.entry.attachments
66
    });
67
    // Create the modal.
68
    const modal = await ModalCancel.create({
69
        title: entryData.entry.concept,
70
        body: html,
71
        isVerticallyCentered: true,
72
        buttons: {
73
            cancel: await getString('ok')
74
        }
75
    });
76
    // Execute the JS code returned from the template once the modal is created.
77
    Templates.runTemplateJS(js);
78
    // Display the modal.
79
    modal.show();
80
 
81
    return modal;
82
};
83
 
84
/**
85
 * Fetch the linked glossary entry.
86
 *
87
 * @method fetchGlossaryEntry
88
 * @param {int} entryId The id of the linked glossary entry.
89
 * @returns {Promise} The glossary entry promise.
90
 */
91
const fetchGlossaryEntry = (entryId) => {
92
    const request = {
93
        methodname: 'mod_glossary_get_entry_by_id',
94
        args: {
95
            id: entryId,
96
        },
97
    };
98
    return Ajax.call([request])[0];
99
};
100
 
101
/**
102
 * Notify that the linked glossary entry was viewed.
103
 *
104
 * @method glossaryEntryViewed
105
 * @param {int} entryId The id of the linked glossary entry.
106
 * @returns {Promise} The promise object.
107
 */
108
const glossaryEntryViewed = (entryId) => {
109
    const request = {
110
        methodname: 'mod_glossary_view_entry',
111
        args: {
112
            id: entryId,
113
        },
114
    };
115
    return Ajax.call([request])[0];
116
};
117
 
118
/**
119
 * Generates an object that contains the data required to render a tag list.
120
 *
121
 * @method generateTagListData
122
 * @param {array} tags The array containing the tags related to the linked glossary entry.
123
 * @returns {Object} The data required to render a tag list.
124
 */
125
const generateTagListData = async(tags) => {
126
    // Define the number of initially displayed tags.
127
    const limit = 10;
128
    const hasOverflow = tags.length > limit;
129
    // If the total number of tags exceeds the defined limit, then we need to mark all the excess tags as over the limit.
130
    // By specifying this, these tags will be initially hidden.
131
    if (hasOverflow) {
132
        for (let i = limit; i < tags.length; i++) {
133
            tags[i].overlimit = true;
134
        }
135
    }
136
 
137
    return {
138
        tags: tags,
139
        tagscount: tags.length,
140
        overflow: hasOverflow,
141
        label: await getString('tags')
142
    };
143
};
144
 
145
/**
146
 * Initialize the module.
147
 */
148
export const init = () => {
149
    registerEventListeners();
150
};