Viewing File: /usr/local/cpanel/base/frontend/jupiter/mail/lists/lists.cmb.js

/*
# share/apps/mailinglists/src/services/mailingListsService       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: false, YAHOO:false, angular:false */

/*
 * Creates a new MailingListItem
 * @class MailingListItem
 *
 * Used by MailingListService to store
 * each async loaded item
 *
 */
/* jshint -W100 */
function MailingListItem() {

    var _self = this;

    _self.defaultValues = {
        accesstype: "",
        advertised: 0,
        archive_private: 0,
        desthost: "",
        diskused: "",
        humandiskused: "00.00 KB",
        list: "",
        listadmin: "",
        listid: "",
        subscribe_policy: 0
    };
}

/*
 * @method create
 * Sets variables on the this object by merging
 * defaultValues and the rawData from the api
 *
 * benefits of this method are in the event that
 * if the rawData format ever changes, only this
 * bridge function will have to be altered.
 *
 * @param rawData {object} api generated response.data object
 */
MailingListItem.prototype.create = function(rawData) {
    angular.extend(this, this.defaultValues, rawData);
};

/*
 * @method getAttribute
 * Gets the attribute by the name (key)
 *
 * this is useful for the table because the columns
 * can be selected dynamically within an ngRepeat.
 *
 * @param key {string} name of attribute to fetch
 * @return attribute [key] {*}
 */
MailingListItem.prototype.getAttribute = function(key) {
    return this[key];
};

/*
 * @method formatListAdmin
 *
 * formats string to specified rows and columns
 *
 * @param settings {object} name of attribute to fetch
 * @param settings.maxItems {int} number of items / rows to display
 *        prepends "... and [N] more."
 * @param settings.maxCols {int} name of attribute to fetch
 * @param settings.separator {string} row separator
 * @return formatted string or html string based on settings
 */
MailingListItem.prototype.formatListAdmins = function(settings) {
    var input = this.getAttribute("listadmin");
    var defaultFormatSettings = {
        maxItems: input.length,
        maxCols: input.length,
        separator: "\n"
    };
    settings = angular.extend(defaultFormatSettings, settings);
    var admins = input.split(",");

    var excess;

    for (var i = 0; i < admins.length; i++) {
        var admin = admins[i].replace(/[\r\n]/gi, "").trim();
        if (admin.length > settings.maxCols) {
            admin = admin.substr(0, settings.maxCols - 3) + "…";
        }

        admins[i] = admin;

        if (i === settings.maxItems - 1 && i + 2 < admins.length) {
            excess = admins.length - settings.maxItems;
            admins.splice(i + 1); // empty out remaining items
            break;
        }
    }
    var out;

    if (excess) {
        out = LOCALE.maketext("[join,_1,_2][_1] … and [numf,_3] more", settings.separator, admins, excess);
    } else {
        out = admins.join(settings.separator);
    }

    return out;
};

/*
 * Creates a new MailingListService
 * @class MailingListService
 *
 * This serves as the model for the app
 * currently only retrieving the data
 * but also storing configurations for
 * that retreival
 *
 */
