All Downloads are FREE. Search and download functionalities are using the official Maven repository.

SLING-INF.content.devwidgets.deletecontent.javascript.deletecontent.js Maven / Gradle / Ivy

/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

/*
 * Dependencies
 *
 * /dev/lib/jquery/plugins/jqmodal.sakai-edited.js
 */

/*global, fluid, window, $ */

require(["jquery", "sakai/sakai.api.core"], function($, sakai) {

    /**
     * @name sakai_global.deletecontent
     *
     * @class deletecontent
     *
     * @description
     * Deletecontent widget
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
    sakai_global.deletecontent = function(tuid, showSettings){

        //////////////////////
        // Global variables //
        //////////////////////

        var pathsToDelete = false;
        var contentIManage = false;
        var contentIView = false;
        var context = false;
        var callback = false;
        var contextType = false;

        ///////////////////
        // CSS Selectors //
        ///////////////////

        var $deletecontent_dialog = $("#deletecontent_dialog");

        ////////////////////////////
        // Batch request handling //
        ////////////////////////////

        /**
         * Once all requests have been collected into a batchRequest array, we can submit them as
         * a batch request
         * @param {Object} batchRequests    Array that contains all batch requests to be submitted
         * @param {Object} successMessage   Id of the dom element that contains the success message to be displayed
         */
        var sendDeletes = function(batchRequests, successMessage) {
            // Update the inserter
            $.each(collectionsToUpdate, function(collectionId, amount) {
                $.each(sakai.api.User.data.me.groups, function(index, group){
                    if (group && group.counts && group.groupid === collectionId) {
                        group.counts.contentCount -= amount;
                        collectionId = collectionId.substring(2,collectionId.length);
                        $(window).trigger('updateCount.inserter.sakai', [collectionId, group.counts.contentCount]);
                    }
                });
            });
            sakai.api.Server.batch(batchRequests, function (success, data) {
                if (success) {
                    sakai.api.Util.notification.show($("#deletecontent_message_title").html(), $(successMessage).html());
                } else {
                    sakai.api.Util.error.show($("#deletecontent_message_title").html(), $("#deletecontent_message_error").html()); 
                }

                $(window).trigger("done.deletecontent.sakai", [pathsToDelete]);
                if ($.isFunction(callback)) {
                    callback(success);
                }
                $deletecontent_dialog.jqmHide();
            });
        };

        //////////////////////////////
        // Remove from library only //
        //////////////////////////////

        /**
         * Add one request for each item to be removed from the current library
         * @param {Object} batchRequests    Array to which to add the requests for removing the content
         * @param {Object} items            Content items to be removed from the current library
         */
        var processRemoveFromLibrary = function(batchRequests, items){
            batchRequests = batchRequests || [];
            for (var i = 0; i < items.length; i++){
                var parameters = {};
                if (sakai.api.Content.Collections.isCollection(items[i])) {
                    var groupId = sakai.api.Content.Collections.getCollectionGroupId(items[i]);
                    batchRequests.push({
                        "url": "/system/userManager/group/" + groupId + "-members.update.json",
                        "method": "POST",
                        "parameters": {
                            ":viewer@Delete": context,
                            ":member@Delete": context
                        }
                    });
                    batchRequests.push({
                        "url": "/system/userManager/group/" + groupId + "-managers.update.json",
                        "method": "POST",
                        "parameters": {
                            ":viewer@Delete": context,
                            ":member@Delete": context
                        }
                    });
                } else {
                    parameters[":manager@Delete"] = context;
                    parameters[":viewer@Delete"] = context;
                    batchRequests.push({
                        "url": "/p/" + items[i]["_path"] + ".members.json",
                        "method": "POST",
                        "parameters": parameters
                    });
                }
            }
        };

        /**
         * Remove the selected items from the current library only and keep them onto the
         * system.
         */
        var removeFromLibrary = function(){
            var batchRequests = [];
            processRemoveFromLibrary(batchRequests, contentIView);
            processRemoveFromLibrary(batchRequests, contentIManage);
            sendDeletes(batchRequests, (contextType === "collection" ? "#deletecontent_message_from_collection" : "#deletecontent_message_from_library"));
        };

        ////////////////////////////
        // Remove from the system //
        ////////////////////////////

        /**
         * Add one request for each item to delete from the system
         * @param {Object} batchRequests    Array to which to add the requests for removing the content
         * @param {Object} items            Content items to be removed from the system
         */
        var processRemoveFromSystem = function(batchRequests, items){
            batchRequests = batchRequests || [];
            for (var i = 0; i < items.length; i++){
                batchRequests.push({
                    "url": "/p/" + items[i]["_path"],
                    "method": "POST",
                    "parameters": {
                        ":operation": "delete"
                    }
                });
                // Remove the pseudoGroups associated to the collection
                var collectionGroupId = sakai.api.Content.Collections.getCollectionGroupId(items[i]);
                if (sakai.api.Content.Collections.isCollection(items[i])) {
                    batchRequests.push({
                        "url": "/system/userManager.delete.json",
                        "method": "POST",
                        "parameters": {
                            ":applyTo": [collectionGroupId, collectionGroupId + "-members", collectionGroupId + "-managers"]
                        }
                    });
                }
            }
        };

        /**
         * Remove the selected items from the system and thus from all libraries where this is being
         * used
         */
        var removeFromSystem = function(){
            // Remove content I manage from the system
            var batchRequests = [];
            processRemoveFromLibrary(batchRequests, contentIView);
            processRemoveFromSystem(batchRequests, contentIManage);
            sendDeletes(batchRequests, "#deletecontent_message_from_system");
        };

        var collectionsToUpdate = {};

        /**
         * Check whether any users or groups are either managers or viewers from
         * any of the selected content items
         */
        var checkUsedByOthers = function(){
            collectionsToUpdate = {};
            var userGroupIds = [];
            var collectionsToCheck = [];
            // Check whether any of the content I manage is managed by or
            // shared with other people
            for (var m = 0; m < contentIManage.length; m++){
                if (sakai.api.Content.Collections.isCollection(contentIManage[m])){
                    var collectionGroupId = sakai.api.Content.Collections.getCollectionGroupId(contentIManage[m]);
                    collectionsToCheck.push(collectionGroupId + "-members");
                    collectionsToCheck.push(collectionGroupId + "-managers");
                } else {
                    var managers = contentIManage[m]["sakai:pooled-content-manager"];
                    if (managers){
                        for (var i = 0; i < managers.length; i++){
                            if ($.inArray(managers[i], userGroupIds) === -1 && managers[i] !== sakai.data.me.user.userid &&
                            managers[i] !== context){
                                userGroupIds.push(managers[i]);
                            }
                        }
                    }
                    var viewers = contentIManage[m]["sakai:pooled-content-viewer"];
                    if (viewers){
                        for (var j = 0; j < viewers.length; j++){
                            if ($.inArray(viewers[j], userGroupIds) === -1 && viewers[j] !== sakai.data.me.user.userid &&
                                viewers[j] !== context && viewers[j] !== "everyone" && viewers[j] !== "anonymous"){
                                userGroupIds.push(viewers[j]);
                                if (sakai.api.Content.Collections.isCollection(viewers[j])) {
                                     collectionsToUpdate[viewers[j]] = collectionsToUpdate[viewers[j]] || 0;
                                     collectionsToUpdate[viewers[j]] += 1;
                                 }
                            }
                        }
                    }
                }
            }
            if (collectionsToCheck.length > 0) {
                var batchRequest = [];
                $.each(collectionsToCheck, function(index, collectiongroup){
                    batchRequest.push({
                        "url": "/system/userManager/group/" + collectiongroup + ".members.json",
                        "method": "GET",
                        "parameters": {
                            items: 10000
                        }
                    });
                });
                sakai.api.Server.batch(batchRequest, function (success, data) {
                    for (var i = 0; i < data.results.length; i++) {
                        var members = $.parseJSON(data.results[i].body);
                        for (var ii = 0; ii < members.length; ii++) {
                            var member = members[ii].userid || members[ii].groupid;
                            if ($.inArray(member, userGroupIds) === -1 &&
                                member !== sakai.data.me.user.userid &&
                                member !== context) {
                                userGroupIds.push(member);
                                if (sakai.api.Content.Collections.isCollection(member)) {
                                    collectionsToUpdate[member] = collectionsToUpdate[member] || 0;
                                    collectionsToUpdate[member] += 1;
                                }
                            }
                        }
                    }
                    if (userGroupIds.length > 0) {
                        setUpUsedByOverlay(userGroupIds);
                    } else {
                        removeFromSystem();
                    }
                });
            } else {
                if (userGroupIds.length > 0) {
                    setUpUsedByOverlay(userGroupIds);
                } else {
                    removeFromSystem();
                }
            }
        };

        /**
         * When the content the user is trying to delete from the system is
         * being used by others, present an overlay that lists all of the
         * groups and users that either use or manage the content
         * @param {Object} userGroupIds    Array that contains the userids and groupids of all
         *                                 users and groups using the content
         */
        var setUpUsedByOverlay = function(userGroupIds){
            // Show the overview screen of who else is using this
            $("#deletecontent_used_by_others_container").html("");
            $("#deletecontent_container").hide();
            $("#deletecontent_used_by_others").show();
            // Set up the buttons correctly
            hideButtons();
            $("#deletecontent_action_removefromsystem_confirm").show();
            if (context && contextType === "collection"){
                $("#deletecontent_action_removefromcollection_only").show();
            } else if (context){
                $("#deletecontent_action_removefromlibrary_only").show();
            }
            // Show the correct overlay title
            $("#deletecontent_main_content").hide();
            $("#deletecontent_main_confirm").show();
            // Get the profile information of who else is using it
            var batchRequests = [];
            for (var i = 0; i < userGroupIds.length; i++){
                batchRequests.push({
                    "url": "/~" + userGroupIds[i] + "/public/authprofile.profile.json",
                    "method": "GET"
                });
            }
            // Get profile information for each of the users and groups using
            // this content
            sakai.api.Server.batch(batchRequests, function (success, data) {
                var profileInfo = [];
                for (var i = 0; i < data.results.length; i++){
                    if (data.results[i].success && data.results[i].status !== 404) {
                        // Process pseudoGroups
                        var profile = $.parseJSON(data.results[i].body);
                        profile.showLink = true;
                        if (sakai.api.Content.Collections.isCollection(profile)){
                            profile.collectionid = sakai.api.Content.Collections.getCollectionPoolId(profile);
                        } else if (profile["sakai:excludeSearch"] === "true"){
                            var splitOnDash = profile.groupid.split("-");
                            profile["sakai:group-title"] = profile["sakai:parent-group-title"] + " (" + sakai.api.i18n.getValueForKey(profile["sakai:role-title-plural"]) + ")";
                            profile.groupid = splitOnDash.splice(0, splitOnDash.length - 1).join("-");
                        }
                        profileInfo.push(profile);
                    } else {
                        var privateProfile = {
                            showLink: false
                        };
                        if (data.results[i].url.substring(0,4) === '/~c-') {
                            privateProfile.collectionid = true;
                            privateProfile['sakai:group-title'] =
                                sakai.api.i18n.getValueForKey('PRIVATE_COLLECTION', 'deletecontent');
                        } else {
                            privateProfile['sakai:group-title'] =
                                sakai.api.i18n.getValueForKey('PRIVATE_USER_GROUP', 'deletecontent');
                        }
                        profileInfo.push(privateProfile);
                    }
                }
                $("#deletecontent_used_by_others_container").html(sakai.api.Util.TemplateRenderer("deletecontent_used_by_others_template", {
                    "profiles": profileInfo,
                    "sakai": sakai
                }));
            });
        };

        ////////////////////////////
        // Remove hybrid strategy //
        ////////////////////////////

        /**
         * Check whether the users has chosen to remove the content he manages from his
         * library only or from the system. If removing from the library only, we can
         * go ahead and remove the content. If removing from the system, we want to check
         * first whether the content is being used by anyone else
         */
        var selectHybrid = function(){
            var manageOption = $("input[name='deletecontent_hybrid_options']:checked").val();
            if (manageOption === "libraryonly") {
                removeFromLibrary();
            } else if (manageOption === "system") {
                checkUsedByOthers();
            }
        };

        ///////////////////
        // Overlay setup //
        ///////////////////

        /**
         * Hide all of the action buttons in the overlay
         */
        var hideButtons = function(){
            $("#deletecontent_action_removefromsystem").hide();
            $("#deletecontent_action_removefromsystem_nocontext").hide();
            $("#deletecontent_action_removefromlibrary").hide();
            $("#deletecontent_action_removefromcollection").hide();
            $("#deletecontent_action_apply").hide();
            $("#deletecontent_action_removefromsystem_confirm").hide();
            $("#deletecontent_action_removefromlibrary_only").hide();
            $("#deletecontent_action_removefromcollection_only").hide();
        };

        /**
         * Set up the delete overlay depending on the permissions I have on the content
         * about to be deleted from the overlay
         * There are 3 scenarios:
         * 1. I am a manager of some items and a viewer of others
         * 2. I am a manager of all items
         * 3. I am a viewer of all items
         * @param {Object} contentIManage    Array that contains all files about to be
         *                                   removed from the library that I manage
         * @param {Object} contentIView      Array that contains all files about to be
         *                                   removed from the library that I'm a viewer of
         */
        var setupOverlay = function(contentIManage, contentIView){
            hideButtons();
            var template = "";
            if (contentIManage.length > 0 && contentIView.length > 0){
                // Set up overlay for mixed permissions
                template = "deletecontent_template_hybrid";
                $("#deletecontent_action_apply").show();
            } else if (contentIManage.length > 0){
                // Set up overlay for full management permissions
                template = "deletecontent_template_list";
                if (context){
                    $("#deletecontent_action_removefromsystem").show();
                    if (contextType === "collection"){
                        if (sakai_global.content_profile && sakai_global.content_profile.content_data) {
                            var managerCid = 'c-' + sakai_global.content_profile.content_data.data._path;
                            collectionsToUpdate[managerCid] = collectionsToUpdate[managerCid] || 0;
                            collectionsToUpdate[managerCid] += contentIManage.length;
                        }
                        $("#deletecontent_action_removefromcollection").show();
                    } else {
                        $("#deletecontent_action_removefromlibrary").show();
                    }
                // When no context/library is specified, we assume that the content is being deleted outside
                // of a library (e.g. content profile). We thus don't offer the remove from library option
                } else {
                    $("#deletecontent_action_removefromsystem_nocontext").show();
                }
            } else if (contentIView.length > 0){
                // Set up overlay for full viewer permissions
                template = "deletecontent_template_list";
                if (contextType === "collection") {
                    if (sakai_global.content_profile && sakai_global.content_profile.content_data) {
                        var viewerCid = 'c-' + sakai_global.content_profile.content_data.data._path;
                        collectionsToUpdate[viewerCid] =
                            collectionsToUpdate[viewerCid] || 0;
                        collectionsToUpdate[viewerCid] += contentIView.length;
                    }
                    $("#deletecontent_action_removefromcollection").show();
                } else {
                    $("#deletecontent_action_removefromlibrary").show();
                }
            }
            $("#deletecontent_container").html(sakai.api.Util.TemplateRenderer(template, {
                "contentIManage": contentIManage,
                "contentIView": contentIView,
                "contextType": contextType,
                "sakai": sakai
            }));
        };

        /**
         * Run over the list of content items to delete and determine whether there
         * any that I manage and can thus remove from the system
         * @param {Object} contentList    Response from batch request that retrieved
         *                                metadata for all content that need to be deleted
         */
        var findContentIManage = function(contentList){
            contentIManage = []; 
            contentIView = [];
            $.each(contentList.results, function (i, contentItem) {
                var content = $.parseJSON(contentItem.body);
                var manage = sakai.api.Content.isUserAManager(content, sakai.data.me);
                if (manage){
                    contentIManage.push(content);
                } else {
                    contentIView.push(content);
                }
            });
            setupOverlay(contentIManage, contentIView);
        };

        /**
         * Retrieve the metadata of all selected files
         * @param {Object} paths    Array that contains the paths to all
         *                          content that needs to be deleted
         */
        var getContentInfo = function(paths){
            var batchRequest = [];
            $.each(paths, function (i, url) {
                batchRequest.push({
                    url: "/p/" + url + ".json",
                    method: "GET"
                });
            });
            sakai.api.Server.batch(batchRequest, function (success, data) {
                if (success) {
                    findContentIManage(data);
                }
            });
        };

        ////////////////////
        // Initialisation //
        ////////////////////

        /**
         * Load the delete content widget with the appropriate data
         * This function can be called from anywhere within Sakai by triggering the
         * 'init.deletecontent.sakai' event
         *
         * @param {Object} data A JSON object containing the necessary information.
         *
         * @example To delete one item:
         *     $(window).trigger('init.deletecontent.sakai', [{
         *         "path": [ "/test.jpg" ]
         *     }, callbackFn]);  // callbackFn is sent one param: success (true if delete succeeded, false otherwise)
         *
         * @example To delete multiple items:
         *     $(window).trigger('init.deletecontent.sakai', [{
         *         "path": [ "/file1.ext", "/file2.ext", "/file3.ext", "/file4.ext" ]
         *     }, callbackFn]);  // callbackFn is sent one param: success (true if delete succeeded, false otherwise)
         */
        var load = function(ev, data, _callback){
            context = data.context;
            contextType = "default";
            if (context && sakai.api.Content.Collections.isCollection(context)){
                contextType = "collection";
            }
            callback = _callback;
            pathsToDelete = data.paths;
            getContentInfo(data.paths);
            hideButtons();
            // Show the appropriate overlay title
            $("#deletecontent_main_confirm").hide();
            $("#deletecontent_main_content").show();
            // Show and clear the main container
            $("#deletecontent_container").html("");
            $("#deletecontent_container").show();
            $("#deletecontent_used_by_others").hide();
            sakai.api.Util.positionDialogBox($deletecontent_dialog);
            sakai.api.Util.bindDialogFocus($deletecontent_dialog);
            $deletecontent_dialog.jqmShow();
        };

        /**
         * Initialize the delete content widget
         * All the functionality in here is loaded before the widget is actually rendered
         */
        var init = function(){
            // This will make the widget popup as a layover.
            $deletecontent_dialog.jqm({
                modal: true,
                toTop: true
            });
        };

        ////////////////////////////
        // Internal event binding //
        ////////////////////////////

        $("#deletecontent_action_removefromlibrary").bind("click", removeFromLibrary);
        $("#deletecontent_action_removefromcollection").bind("click", removeFromLibrary);
        $("#deletecontent_action_removefromsystem").bind("click", checkUsedByOthers);
        $("#deletecontent_action_apply").bind("click", selectHybrid);
        $("#deletecontent_action_removefromlibrary_only").bind("click", removeFromLibrary);
        $("#deletecontent_action_removefromcollection_only").bind("click", removeFromLibrary);
        $("#deletecontent_action_removefromsystem_confirm").bind("click", removeFromSystem);
        $("#deletecontent_action_removefromsystem_nocontext").bind("click", checkUsedByOthers);

        ////////////////////////////
        // External event binding //
        ////////////////////////////

        $(window).unbind("init.deletecontent.sakai").bind("init.deletecontent.sakai", load);

        init();
    };

    sakai.api.Widgets.widgetLoader.informOnLoad("deletecontent");
});




© 2015 - 2025 Weber Informatics LLC | Privacy Policy