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
 * This module handles the creation of a Modal that shows the user's post in context of the entire discussion.
18
 *
19
 * @module     mod_forum/grades/expandconversation
20
 * @copyright  2019 Mathew May <mathew.solutions>
21
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
import * as ForumSelectors from './grader/selectors';
24
import Repository from 'mod_forum/repository';
25
import {exception as showException} from "core/notification";
26
import Templates from 'core/templates';
27
import Modal from 'core/modal_cancel';
28
import * as ModalEvents from 'core/modal_events';
29
 
30
/**
31
 * Find the Node containing the gradable details from the provided node by searching up the tree.
32
 *
33
 * @param {HTMLElement} node
34
 * @returns {HTMLElement}
35
 */
36
const findGradableNode = node => node.closest(ForumSelectors.expandConversation);
37
 
38
/**
39
 * Show the post in context in a modal.
40
 *
41
 * @param {HTMLElement} rootNode The button that has been clicked
42
 * @param {object} param
43
 * @param {bool} [param.focusOnClose=null]
44
 */
45
const showPostInContext = async(rootNode, {
46
    focusOnClose = null,
47
} = {}) => {
48
    const postId = rootNode.dataset.postid;
49
    const discussionId = rootNode.dataset.discussionid;
50
    const discussionName = rootNode.dataset.name;
51
    const experimentalDisplayMode = rootNode.dataset.experimentalDisplayMode == "1";
52
 
53
    const [
54
        allPosts,
55
        modal,
56
    ] = await Promise.all([
57
        Repository.getDiscussionPosts(parseInt(discussionId)),
58
        Modal.create({
59
            title: discussionName,
60
            large: true,
61
            removeOnClose: true,
62
            returnElement: focusOnClose,
63
        }),
64
    ]);
65
 
66
    const postsById = new Map(allPosts.posts.map(post => {
67
        post.readonly = true;
68
        post.hasreplies = false;
69
        post.replies = [];
70
        return [post.id, post];
71
    }));
72
 
73
    let posts = [];
74
    allPosts.posts.forEach(post => {
75
        if (post.parentid) {
76
            const parent = postsById.get(post.parentid);
77
            if (parent) {
78
                post.parentauthorname = parent.author.fullname;
79
                parent.hasreplies = true;
80
                parent.replies.push(post);
81
            } else {
82
                posts.push(post);
83
            }
84
        } else {
85
            posts.push(post);
86
        }
87
    });
88
 
89
    modal.getRoot().on(ModalEvents.bodyRendered, () => {
90
        const relevantPost = modal.getRoot()[0].querySelector(`#p${postId}`);
91
        if (relevantPost) {
92
            relevantPost.scrollIntoView({behavior: "smooth"});
93
        }
94
    });
95
 
96
    modal.show();
97
 
98
    // Note: We do not use await here because it messes with the Modal transitions.
99
    const templatePromise = Templates.render('mod_forum/grades/grader/discussion/post_modal', {
100
        posts,
101
        experimentaldisplaymode: experimentalDisplayMode
102
    });
103
    modal.setBody(templatePromise);
104
};
105
 
106
/**
107
 * Register event listeners for the expand conversations button.
108
 *
109
 * @param {HTMLElement} rootNode The root to listen to.
110
 */
111
export const registerEventListeners = (rootNode) => {
112
    rootNode.addEventListener('click', (e) => {
113
        const rootNode = findGradableNode(e.target);
114
 
115
        if (rootNode) {
116
            e.preventDefault();
117
 
118
            try {
119
                showPostInContext(rootNode, {
120
                    focusOnClose: e.target,
121
                });
122
            } catch (err) {
123
                showException(err);
124
            }
125
        }
126
    });
127
};