function MailingListService($rootScope, AlertService) {

    var _self = this;
    _self.lists = [];
    _self.loading = false;
    _self.alertService = AlertService;

    _self.page = 0;
    _self.pageSize = 10;
    _self.maxPages = 3;
    _self.totalResults = 0;
    _self.filterValue = "";
    _self.totalPages = 0;
    _self.errors = [];
    _self.request = null;

    _self.meta = {
        sort: {
            sortBy: "list",
            sortDirection: "asc",
            sortType: ""
        }
    };
    _self.meta.sort.sortString = "list";

    /*
     * @method addItem
     * factory function for creating and adding a new MailingListItem
     *
     * @param rawData {object} api generated response.data object
     */
    _self.addItem = function(rawData) {
        var item = new MailingListItem();
        item.create(rawData);
        _self.lists.push(item);
    };

    /*
     * @method handleLoadSuccess
     * success callback function for the api call below
     *
     * @param response {object} CPANEL.api response object
     */
    _self.handleLoadSuccess = function(response) {
        _self.lists = [];
        for (var i = 0; i < response.cpanel_data.length; i++) {
            _self.addItem(response.cpanel_data[i]);
        }
        var paginateData = response.cpanel_raw.metadata.paginate;
        if (typeof paginateData !== "undefined") {
            _self.totalPages = paginateData.total_pages;
            _self.totalResults = paginateData.total_results;
        }
        _self.loading = false;
        $rootScope.$apply();
    };

    /*
     * @method handleLoadError
     * error callback function for the api call below
     * currently just resets the "loading" param
     * and "$apply()s the empty list"
     * TODO: Add error messaging
     *
     * @param response {object} CPANEL.api response object
     */
    _self.handleLoadError = function(response) {
        _self.loading = false;
        _self.alertService.clear();
        angular.forEach(response.cpanel_messages, function(message) {
            _self.alertService.add({
                message: message.content,
                type: message.level
            });
        });
        $rootScope.$apply();
    };

    /*
     * @method selectPage
     * sets the current page and reloads the list
     *
     * @param page {number} number of the page to load
     */
    _self.selectPage = function() {
        _self.getLists();
    };

    /*
     * @method selectPageSize
     * sets number of items to pull per page
     * and reloads the list
     *
     * @param pageSize {number} number of items to display per page
     */
    _self.selectPageSize = function(pageSize) {

        _self.pageSize = pageSize;
        _self.getLists();
    };

    /*
     * @method dataSorted
     * on sorting of the data (from ToggleSortDirective)
     * rebuild the sortString and reload the list
     *
     * @param sortBy {string} key to sort by
     * @param sortDirection {string} [asc,desc] direction of the sort
     * @param sortType {string} [numeric, ...] how to handle the data being sorted
     */
    _self.dataSorted = function() {
        _self.meta.sort.sortString = _self.meta.sort.sortDirection === "asc" ? _self.meta.sort.sortBy : "!" + _self.meta.sort.sortBy;
        _self.getLists();
    };

    /*
     * @method getLists
     * reload lists from fresh api call
     * using stored parameters
     *
     */
    _self.getLists = function() {

        if (YAHOO.util.Connect.isCallInProgress(_self.request)) {
            YAHOO.util.Connect.abort(_self.request);
            _self.request = null;
        }

        _self.errors = [];

        var api_params = {
            module: "Email",
            version: "3",
            func: "list_lists",
            data: {
                domain: CPANEL.PAGE.domain
            },
            api_data: {
                sort: [],
                filter: []
            },
            callback: {
                success: _self.handleLoadSuccess,
                failure: _self.handleLoadError
            }
        };

        if (_self.meta.sort.sortBy === "humandiskused") {
            api_params.api_data.sort.push([(_self.meta.sort.sortDirection === "asc" ? "" : "!") + "diskused", "numeric"]);
        } else if (_self.meta.sort.sortString !== "") {
            api_params.api_data.sort.push(_self.meta.sort.sortString);
        }
        if (_self.filterValue !== "") {
            api_params.api_data.filter.push(["*", "contains", _self.filterValue]);
        }
        if (_self.pageSize !== -1) {
            api_params.api_data.paginate = {
                start: (_self.page - 1) * _self.pageSize,
                size: _self.pageSize
            };
        }

        _self.request = CPANEL.api(api_params);
        _self.loading = true;
    };

    if ("initData" in window.PAGE) {

        _self.totalResults = Number(window.PAGE.initData.totalResults) || 0;
        _self.totalPages = Number(window.PAGE.initData.totalPages) || 1;
        _self.pageSize = Number(window.PAGE.initData.resultsPerPage) || _self.pageSizes[0];

        for (var i = 0; i < window.PAGE.initData.lists.length; i++) {
            _self.addItem(window.PAGE.initData.lists[i]);
        }
    } else {
        _self.getLists();
    }

}

define(
    'app/services/mailingListsService',[

        // Libraries
        "angular",
        "cjt/util/locale",
        "cjt/services/alertService"
    ],
    function(angular) {

        // Fetch the current application
        var app;
        try {
            app = angular.module("App"); // For runtime
        } catch (e) {
            app = angular.module("App", []); // Fall-back for unit testing
        }

        MailingListService.$inject = ["$rootScope", "alertService"];
        app.service("mailingListsService", MailingListService);
    }
);

/*
# share/apps/mailinglists/src/views/mailingListsController    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: false */

