| /*
 * Pim
 * Free Extension
 * Copyright (c) TreoLabs GmbH
 * Copyright (c) Kenner Soft Service GmbH
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
Espo.define('pim:views/product/record/search', ['views/record/search', 'search-manager'],
    (Dep, SearchManager) => Dep.extend({
        template: 'pim:product/record/search',
        familiesAttributes: [],
        attributesDownloaded: false,
        selectedAttributesWithOneFilter: [],
        events: _.extend({}, Dep.prototype.events, {
            'click a[data-action="addAttributeFilter"]': function (e) {
                var $target = $(e.currentTarget);
                var id = $target.data('id');
                var nameCount = 1;
                var getLastIndexName = function () {
                    if (this.advanced.hasOwnProperty(id + '-' + nameCount)) {
                        nameCount++;
                        getLastIndexName.call(this);
                    }
                };
                getLastIndexName.call(this);
                let compiledName = id + '-' + nameCount;
                this.advanced[compiledName] = {};
                this.advanced = this.sortAdvanced(this.advanced);
                this.presetName = this.primary;
                let params = this.getAttributeParams(compiledName);
                if (this.typesWithOneFilter.includes(params.fieldParams.type) && !this.selectedAttributesWithOneFilter.includes(id)) {
                    this.selectedAttributesWithOneFilter.push(id);
                }
                this.createAttributeFilter(compiledName, params, function (view) {
                    view.populateDefaults();
                    this.fetch();
                    this.updateSearch();
                }.bind(this));
                this.updateAddAttributeFilterButton();
                this.updateExpandListButtonInFamily();
                this.handleLeftDropdownVisibility();
                this.manageLabels();
            },
            'click .advanced-filters a.remove-attribute-filter': function (e) {
                var $target = $(e.currentTarget);
                var name = $target.data('name');
                this.selectedAttributesWithOneFilter.splice(this.selectedAttributesWithOneFilter.indexOf($target.data('id')), 1);
                this.$el.find('a[data-id="' + name.split('-')[0] + '"]').parent().removeClass('hide');
                var container = this.getView('filter-' + name).$el.closest('div.filter');
                this.clearView('filter-' + name);
                container.remove();
                delete this.advanced[name];
                this.presetName = this.primary;
                this.updateAddAttributeFilterButton();
                this.updateExpandListButtonInFamily();
                this.fetch();
                this.updateSearch();
                this.manageLabels();
                this.handleLeftDropdownVisibility();
                this.setupOperatorLabels();
            },
            'click .dropdown-menu a[data-action="savePreset"]': function () {
                this.createView('savePreset', 'Modals.SaveFilters', {}, function (view) {
                    view.render();
                    this.listenToOnce(view, 'save', function (name) {
                        this.savePreset(name);
                        view.close();
                        this.removeFilters();
                        this.createFilters(function () {
                            this.render();
                        }.bind(this));
                    }, this);
                }.bind(this));
            },
            'click .dropdown-submenu > a.add-attribute-filter-button': function (e) {
                e.stopPropagation();
                e.preventDefault();
                let a = $(e.currentTarget);
                a.parents('.dropdown-menu').find('> .dropdown-submenu > a:not(.add-attribute-filter-button)').next('ul').toggle(false);
                if (this.attributesDownloaded) {
                    a.next('ul').toggle();
                } else {
                    if (this.getAcl().check('Attribute', 'read')) {
                        this.$el.find('.family-list .no-family-data').text(this.translate('Loading...', 'labels', 'Global'));
                        this.$el.find('.family-list').toggle();
                        this.ajaxGetRequest('Markets/Attribute/filtersData')
                            .then(response => {
                                this.attributesDownloaded = true;
                                this.familiesAttributes = response;
                            })
                            .always(() => {
                                this.listenToOnce(this, 'after:render', () => {
                                    this.$el.find('.left-dropdown').addClass('open');
                                    this.$el.find('.family-list').toggle();
                                });
                                this.reRender();
                            });
                    }
                }
            },
            'click .dropdown-submenu a.expand-list': function (e) {
                $(e.target).next('ul').toggle();
                e.stopPropagation();
                e.preventDefault();
            }
        }),
        data() {
            var data = Dep.prototype.data.call(this);
            data.familiesAttributes = this.familiesAttributes;
            data.showFamiliesAttributes = this.getAcl().check('Attribute', 'read');
            return data;
        },
        hideAttributesWithOneFilter() {
            this.familiesAttributes.some(family => family.rows.some(row => {
                if (this.selectedAttributesWithOneFilter.includes(row.attributeId)) {
                    this.$el.find(`a[data-id="${row.attributeId}"]`).parent().addClass('hide');
                }
            }));
        },
        getAttributeParams(name) {
            let params = {
                isAttribute: true
            };
            this.familiesAttributes.some(family => family.rows.some(row => {
                if (row.attributeId === name.split('-')[0]) {
                    params.label = row.name;
                    params.type = row.type;
                    if (['enum', 'multiEnum'].includes(row.type)) {
                        params.isTypeValue = true;
                        params.options = row.typeValue;
                        row.typeValue.forEach(value => {
                            params.translatedOptions = params.translatedOptions || {};
                            params.translatedOptions[value] = this.getLanguage().translateOption(value, row.name, 'Attribute');
                        });
                    }
                    return true;
                }
            }));
            return {fieldParams: params};
        },
        fetch: function () {
            this.textFilter = (this.$el.find('input[name="textFilter"]').val() || '').trim();
            this.bool = {};
            this.boolFilterList.forEach(function (name) {
                this.bool[name] = this.$el.find('input[name="' + name + '"]').prop('checked');
            }, this);
            for (var field in this.advanced) {
                var view = this.getView('filter-' + field).getView('field');
                let fieldParams = this.advanced[field].fieldParams || {};
                this.advanced[field] = view.fetchSearch();
                if (fieldParams.isAttribute) {
                    this.advanced[field].fieldParams = fieldParams;
                }
                this.familiesAttributes.forEach(function (family) {
                    family.rows.forEach(function (row) {
                        let name = field.split('-')[0];
                        if (row.attributeId === name) {
                            if (this.advanced[field] === false) {
                                this.advanced[field] = {};
                            }
                            this.advanced[field] = _.extend(this.getAttributeParams(name), this.advanced[field]);
                        }
                    }, this);
                }, this);
                view.searchParams = this.advanced[field];
            }
        },
        updateCollection() {
            const defaultFilters = this.searchManager.get();
            const catalogTreeData = this.getCatalogTreeData();
            let extendedFilters = _.extend(Espo.Utils.cloneDeep(defaultFilters), catalogTreeData);
            this.searchManager.set(extendedFilters);
            Dep.prototype.updateCollection.call(this);
            this.searchManager.set(defaultFilters);
        },
        getCatalogTreeData() {
            let result = {};
            const list = this.getParentView();
            if (list) {
                const treePanel = list.getView('catalogTreePanel');
                if (treePanel && treePanel.catalogTreeData) {
                    result = treePanel.catalogTreeData;
                }
            }
            return result;
        },
        resetFilters() {
            Dep.prototype.resetFilters.call(this);
            this.selectedAttributesWithOneFilter = [];
            this.$el.find('.family-list li.hide').removeClass('hide');
        },
        updateAddAttributeFilterButton: function () {
            var $ul = this.$el.find('ul.family-list');
            if ($ul.children().not('.hide').size() == 0) {
                this.$el.find('a.add-attribute-filter-button').addClass('disabled');
            } else {
                this.$el.find('a.add-attribute-filter-button').removeClass('disabled');
            }
        },
        updateExpandListButtonInFamily: function () {
            this.$el.find('ul.attribute-filter-list').each((i, el) => {
                let ul = $(el);
                if (ul.children().not('.hide').size() === 0) {
                    ul.parent().find('a.expand-list').addClass('hide');
                } else {
                    ul.parent().find('a.expand-list').removeClass('hide');
                }
            });
        },
        afterRender: function () {
            Dep.prototype.afterRender.call(this);
            this.updateAddAttributeFilterButton();
            this.updateExpandListButtonInFamily();
            this.addAutoCompleteToAttributeSearch();
            this.hideAttributesWithOneFilter();
        },
        addAutoCompleteToAttributeSearch() {
            let attrSearchElement = this.$el.find('.attribute-text-filter');
            if (attrSearchElement.length) {
                let attributes = [];
                (this.familiesAttributes || []).forEach(family => {
                    (family.rows || []).forEach(attribute => {
                        if (!attributes.find(item => (item.data || {}).attributeId === attribute.attributeId)) {
                            attributes.push({value: attribute.name, data: attribute});
                        }
                    });
                });
                attrSearchElement.autocomplete({
                    appendTo: attrSearchElement.parents('ul.family-list'),
                    lookup: attributes,
                    paramName: 'q',
                    minChars: 1,
                    onSelect: function (s) {
                        attrSearchElement.val('');
                        var name = (s.data || {}).attributeId;
                        var nameCount = 1;
                        var getLastIndexName = function () {
                            if (this.advanced.hasOwnProperty(
                                name + '-' + nameCount)) {
                                nameCount++;
                                getLastIndexName.call(this);
                            }
                        };
                        getLastIndexName.call(this);
                        name = name + '-' + nameCount;
                        this.advanced[name] = {};
                        this.advanced = this.sortAdvanced(this.advanced);
                        this.presetName = this.primary;
                        this.createAttributeFilter(name, this.getAttributeParams(name), function (view) {
                            view.populateDefaults();
                            this.fetch();
                            this.updateSearch();
                        }.bind(this));
                        this.updateAddAttributeFilterButton();
                        this.updateExpandListButtonInFamily();
                        this.handleLeftDropdownVisibility();
                        this.manageLabels();
                    }.bind(this)
                });
                $(attrSearchElement.autocomplete().suggestionsContainer).css({top: attrSearchElement.outerHeight(true)});
                this.once('render remove', function () {
                    attrSearchElement.autocomplete('dispose');
                    attrSearchElement.val('');
                }, this);
                this.listenToOnce(this.getRouter(), 'routed', () => {
                    attrSearchElement.autocomplete('dispose');
                    attrSearchElement.val('');
                });
                this.$el.find('.add-attribute-filter-button').click(function () {
                    attrSearchElement.autocomplete().hide();
                    attrSearchElement.val('');
                });
            }
        },
        createFilter: function (name, params, callback, noRender) {
            if (((params || {}).fieldParams || {}).isAttribute) {
                this.createAttributeFilter(name, params, callback);
            } else {
                Dep.prototype.createFilter.call(this, name, params, callback, noRender);
            }
        },
        createAttributeFilter: function (name, params, callback) {
            params = params || {};
            if (this.isRendered() && !this.$advancedFiltersPanel.find(`.filter.filter-${name}`).length) {
                var div = document.createElement('div');
                div.className = "filter filter-" + name + " col-sm-4 col-md-3";
                div.setAttribute("data-name", name);
                var nameIndex = name.split('-')[1];
                var beforeFilterName = name.split('-')[0] + '-' + (+nameIndex - 1);
                var beforeFilter = this.$advancedFiltersPanel.find('.filter.filter-' + beforeFilterName + '.col-sm-4.col-md-3')[0];
                var afterFilterName = name.split('-')[0] + '-' + (+nameIndex + 1);
                var afterFilter = this.$advancedFiltersPanel.find('.filter.filter-' + afterFilterName + '.col-sm-4.col-md-3')[0];
                if (beforeFilter) {
                    var nextFilter = beforeFilter.nextElementSibling;
                    if (nextFilter) {
                        this.$advancedFiltersPanel[0].insertBefore(div, beforeFilter.nextElementSibling);
                    } else {
                        this.$advancedFiltersPanel[0].appendChild(div);
                    }
                } else if (afterFilter) {
                    this.$advancedFiltersPanel[0].insertBefore(div, afterFilter);
                } else {
                    this.$advancedFiltersPanel[0].appendChild(div);
                }
            }
            this.createView('filter-' + name, 'pim:views/product/search/filter', {
                name: name,
                model: this.model,
                params: params.fieldParams,
                searchParams: params,
                el: this.options.el + ' .filter[data-name="' + name + '"]'
            }, function (view) {
                if (!this.selectedAttributesWithOneFilter.includes(name.split('-')[0])) {
                    this.selectedAttributesWithOneFilter.push(name.split('-')[0]);
                }
                this.hideAttributesWithOneFilter();
                if (typeof callback === 'function') {
                    view.once('after:render', function () {
                        callback(view);
                    });
                }
                if (this.isRendered()) {
                    view.listenToOnce(view, 'after:render', () => {
                        this.setupOperatorLabels();
                    });
                }
                view.render();
            }.bind(this));
        },
        selectPreset: function (presetName, forceClearAdvancedFilters) {
            var wasPreset = !(this.primary == this.presetName);
            this.presetName = presetName;
            var advanced = this.getPresetData();
            this.primary = this.getPrimaryFilterName();
            var isPreset = !(this.primary === this.presetName);
            if (forceClearAdvancedFilters || wasPreset || isPreset || Object.keys(advanced).length) {
                this.removeFilters();
                this.advanced = advanced;
            }
            this.updateSearch();
            this.manageLabels();
            this.createFilters();
            this.reRender();
            this.updateCollection();
        },
        updateCollection() {
            const defaultFilters = Espo.Utils.cloneDeep(this.searchManager.get());
            const list = this.getParentView();
            const catalogTreePanel = list.getView('catalogTreePanel');
            if (catalogTreePanel && catalogTreePanel.catalogTreeData) {
                const extendedFilters = Espo.Utils.cloneDeep(defaultFilters);
                $.each(catalogTreePanel.catalogTreeData, (key, value) => {
                    extendedFilters[key] = _.extend({}, extendedFilters[key], value);
                });
                this.searchManager.set(extendedFilters);
            }
            Dep.prototype.updateCollection.call(this);
            this.searchManager.set(defaultFilters);
        }
    })
);
 |