Viewing File: /usr/local/cpanel/whostmgr/docroot/templates/cpanel_plugin_manager/views/createPluginController.js

/*
* templates/cpanel_plugin_manager/views/createPluginController.js Copyright(c) 2020 cPanel, L.L.C.
*                                                                 All rights reserved.
* copyright@cpanel.net                                            http://cpanel.net
* This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

/* global define, PAGE */

define(
    [
        "angular",
        "lodash",
        "cjt/util/locale",
        "app/services/createPluginService",
        "cjt/services/alertService",
        "cjt/directives/alertList",
        "cjt/validator/datatype-validators",
        "cjt/directives/validationContainerDirective",
        "cjt/directives/validationItemDirective",
    ],
    function(angular, _, LOCALE) {
        "use strict";

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

        app.controller(
            "createPluginController",
            ["$scope", "$anchorScroll", "alertService", "createPluginService", "PAGE",
                function($scope, $anchorScroll, alertService, createPluginService, PAGE) {

                    // Set default form variables for Add Item form. It is useful to clear the form when needed.
                    var defaultAddItemForm = {
                        itemData: {
                            id: "",
                            name: "",
                            description: "",
                            group_id: "",
                            order: "",
                            uri: "index.html",
                            overwrite: false,
                            featuremanager: false,
                            target: "",
                        },
                        showNewGroup: false,
                        newGroup: "",
                        itemIcon: "",
                    };

                    // Initialize createPlugin form
                    $scope.itemList = [];

                    $scope.item = angular.copy(defaultAddItemForm.itemData);

                    var groupList = [];

                    // Should contain the list of icons that get added to the plugin.
                    var iconList = {};

                    // Populate groups form the list obtained from backend.
                    $scope.groups = PAGE.groups;

                    // Get the list of item Ids to check against
                    var itemIds = PAGE.itemIds;

                    // Pre-populate the URI to index.html
                    $scope.item.uri = defaultAddItemForm.itemData.uri;

                    /**
                 * Add the newly entered item to new plugin to generate.
                 */
                    $scope.addItemToPlugin = function() {
                        if ($scope.addItemForm.$invalid) {
                            return;
                        }

                        if ($scope.item !== void 0) {

                            // Add Item type.
                            $scope.item.type = "link";

                            // Add Item group
                            if ($scope.newGroup !== void 0 && $scope.newGroup !== "") {

                                // Add the new group to the group list and assign this group to the current item
                                // to be added.
                                var newGroupId = $scope.newGroup.toLowerCase().split(" ").join("_");

                                var newGroupObj = { id: newGroupId, name: $scope.newGroup };

                                $scope.groups.push(newGroupObj);

                                // Assign this new group to the item.
                                $scope.item.group_id = newGroupId;

                                // Create an entry for the group list which gets added
                                // later into install.json.
                                var installGroupObj = {
                                    name: $scope.newGroup,
                                    type: "group",
                                    order: 99,   // Order is kept high for now. It will change when order input could be taken.
                                    id: newGroupId,
                                };

                                groupList.push(installGroupObj);
                            }

                            // We need to read the icon file before we say
                            // 'Add Item' is done. Since FileReader read is asynchronous,
                            // the process of pushing the item into itemList will be done in addIconItem
                            // function to make sure the icon file is read successfully before item is added.
                            readIconFile();
                        }
                    };

                    // This is custom validation function which validates
                    // if the entered item ID is already used in previously
                    // added items.
                    $scope.validateDuplicate = function() {

                        // Check for duplicate unique_id when something is
                        // entered in the id textbox.
                        if ($scope.item.id !== "") {
                            var isDuplicate = $scope.itemList.some(function(item) {
                                return item.id === $scope.item.id;
                            });

                            if (isDuplicate) {
                                $scope.addItemForm.txtItemId.$setValidity("unique", false);
                                $scope.focusOnId = true;
                                return isDuplicate;
                            } else {
                                $scope.addItemForm.txtItemId.$setValidity("unique", true);
                            }

                            // Check for existing cPanel items only if it is not previously
                            // checked.
                            var askOverwrite = itemIds.some(function(existingItem) {
                                return existingItem === $scope.item.id;
                            });

                            if (askOverwrite) {
                                $scope.addItemForm.txtItemId.$setValidity("existing", false);
                                $scope.showOverwrite = true;

                                return askOverwrite;
                            } else {
                                $scope.addItemForm.txtItemId.$setValidity("existing", true);
                                $scope.showOverwrite = false;
                                $scope.item.overwrite = false;

                                return askOverwrite;
                            }
                        }
                    };

                    // This is custom validation function which validates
                    // if the entered New Group Name is already used in previously
                    $scope.validateGroupNameDuplicate = function() {
                        var duplicate = false;

                        if ($scope.newGroup !== void 0 && $scope.newGroup !== "") {
                            var newGroupId = $scope.newGroup.toLowerCase().split(" ").join("_");
                            duplicate = $scope.groups.some(function(existingGroup) {
                                return existingGroup.id === newGroupId;
                            });
                        }

                        $scope.addItemForm.txtItemGroup.$setValidity("unique", !duplicate);
                    };

                    // This method updates the validation of item ID when
                    // user explicitly checks the checkbox to give his consent
                    // to overwrite an existing cPanel.
                    $scope.validateOverwrites = function() {
                        var pleaseOverwrite = $scope.item.overwrite;
                        $scope.addItemForm.txtItemId.$setValidity("existing", pleaseOverwrite);
                    };

                    $scope.clearItem = function() {
                        clearItemForm();
                    };

                    $scope.addGroup = function() {
                        $scope.showNewGroup = true;
                        if ($scope.item && $scope.item.group_id) {
                            $scope.item.group_id = "";
                        }
                        $scope.addItemForm.ddlGroup.$setPristine();
                    };

                    $scope.cancelNewGroup = function() {
                        $scope.showNewGroup = false;
                        $scope.newGroup = "";

                        // Reset the validation for the new group text field on cancelling.
                        $scope.addItemForm.txtItemGroup.$setValidity("unique", true);
                        $scope.addItemForm.txtItemGroup.$setPristine();
                    };

                    $scope.removeItem = function(itemId) {
                        if (itemId !== "") {
                            var itemList = $scope.itemList;

                            var removeItem =  itemList.filter(function(item) {
                                return item.id === itemId;
                            });

                            if (removeItem && removeItem.length === 1) {
                                var index = itemList.indexOf(removeItem[0]);
                                if (index !== -1) {
                                    $scope.itemList.splice(index, 1);
                                }

                                var removeIcon = removeItem[0].icon;

                                // Also remove the icon entry from iconlist.
                                delete iconList[removeIcon];
                            }

                        }
                    };

                    $scope.generatePlugin = function() {

                        if ($scope.createPluginForm.$invalid) {
                            return;
                        }

                        groupList = groupList.filter(function(group) {
                            return $scope.itemList.some(function(item) {
                                return item.group_id === group.id;
                            });
                        });

                        // Convert iconList object to JSON string.
                        var iconListJson = angular.toJson(iconList);

                        // Merge itemlist and group list
                        var installList = groupList.concat($scope.itemList);

                        // Convert installList object to JSON string.
                        var installListJson = angular.toJson(installList);

                        var pluginData = {
                            "name": $scope.pluginName,
                            "installListJson": installListJson,
                            "iconListJson": iconListJson,
                        };

                        return createPluginService.generatePluginFile(pluginData)
                            .then(
                                function(data) {
                                    if (data.tarball !== void 0) {
                                        $scope.notice = true;
                                        var downloadUrl = "download/" + data.tarball;
                                        alertService.add({
                                            type: "success",
                                            message: LOCALE.maketext("The plugin file “[_1]” was generated successfully. Please [output,url,_2,download the plugin,target,blank,title,_1] before creating a new one.", data.tarball, downloadUrl),
                                            id: "alertAddSuccess",
                                            closeable: false,
                                        });
                                        clearItemForm();
                                        clearCreatePluginForm();
                                    }
                                }, function(error) {
                                    alertService.add({
                                        type: "danger",
                                        message: error,
                                        id: "alertMessages",
                                        closeable: false,
                                    });
                                }
                            );
                    };

                    function clearItemForm() {
                        if ($scope.addItemForm.$dirty) {
                            $scope.addItemForm.$setPristine();
                            $scope.item = angular.copy(defaultAddItemForm.itemData);
                            $scope.showNewGroup = defaultAddItemForm.showNewGroup;
                            $scope.newGroup = defaultAddItemForm.newGroup;
                            $scope.itemIcon = defaultAddItemForm.itemIcon;
                            $scope.showOverwrite = false;
                            $scope.focusOnId = true;

                            // Browsers like Chrome do not fire 'changed' event on the file field
                            // if we try to select the same file again. But we need it to fire the event
                            // in our case, as we are handling the 'add item' just through javascript and
                            // multiple items may want to have same icon file uploaded.
                            var fileField = document.getElementById("fileIcon");
                            if (fileField !== void 0) {
                                fileField.value = defaultAddItemForm.itemIcon;
                            }
                        }
                    }

                    function clearCreatePluginForm() {
                        if ($scope.createPluginForm.$dirty) {
                            $scope.createPluginForm.$setPristine();
                            $scope.itemList = [];
                            $scope.pluginName = "";
                            iconList = {};
                        }
                    }

                    function readIconFile() {
                        var reader = new FileReader();

                        reader.onloadend = function() {
                            $scope.addItemProcessing = false;
                            $scope.$apply(addIconToItem(reader.result));
                        };

                        if ($scope.itemIcon) {
                            $scope.addItemProcessing = true;
                            reader.readAsDataURL($scope.itemIcon);
                        }
                    }

                    function addIconToItem(iconFileData) {

                        // Icons in the cPanel theme are always named by the item's id.
                        // AND it should be a .png or .svg file.

                        var imgName = $scope.itemIcon.name;
                        var iconExtension = imgName.substr(imgName.lastIndexOf("."));

                        var iconFileName = $scope.item.icon = $scope.item.id + iconExtension;
                        iconList[iconFileName] = iconFileData;

                        $scope.itemList.push($scope.item);

                        // Add the new item's id to the itemIds list to ensure duplicate id validation
                        // happens correctly.
                        // itemIds.push($scope.item.id);

                        clearItemForm();
                    }
                },
            ]);
    }
);
Back to Directory File Manager