define(
    'app/controllers/mailingListsController',[
        "angular",
        "app/services/mailingListsService"
    ],
    function(angular) {

        // Fetch the current application
        var app;
        try {
            app = angular.module("App"); // For runtime
        } catch (e) {
            app = angular.module("App", []); // Fall-back for unit testing
        }

        /*
         * Creates a new MailingListsController
         * @class MailingListsController
         *
         * table view controller
         *
         */
        function MailingListsController($scope, MailingListService) {

            var _self = this;

            _self.model = MailingListService;

            _self.columnHeaders = [];

            /*
             * @method addColumn
             * builds column header object
             *
             * @param key {string} column key name (coorelates to api params)
             * @param name {string} Localized name used to label column
             */
            _self.addColumn = function(key, name) {
                _self.columnHeaders.push({
                    "key": key,
                    "name": name
                });
            };

            /*
             * @method getHeaders
             * get array of column headers
             *
             * @return {array} list of column objects {key:...,name:...}
             */
            _self.getHeaders = function() {
                return _self.columnHeaders;
            };

            /*
             * @method getLists
             * get array lists to display
             *
             * @return {array} list of MailingListItems
             */
            _self.getLists = function() {
                return _self.model.lists;
            };

            /*
             * add initial columns
             */
            _self.addColumn("list", LOCALE.maketext("List Name"));
            _self.addColumn("humandiskused", LOCALE.maketext("Usage"));
            _self.addColumn("accesstype", LOCALE.maketext("Access"));
            _self.addColumn("listadmin", LOCALE.maketext("Admin"));
            _self.addColumn("functions", LOCALE.maketext("Functions"));
        }

        MailingListsController.$inject = ["$scope", "mailingListsService"];
        app.controller("mailingListsController", MailingListsController);

    });

/*
# share/apps/mailinglists/src/views/mainController          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: false */

/* TABLE ControllerCode */

define(
    'app/controllers/mainController',[
        "angular",
        "app/services/mailingListsService",
        "cjt/directives/alertList",
        "cjt/filters/qaSafeIDFilter",
        "cjt/decorators/paginationDecorator"
    ],
    function(angular) {


        // Fetch the current application
        var app;
        try {
            app = angular.module("App"); // For runtime
        } catch (e) {
            app = angular.module("App", []); // Fall-back for unit testing
        }


        /*
         * Creates a new MainController
         * @class MainController
         *
         * serves the purpose of the table controller
         * and handles the inital loading of the lists
         *
         */
        function MainController($scope, MailingListService, spinnerAPI) {

            var _self = this;

            _self.model = MailingListService;
            _self.spinner = spinnerAPI;

            $scope.totalItems = _self.model.totalResults;
            $scope.currentPage = _self.model.page;

            /*
             * watches the loading param on the MalingListService
             * and shows or hides the spinner accordingly
             */
            $scope.$watch(function() {
                return _self.model.loading;
            }, function() {
                if (_self.model.loading) {
                    _self.spinner.start();
                } else {
                    _self.spinner.stop();
                }
            });

            /*
             * @method startSearch
             * wrapper function to start the search based on filter
             *
             */
            _self.startSearch = function() {
                _self.model.page = 0;
                _self.model.getLists();
            };

            /*
             * @method clearSearch
             * clear the filterValue and reload lists
             *
             */
            _self.clearSearch = function() {
                _self.model.filterValue = "";
                _self.model.selectPage(0);
            };

            $scope.$watch(function() {
                return _self.model.pageSize;
            }, function(newValue, oldValue) {

                if (newValue !== oldValue) {
                    _self.model.getLists();
                }
            });

            $scope.$watch(function() {
                return _self.model.filterValue;
            }, function(newValue, oldValue) {
                if (newValue !== "") {
                    _self.startSearch();
                } else if (newValue !== oldValue) {
                    _self.clearSearch();
                }
            });

        }

        MainController.$inject = ["$scope", "mailingListsService", "spinnerAPI"];
        app.controller("mainController", MainController);

    });

/*
# mail/lists/lists.js                                Copyright 2022 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 require: false, define: false */
/* jshint -W098 */

