Viewing File: /usr/local/cpanel/base/frontend/jupiter/tools/views/applicationListController.js

// Copyright 2023 cPanel, L.L.C. - All rights reserved.
// copyright@cpanel.net
// https://cpanel.net
// This code is subject to the cPanel license. Unauthorized copying is prohibited

define(
    [
        "angular",
        "lodash",
        "cjt/util/locale",
        "cjt/services/cpanel/nvDataService",

        // application related
        "app/directives/draggableDirective",
        "app/directives/dropDirective",
    ],
    function(angular, _, LOCALE) {

        "use strict";

        // Retrieve the current application
        var app = angular.module("App");

        var controller = app.controller(
            "applicationListController", ["$scope", "nvDataService",
                function($scope, nvDataService) {

                    var applicationList = PAGE.appGroups;
                    var collapsedGroupsList = PAGE.collapsedGroups.split("|");

                    // Binding it to the scope so that
                    $scope.collapsedGroups = PAGE.collapsedGroups;

                    /* Updating the searchText model with the value in
                     * search Field if typed before angular bootstrap.
                     * Hack to ensure delayed search is preformed on the
                     * text in the search box, if user types in before angular
                     * bootstrap completes
                     */
                    var searchBox = document.querySelector("#quickjump");
                    if (searchBox && $scope.searchText !== searchBox.value) {
                        $scope.searchText = searchBox.value;
                    }

                    init();

                    function init() {
                        trackAppLinkClicks();
                    }

                    function trackAppLinkClicks() {
                        var querySelForAppLinks = "#boxes [id*='-container'] > [id*='-group'] > [id*='-body'] > .icon-container-body > a";
                        var appLinkEls = document.querySelectorAll(querySelForAppLinks);

                        if (appLinkEls && appLinkEls.length && window["mixpanel"]) {
                            window["mixpanel"].track_links(appLinkEls, "cPanel-Tools-Nav-Link", (linkEl) => {
                                return { "nav-link-id": linkEl.id };
                            });
                        }
                    }

                    /**
                    * Clears search on Esc
                    *
                    * @method clearSearch
                    * @param {Event} event Event
                    */
                    $scope.clearSearch = function(event) {

                        // clear the search when pressing the Esc key
                        if (event.keyCode === 27) {
                            $scope.searchText = "";
                        }
                    };

                    var searchCache = {};

                    /**
                    * Search Groups
                    *
                    * @method searchGroup
                    * @param {Object} group Group
                    * @return {Boolean}  If the group needs to be displayed
                    */
                    $scope.searchGroup = function(group) {
                        if (!$scope.searchText) {
                            return 1;
                        }
                        if (!searchCache[$scope.searchText]) {
                            searchCache[$scope.searchText] = new RegExp($scope.searchText, "i");
                        }
                        var regex = searchCache[$scope.searchText];
                        var found = false;

                        var groupInfo = _.find(applicationList, function(app) {
                            return app.group === group;
                        });

                        var items = groupInfo.length ? groupInfo.items : [];

                        for (var i = 0, len = items.length; i < len; i++) {
                            found = regex.test(items[i].searchtext);
                            if (found) {
                                return found;
                            }
                        }
                    };

                    /**
                    * Search Item
                    *
                    * @method searchItem
                    * @param {Object} Item Item
                    * @return {Boolean} If the item searchtext matches the searchtext
                    */
                    $scope.searchItem = function(item) {
                        if (!$scope.searchText) {
                            return 1;
                        }
                        if (!searchCache[$scope.searchText]) {
                            searchCache[$scope.searchText] = new RegExp($scope.searchText, "i");
                        }
                        var regex = searchCache[$scope.searchText];

                        return regex.test(item.searchtext);
                    };

                    /**
                     * Sends the ordered list of application groups to the server to retain
                     * user preferences in the page's NVData object
                     * @param {String} groups - The | delimited list of group order
                     */
                    var setGroupsOrder = function(groups) {
                        nvDataService.setObject(
                            {
                                xmaingroupsorder: groups,
                            })
                            .catch(function(error) {
                                console.error(error);
                            });
                    };

                    /**
                     * Sends the list of collapsed menu groups to the server to retain
                     * user preferences in the page's NVData object
                     * @param {String} groups - The | delimited list of collapsed menu groups
                     */
                    var setCollapsedGroupsList = function(groups) {
                        nvDataService.setObject(
                            {
                                xmainrollstatus: groups,
                            })
                            .catch(function(error) {
                                console.error(error);
                            });
                    };

                    /**
                    * Toggles group and saves state in NvData
                    *
                    * @method toggleGroup
                    * @param {Object} group Group
                    */
                    $scope.toggleGroup = function(group) {
                        var groupBody = angular.element(document.querySelector("#" + group + "-body"));
                        var groupCollapseIndicator = angular.element(document.querySelector("#" + group + "-collapsed-indicator"));

                        group = group + "=0";

                        var index = collapsedGroupsList.indexOf(group);
                        if (index === -1) {
                            groupBody.removeClass("maximize");
                            collapsedGroupsList.push(group);
                            groupBody.addClass("minimized ng-hide");

                            groupCollapseIndicator.removeClass("fa-minus");
                            groupCollapseIndicator.addClass("fa-plus");
                        } else {
                            groupBody.removeClass("minimized ng-hide");
                            collapsedGroupsList.splice(index, 1);
                            groupBody.addClass("maximize");

                            groupCollapseIndicator.removeClass("fa-plus");
                            groupCollapseIndicator.addClass("fa-minus");
                        }

                        var groupList = collapsedGroupsList.join("|");

                        // updating the collapseGroups model with new changes
                        $scope.collapsedGroups = groupList;

                        // Save the changes to NvData
                        setCollapsedGroupsList(groupList);
                    };

                    /**
                    * Handles drag event
                    *
                    * @method handleDrag
                    * @param {String} itemID ID of the item thats being dragged.
                    */
                    $scope.handleDrag = function(itemID) {
                        var groupName = itemID.replace("-group", ""),
                            groupBody = angular.element(document.querySelector("#" + groupName + "-body"));

                        groupBody.removeClass("minimize maximize");

                        var startingPosition = _.findIndex(applicationList, function(group) {
                            return group.group === groupName;
                        });

                        var previousDropAreaId = "#top-drop-area";
                        if (startingPosition > 0) {
                            previousDropAreaId = "#" + applicationList[startingPosition - 1].group + "-drop-area";
                        }

                        // Hidding the DropArea of the group right above the item being moved. We dont want to
                        // drop the group in the same place
                        var hiddenDropArea = angular.element(document.querySelector(previousDropAreaId));
                        hiddenDropArea.addClass("drag-hidden");
                    };

                    /**
                    * Handles the case when a drag event is started but the item is never dropped into a dropArea
                    *
                    * @method handleDragEnd
                    */
                    $scope.handleDragEnd = function() {
                        var hiddenDropArea = angular.element(document.querySelectorAll(".drag-hidden"));

                        // On DragEnd ensures none of the dragAreas are hidden
                        hiddenDropArea.removeClass("drag-hidden");
                    };

                    /**
                    * Handles the drop of group in dropArea
                    *
                    * @method handleDrop
                    * @param {Object} item The item thats being moved
                    * @param {Object} dropArea The area where the item is dropped
                    */
                    $scope.handleDrop = function(item, dropArea) {

                        var groupToMove = item.getAttribute("data-group-name");
                        var moveAfter = dropArea.getAttribute("data-group-name");

                        var boxes = document.querySelector("#boxes");
                        var groupToMoveContainer, moveAfterContainer;

                        if (moveAfter) {
                            groupToMoveContainer = document.querySelector("#" + groupToMove + "-container");
                            moveAfterContainer = document.querySelector("#" + moveAfter + "-container");
                        } else {
                            groupToMoveContainer = document.querySelector("#" + groupToMove + "-container");
                            moveAfterContainer = document.querySelector("#top-drop-area");
                        }

                        // Moving DOM elements
                        if (boxes && groupToMoveContainer && moveAfterContainer) {
                            boxes.insertBefore(groupToMoveContainer, moveAfterContainer.nextSibling);
                        }

                        var oldPosition = _.findIndex(applicationList, function(group) {
                            return group.group === item.id.replace("-group", "");
                        });

                        var movedGroup = applicationList[oldPosition];
                        var newPosition = _.findIndex(applicationList, function(group) {
                            return group.group === dropArea.id.replace("-drop-area", "");
                        });

                        if (oldPosition > newPosition) {
                            newPosition += 1;
                        }

                        applicationList.splice(oldPosition, 1);
                        applicationList.splice(newPosition, 0, movedGroup);

                        var newOrder = _.map(applicationList, "group").join("|");
                        setGroupsOrder(newOrder);

                    };
                },
            ]);

        return controller;
    }
);
Back to Directory File Manager