Viewing File: /usr/local/cpanel/share/libraries/cjt2/src/models/searchSettingsModel.js

/*
# cjt/models/searchSettingsModel.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
*/

/**
 * Provides a factory method for generating a searchSettingsPanel
 * directive for a given environment.
 *
 * @module   cjt/directives/searchSettingsModel
 */

/* eslint-disable camelcase */
define(
    [
        "angular",
        "cjt/util/locale",
    ],
    function(angular, LOCALE) {
        "use strict";

        // Retrieve the current application
        var module = angular.module("cjt2.directives.searchSettingsModel", []);


        /**
         * @external ngFilter
         * @see {@link https://docs.angularjs.org/api/ng/filter/filter|$filter}
         */

        /**
          * @typedef {Object} SearchSettingOption
          * @property {String} label        label for the option. Should be localized.
          * @property {String} description  description of the option. Should be localized.
          * @property {String|Number} value value for the option
          */

        /**
          * The SearchSettingsModel consists of one or more of these objects.
          *
          * @typedef {Object} SearchSetting
          * @property {String} label     label for the setting.
          * @property {String} item_key  key to find the item in nvdata.
          * @property {SearchSettingOption[]} options list of options that can be selected
          */

        /**
         * Factory for creating a SearchSettingsModel
         *
         * @ngfactory SearchSettingsModel
         * @param  {ngFilter} $filter     Filter service from angularjs.
         * @return {SearchSettingsModel}  [description]
         */
        module.factory("SearchSettingsModel", ["$filter", function($filter) {

            /**
             *
             * @class SearchSettingsModel
             * @param {Object.<string, SearchSetting>} options set of options to be displayed by the SearchSettingsPanel which would look as follows:
             *
             *  {
             *      optionList2: {
             *          label: "This is the column label of the option",
             *          item_key: "this_is_the_reference_key_to_filter_on",
             *          options: [
             *              {
             *                  value: "value_item_key_must_be_if_this_is_selected",
             *                  label: "Label of the option listed on the panel",
             *                  description: "uib-tooltip description for option"
             *              }
             *              ...
             *          ]
             *      },
             *      ...
             *      optionList2: ...
             *  }
             *
             * @param  {Object.<string, Object>} option_values default values for specific options:
             *
             *  {
             *      uniqueOptionKey: {
             *          "value_item_key_must_be_if_this_is_selected": "default value"
             *          ...
             *      },
             *      ...
             *  }
             *
             * @return {SearchSettingsModel}
             *
             */
            function SearchSettingsModel(options, option_values) {

                var self = this;

                self.settings = null;
                self.settings_values = null;

                // Because option_values is optional
                option_values = option_values || {};

                /**
                 * Uses the originally passed "options" parameter to generate the
                 * initial settings and values.
                 *
                 * @method _initate_values
                 * @private
                 *
                 */
                self._initate_values = function _initate_values() {
                    if (self.settings) {
                        return true;
                    }
                    self.settings = {};
                    self.settings_values = {};
                    angular.forEach(options, function(setting, filterKey) {
                        self.settings[filterKey] = setting;
                        self.settings_values[filterKey] = {};
                        angular.forEach(setting.options, function(option) {
                            if (option_values[filterKey] && !angular.isUndefined(option_values[filterKey][option.value])) {
                                self.settings_values[filterKey][option.value] = option_values[filterKey][option.value];
                            } else {
                                self.settings_values[filterKey][option.value] = true;
                            }
                        });
                    });
                };

            }

            angular.extend(SearchSettingsModel.prototype, {

                /**
                 * Get the parsed settings object
                 *
                 * @method get_settings
                 * @return {Object} current settings object
                 */
                get_settings: function() {
                    this._initate_values();
                    return this.settings;
                },

                /**
                 * Get the current set values of the settings
                 *
                 * @method get_values
                 * @return {Object} Returns the settings values object. The values correlate to the options->value from the original options array.
                 *
                 *  {
                 *      uniqueOptionKey: {
                 *          "value_item_key_must_be_if_this_is_selected":true,
                 *          "value_item_key_must_be_if_this_is_selected2":true,
                 *          "value_item_key_must_be_if_this_is_selected3":true
                 *          ...
                 *      },
                 *      ...
                 *  }
                 *
                 */
                get_values: function() {
                    this._initate_values();
                    return this.settings_values;
                },

                /**
                 * Get a list of values for filtered items for a specific filterType
                 *
                 * @method get_filtered_values
                 * @param  {String} filterType The column for which you want to get the labels (correlates to the original options top level keys)
                 * @return {Array.<Any>} returns a flat array of values from a filterType.
                 *  [true, false, true, true, true]
                 *
                 */
                get_filtered_values: function(filterType) {
                    var self = this;
                    var filterOptions = self.settings[filterType];
                    var values = [];
                    var settings_values = self.get_values();

                    if (!settings_values) {
                        return [];
                    }

                    if (filterOptions) {
                        angular.forEach(filterOptions.options, function(option) {
                            if (settings_values[filterType][option.value]) {
                                values.push(option.value);
                            }
                        });
                    }

                    return values;
                },

                /**
                 * Get a list of display labels for filtered items for a specific filterType
                 *
                 * @method get_filtered_labels
                 * @param  {String} filterType The column for which you want to get the labels (correlates to the original options top level keys)
                 * @return {Array.<String>} returns a flat array of labels to display. If no items are filtered, the array is empty.
                 *  ["Lela", "Fry", "Bender"]
                 */
                get_filtered_labels: function(filterType) {
                    var self = this;
                    var filterOptions = self.settings[filterType];
                    var values = [];
                    var settings_values = self.get_values();

                    if (!settings_values) {
                        return [];
                    }

                    if (filterOptions) {
                        angular.forEach(filterOptions.options, function(option) {
                            if (settings_values[filterType][option.value]) {
                                values.push(option.label);
                            }
                        });

                        // so that we don't display the label if we're showing "all", but we don't have to relay on in-dom logic
                        if (values.length === filterOptions.options.length) {
                            return [];
                        }
                    }

                    return values.length ? values : [LOCALE.maketext("None")];
                },

                /**
                 * Set all the items in a column to a value
                 *
                 * @method set_search_filter_values
                 * @param  {String} filterKey The column for which you want to update the values (correlates to the original options top level keys)
                 * @param  {*} filterValue new value to set the items to
                 * @return {None} does not return a value
                 */
                set_search_filter_values: function(filterKey, filterValue) {
                    var self = this;
                    angular.forEach(self.settings_values[filterKey], function(option, key) {
                        self.settings_values[filterKey][key] = filterValue;
                    });
                },

                /**
                 * Isolate a specific item in a filter to display only that one
                 *
                 * @method show_only
                 * @param  {String} filterKey key associated with the column
                 * @param  {String} itemKey key associated with the row in the column
                 * @return {None} None
                 */
                show_only: function(filterKey, itemKey) {
                    var self = this;

                    self.set_search_filter_values(filterKey, false);
                    if (self.settings_values[filterKey]) {
                        self.settings_values[filterKey][itemKey] = true;
                    }
                },

                /**
                 * This is the hook function used to filter the items list. It will use the existing setting_values and compare them to the item value key
                 *
                 * @method filter
                 * @param  {Array} items An array of items to filter based on each of the options in the panel
                 *
                 *  [
                 *      {
                 *          key: value, // where 'key' correlates the the 'item_key' established by each column in the initial options array
                 *          key2: value
                 *      }
                 *  ]
                 *
                 * @return {Array} filtered version of the passed in items array
                 *
                 */
                filter: function(items) {

                    var typesToFilter = {};
                    var self = this;

                    angular.forEach(self.settings, function(searchFilterOption, filterKey) {
                        var true_values = [];
                        angular.forEach(searchFilterOption.options, function(option) {

                            // One of the options isn't selected; filter based on it
                            if (self.settings_values[filterKey][option.value]) {
                                true_values.push(option.value);
                            }
                        });

                        // lengths are not equal; some are disabled.
                        if (true_values.length !== searchFilterOption.options.length) {

                            // store in keyed values for faster lookup
                            typesToFilter[filterKey] = {};
                            angular.forEach(true_values, function(true_value) {
                                typesToFilter[filterKey][true_value] = 1;
                            });
                        }
                    });

                    return $filter("filter")(items, function(item) {

                        for (var settingKey in typesToFilter) {
                            if (typesToFilter.hasOwnProperty(settingKey)) {
                                var itemKey = self.settings[settingKey].item_key;
                                var itemValue = item[itemKey];

                                // value doesn't exist in the allowed and filtered values
                                if (!self.settings_values[settingKey][itemValue]) {
                                    return false;
                                }
                            }
                        }

                        return true;
                    });
                }
            });

            return SearchSettingsModel;

        }]);
    }
);
Back to Directory File Manager