(function(window) {
    "use strict";

    var LOCALE = window.LOCALE,
        CPANEL = window.CPANEL,
        YAHOO = window.YAHOO,
        DOM = YAHOO.util.Dom,
        EVENT = YAHOO.util.Event,
        PAGE = window.CPANEL.PAGE;

    var Handlebars = window.Handlebars;

    var privacy_opts_maker;

    var record_by_email = {};

    if (PAGE.lists && PAGE.lists.length) {
        for (var l = PAGE.lists.length - 1; l >= 0; l--) {
            record_by_email[PAGE.lists[l].list] = PAGE.lists[l];
        }
    }

    // NOTE: Keep this in sync with Cpanel::Mailman!
    var PRIVATE_PRIVACY_OPTIONS = {
        advertised: false,
        archive_private: true,
        subscribe_policy: ["3", "2"]
    };

    /*
     * Submit handler that triggers when the "Proceed" button is pressed on "Edit Privacy Options" dialog
     *
     * @method privacy_opts_popup
     * @param {String} type The event type
     * @param {Array} args
     * @param {Object} obj The object returned on callback
     */

    function _privacy_opts_submit_handler(type, args, obj) {
        var dialog = obj.dialog;

        var params = CPANEL.dom.get_data_from_form(
            dialog.form, {
                include_unchecked_checkboxes: 0 // represents these as a "0"
            }
        );

        params.list = obj.list;

        CPANEL.api({
            version: 3,
            module: "Email",
            func: "set_list_privacy_options",
            data: params,

            callback: CPANEL.ajax.build_page_callback(function() {
                obj.onSuccess.call();
                dialog.destroy();
            }, {
                on_error: dialog.destroy.bind(dialog)
            })
        });
    }

    /* Sets the values in the "Edit Privacy Options" dialog based on existing object that should mirror Cpanel::Mailman
     *
     * @method _set_private_values_in_form
     */

    function _set_private_values_in_form() {
        /* jshint validthis: true */
        var clicked_el = this;

        var form = DOM.getAncestorByTagName(clicked_el, "form");
        var form_data = CPANEL.dom.get_data_from_form(form);

        for (var key in PRIVATE_PRIVACY_OPTIONS) {
            if (form[key].type === "checkbox") {
                form[key].checked = PRIVATE_PRIVACY_OPTIONS[key];
            } else {
                var acceptable = PRIVATE_PRIVACY_OPTIONS[key];
                if (!YAHOO.lang.isArray(acceptable)) {
                    acceptable = [acceptable];
                }

                if (acceptable.indexOf(form_data[key]) === -1) {
                    CPANEL.dom.set_form_el_value(form[key], acceptable[0]);
                }
            }
        }

        _update_access_type_text_in_form("private");
    }


    /*
     * Update the displayed access type in the access type dialog box.
     *
     * @method _update_access_type_text_in_form
     * @param {String} new_type The access type to translate and display.
     */

    function _update_access_type_text_in_form(new_type) {
        DOM.get("form_access_type").innerHTML = PAGE.translated_access_type[new_type];
    }


    /*
     * Re-evaluate and update the displayed access type in the access type dialog box.
     *
     * @method _reevaluate_access_type_in_form
     * @param {Event | null} evt The event that triggered this call. (unused)
     * @param {DOM} the_form The form DOM node to evaluate for public/private-setting.
     */

    function _reevaluate_access_type_in_form(evt, the_form) {
        var type = "private";
        var to_compare;

        var form_data = CPANEL.dom.get_data_from_form(the_form);

        for (var key in PRIVATE_PRIVACY_OPTIONS) {
            if (PRIVATE_PRIVACY_OPTIONS.hasOwnProperty(key)) {
                if (the_form[key].type === "checkbox") {
                    to_compare = !!form_data[key];
                } else {
                    to_compare = form_data[key];
                }

                var acceptable_for_private = PRIVATE_PRIVACY_OPTIONS[key];
                if (YAHOO.lang.isArray(acceptable_for_private)) {
                    if (acceptable_for_private.indexOf(to_compare) === -1) {
                        type = "public";
                    }
                } else if (to_compare !== acceptable_for_private) {
                    type = "public";
                }

                if (type === "public") {
                    break;
                }
            }
        }

        _update_access_type_text_in_form(type);
    }


    /*
     * Same as _reevaluate_access_type_in_form(), but with a slight delay
     * so that this can be used on reset() event listeners.
     *
     * @method _delayed_reevaluate_access_type_in_form
     * @param {Event | null} evt The event that triggered this call. (unused)
     * @param {DOM} the_form The form DOM node to evaluate for public/private-setting.
     */

    function _delayed_reevaluate_access_type_in_form(evt, the_form) {
        setTimeout(
            function() {
                _reevaluate_access_type_in_form(evt, the_form);
            },
            1
        );
    }

    /*
     * Show the popup of privacy options in the mailing list UI.
     *
     * @method privacy_opts_popup
     * @param {Object} list The list record.
     * @param {DOM} clicked_obj The DOM node that received the "click" that opens this popup.
     */

    function privacy_opts_popup(list, clicked_obj, successFunction) {

        if (!privacy_opts_maker) {
            privacy_opts_maker = Handlebars.compile(DOM.get("change_list_privacy_template").text.trim());
        }

        var dialog = new CPANEL.ajax.Common_Dialog(null, {
            close: true,
            show_status: true,
            status_html: LOCALE.maketext("Saving …")
        });

        dialog.setHeader(CPANEL.widgets.Dialog.applyDialogHeader(
            LOCALE.maketext("Edit Privacy Options: “[_1]”", list.list.html_encode())
        ));

        var list_record = list;
        var subscribe_policy = String(list_record.subscribe_policy);

        dialog.form.innerHTML = privacy_opts_maker({
            advertised: String(list_record.advertised) === "1",

            archive_private: String(list_record.archive_private) === "1",

            subscribe_policy_is_1: subscribe_policy === "1",
            subscribe_policy_is_2: subscribe_policy === "2",
            subscribe_policy_is_3: subscribe_policy === "3"
        });

        dialog.submitEvent.subscribe(
            _privacy_opts_submit_handler, {
                list: list.list.html_encode(),
                dialog: dialog,
                onSuccess: successFunction
            }
        );

        dialog.show_from_source(clicked_obj);

        _reevaluate_access_type_in_form(null, dialog.form);

        EVENT.on(dialog.form, "change", _reevaluate_access_type_in_form, dialog.form);
        EVENT.on(dialog.form, "reset", _delayed_reevaluate_access_type_in_form, dialog.form);

        var private_values_el = CPANEL.Y(dialog.form).one(".set-private-values");
        EVENT.on(private_values_el, "click", _set_private_values_in_form);
    }

    YAHOO.lang.augmentObject(window, {
        privacy_opts_popup: privacy_opts_popup
    });

    if (PAGE.notice) {
        PAGE.noticeHandle = new CPANEL.widgets.Page_Notice(PAGE.notice);
    }
}(window));

define(
    'app/lists',[
        "angular",
        "cjt/modules"
    ],
    function(angular) {
        "use strict";

        angular.module("App", ["ui.bootstrap", "cjt2.cpanel"]);

        /*
         * this looks funky, but these require that
         * angular be loaded before they can be loaded
         * so the nested requires become relevant
         */
        var app = require(
            [
                "cjt/directives/toggleSortDirective",
                "cjt/directives/spinnerDirective",
                "cjt/directives/searchDirective",
                "cjt/directives/pageSizeDirective",
                "app/services/mailingListsService",
                "app/controllers/mailingListsController",
                "app/controllers/mainController",
                "uiBootstrap"
            ],
            function() {

                var app = angular.module("App");

                /*
                 * filter used to escape emails and urls
                 * using native js escape
                 */
                app.filter("escape", function() {
                    return window.escape;
                });

                /* PrivacyWindowController */

                /*
                 * Creates a new PrivacyWindowController
                 * @class PrivacyWindowController
                 *
                 * serves as a controller to connect to the privacy window pop_up
                 *
                 */
                function PrivacyWindowController(mailingListsService) {
                    var _self = this;

                    /*
                     * @method closed
                     * callback on close of the popup
                     *
                     */
                    PrivacyWindowController.prototype.closed = function() {
                        mailingListsService.getLists();
                    };

                    /*
                     * @method open
                     * opens the popup
                     *
                     * @param list {object} lists item
                     * @param target {string} id of dom js target
                     *
                     */
                    PrivacyWindowController.prototype.open = function(list, target) {
                        window.privacy_opts_popup(list, target.currentTarget, _self.closed);
                    };
                }

                PrivacyWindowController.$inject = ["mailingListsService"];
                app.controller("PrivacyWindowController", PrivacyWindowController);

                /*
                 * because of the race condition with the dom loading and angular loading
                 * before the establishment of the app
                 * a manual initiation is required
                 * and the ng-app is left out of the dom
                 */
                app.init = function() {
                    var appContent = angular.element("#content");

                    if (appContent[0] !== null) {

                        // apply the app after requirejs loads everything
                        angular.bootstrap(appContent[0], ["App"]);
                    }

                    return app;
                };

                app.init();
            });

        return app;
    }
);

Back to Directory File Manager