<commit_before>/* 
 * Copyright (C) 2012-2016 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/* global Ext, FlamingoAppLoader, actionBeans */

/**
 * Print component
 * Creates a AttributeList component
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */

/**
 * In debug mode this definition triggers an error from Ext,
 * seems like a bug that has been solved but maybe not in the GPL version of Ext yet
 * http://www.sencha.com/forum/showthread.php?283775-Cannot-subclass-a-Model-properly
 * For now we used the 'fields' config option in the store instead of a model

Ext.define('Doc', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'label', type: 'string' },
        { name: 'searchConfig', type: 'integer' }
    ]
});

 */

Ext.define ("viewer.components.Search",{
    extend: "viewer.components.Component",
    form: null,
    mainContainer: null,
    searchResult: null,
    results: null,
    autosuggestStore:null,
    searchField:null,
    searchName:null,
    resultPanelId: '',
    searchRequestId: 0,
    onlyUrlConfig:null,
    currentSeachId:null,
    dynamicSearchEntries:null,
    loadingContainer: null,
    showSearchButtons: true,
    simpleSearchResults: false,
    searchFieldTriggers: null,
    pickerAlignment: "tl-bl?", // Ext default
    config:{
        title: null,
        iconUrl: null,
        tooltip: null,
        searchconfigs: null,
        formHeight:null,
        label: "",
        marker: "default",
        //not yet configurable:
        showRemovePin: true,
        details: {
            minWidth: 400,
            minHeight: 400
        }
    },
    constructor: function (conf){
        conf.details.useExtLayout = true;
        this.initConfig(conf);
		viewer.components.Search.superclass.constructor.call(this, this.config);
        this.renderButton(); 
        var notUrlConfigs = [];
        this.onlyUrlConfig = [];
        if(this.config.searchconfigs === null) {
            this.config.searchconfigs = [];
        }
        for(var i = 0 ; i < this.config.searchconfigs.length ;i++){
            var config = this.config.searchconfigs[i];
            if(Ext.isDefined(config.urlOnly) && config.urlOnly ){
                this.onlyUrlConfig.push(config);
            }else{
                notUrlConfigs.push(config);
            }
        }
        this.searchconfigs = notUrlConfigs; 
        this.currentSeachId = this.searchconfigs.length > 0 ? this.searchconfigs[0].id : null; 
        this.dynamicSearchEntries = [];
        this.loadWindow();
        return this;
    },
    renderButton: function() {
        var me = this;
        viewer.components.Search.superclass.renderButton.call(this,{
            text: me.config.title,
            icon: me.config.iconUrl,
            tooltip: me.config.tooltip,
            label: me.config.label,
            handler: function() {
                me.popup.show();
                if(me.searchField) {
                    me.searchField.focus();
                }
            }
        });
    },
    loadWindow : function(){
        var me = this;
        if(this.form){
            this.form.destroy();
        }
        this.form = Ext.create("Ext.form.Panel",{
            frame: false,
            height: this.config.formHeight,
            padding: 0,
            items: this.getFormItems(),
            border: 0,
            layout: {
                type: 'vbox',
                align: 'stretch'
            }
        });

        this.resultPanel = Ext.create('Ext.container.Container', {
            xtype: "container",
            flex: 1,
            componentCls: 'resultPanel',
            scrollable: true
        });

        var options = {
            title: this.getPanelTitle(),
            tools: this.getHelpToolConfig(),
            itemId: this.name + 'Container',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            style: {
                backgroundColor: 'White'
            },
            items: [ this.form, this.resultPanel ]
        };
        if(!this.config.isPopup) {
            options.bodyPadding = this.config.viewerController.layoutManager.isTabComponent(this.name) ? '10 0 10 10' : '10 5 10 5';
        } else {
            options.items.push({
                itemId: this.name + 'ClosingPanel',
                xtype: "container",
                style: {
                    marginTop: '5px',
                    marginRight: '5px'
                },
                layout: {
                    type:'hbox',
                    pack:'end'
                },
                items: [
                    {xtype: 'button', text: i18next.t('viewer_components_search_0'), handler: function() {
                        me.popup.hide();
                    }}
                ]
            });
        }
        this.mainContainer = Ext.create(this.config.isPopup ? 'Ext.container.Container' : 'Ext.panel.Panel', options);
        if(this.config.isPopup) {
            this.popup.getContentContainer().add(this.mainContainer);
        } else {
            this.getContentContainer().add(this.mainContainer);
        }
        this.form.query("#cancel"+ this.name)[0].setVisible(false);
        this.loadingContainer = this.resultPanel;
    },
    getFormItems: function(){
        var me = this;
        var itemList = [];
        if (this.searchconfigs) {
            var configs = Ext.create('Ext.data.Store', {
                fields: ['id', 'name', 'url'],
                data: this.searchconfigs
            });
            this.searchName = Ext.create('Ext.form.ComboBox',{
                fieldLabel: i18next.t('viewer_components_search_1'),
                store: configs,
                queryMode: 'local',
                hidden: this.searchconfigs.length === 1,
                displayField: 'name',
                valueField: 'id',
                anchor: '100%',
                emptyText: i18next.t('viewer_components_search_2'),
                name: 'searchName' + this.name,
                itemId: 'searchName' + this.name,
                value: this.searchconfigs.length > 0 ? this.searchconfigs[0].id : null,
                listeners: {
                    change: {
                        fn: function(combo, newValue) {
                            this.searchConfigChanged(newValue);
                        },
                        scope: this
                    }
                }
            });
            itemList.push(this.searchName);
            if (this.searchconfigs.length> 0){
                var queryMode = 'local';
                var extraParams = {};
                if(this.searchconfigs.length === 1 && (this.searchconfigs[0].type === "solr" || this.searchconfigs[0].type === "pdok" ) ){
                    queryMode = "remote";
                    
                    extraParams["searchName"]=this.searchconfigs[0].id;
                    extraParams["appId"]= FlamingoAppLoader.get("appId");
                    extraParams["componentName"]=this.name;
                }
                this.autosuggestStore = Ext.create('Ext.data.Store',  {
                    autoLoad: false,
                    fields: ['label', 'searchConfig', 'type'],
                    // model: 'Doc',
                    proxy: {
                        type: 'ajax',
                        url: actionBeans["autosuggest"],
                        extraParams: extraParams,
                        reader: {
                            type: 'json',
                            rootProperty: 'results'
                        }
                    }
                });
                this.searchField = Ext.create( Ext.form.field.ComboBox,{ 
                    name: 'searchfield',
                    hideTrigger: me.searchFieldTriggers === null,
                    triggers: me.searchFieldTriggers === null ? {} : me.searchFieldTriggers,
                    flex: 1,
                    margin: this.showSearchButtons ? '0 1 0 0' : 0,
                    editable: true,
                    triggerAction: 'query',
                    queryParam: "searchText",
                    autoSelect:false,
                    displayField: "label",
                    queryMode: queryMode,
                    itemId: 'searchfield' + this.name,
                    minChars: 2,
                    pickerAlign: this.pickerAlignment,
                    listConfig: {
                        maxHeight: this.getPickerMaxHeight(),
                        listeners:{
                            itemclick:function(list, node){
                                this.searchHighlightedSuggestion(node);
                            },
                            scope:me
                        }
                    },
                    listeners: {
                        specialkey: function(field, e){
                            if (e.getKey() === e.ENTER) {
                                var item = null;
                                if(field.picker && field.picker.highlightedItem && !me.simpleSearchResults){
                                    item = field.picker.highlightedItem;
                                }
                                if(!item){
                                    me.search();
                                }
                            }
                        },
                        beforeQuery : function(request){
                            if(this.getCurrentSearchType() !== "solr" && this.getCurrentSearchType() !== "pdok" ){
                                    return false;
                            }
                            var q = request.query;
                            var combo = request.combo;
                            var minChars = combo.minChars;
                            if(q.length >= minChars){
                                this.setVisibleLayers();
                            }
                        },
                        scope:this
                    },
                    store:this.autosuggestStore
                });
                Ext.view.BoundListKeyNav.override({
                    selectHighlighted: function() {
                        if(!this.record) {
                            me.search();
                            return;
                        }
                        //If an item is selected, the user did that. So go directly to that result. Otherwise search with the user typed string
                        me.searchHighlightedSuggestion(this.record);
                    }
                });
                
                var searchFieldAndButton = Ext.create('Ext.container.Container', {
                    layout: {
                        type: this.showSearchButtons ? 'hbox' : 'fit'
                    },
                    scrollable: false,
                    padding: '0 1 0 0',
                    items: [
                        this.searchField,
                        {
                            xtype: 'button',
                            text: i18next.t('viewer_components_search_3'),
                            hidden: !this.showSearchButtons,
                            listeners: {
                                click: {
                                    scope: this,
                                    fn: this.search
                                }
                            }
                        }
                    ]
                });
                itemList.push(searchFieldAndButton);
            }
        }
        itemList.push({ 
            xtype: 'button',
            text: i18next.t('viewer_components_search_4'),
            name: 'cancel',
            itemId: 'cancel'+ this.name,
            hidden: !this.showSearchButtons,
            listeners: {
                click:{
                    scope: this,
                    fn: this.cancel
                }
            }
        });
        //remove pin button
        itemList.push({
            xtype: 'button',
            text: i18next.t('viewer_components_search_5'),
            name: 'removePin',
            itemId: 'removePin'+ this.name,
            hidden: true,
            listeners: {
                click: {
                    scope: this,
                    fn: this.removePin
                }
            }
            
        });
        return itemList;
    },
    getPickerMaxHeight: function() {
        var viewportHeight = Ext.dom.Element.getViewportHeight();
        if(viewportHeight < 600) {
            return Math.floor(viewportHeight * 0.5);
        }
        return 300; // default
    },
    searchHighlightedSuggestion: function(node){
        var data = node.raw !== undefined ? node.raw : node.data;
        this.searchField.setValue(data.originalLabel || data.label);
        if(data.location){
            this.handleSearchResult(data);
            this.searchField.collapse();
        }else{
            this.search();
        }
    },
    hideWindow : function(){
        this.searchField.collapse();
        this.popup.hide();
    },
    search : function(){
        this.searchRequestId++;
        if(this.results !== null){
            this.results.destroy();
        }
        this.searchField.getPicker().hide();
        var searchText = Ext.ComponentQuery.query( "#searchfield" + this.name)[0].getValue();
        var searchName = '';
        if(this.searchconfigs.length === 1){
            searchName = this.searchconfigs[0].id;
        }else{
            searchName = this.form.query("#searchName" + this.name)[0].getValue();<commit_msg>Clear other search results when using autosuggest search (mantis #13268)<commit_after>/* 
 * Copyright (C) 2012-2016 B3<EMAIL>ners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/* global Ext, FlamingoAppLoader, actionBeans */

/**
 * Print component
 * Creates a AttributeList component
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */

/**
 * In debug mode this definition triggers an error from Ext,
 * seems like a bug that has been solved but maybe not in the GPL version of Ext yet
 * http://www.sencha.com/forum/showthread.php?283775-Cannot-subclass-a-Model-properly
 * For now we used the 'fields' config option in the store instead of a model

Ext.define('Doc', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'label', type: 'string' },
        { name: 'searchConfig', type: 'integer' }
    ]
});

 */

Ext.define ("viewer.components.Search",{
    extend: "viewer.components.Component",
    form: null,
    mainContainer: null,
    searchResult: null,
    results: null,
    autosuggestStore:null,
    searchField:null,
    searchName:null,
    resultPanelId: '',
    searchRequestId: 0,
    onlyUrlConfig:null,
    currentSeachId:null,
    dynamicSearchEntries:null,
    loadingContainer: null,
    showSearchButtons: true,
    simpleSearchResults: false,
    searchFieldTriggers: null,
    pickerAlignment: "tl-bl?", // Ext default
    config:{
        title: null,
        iconUrl: null,
        tooltip: null,
        searchconfigs: null,
        formHeight:null,
        label: "",
        marker: "default",
        //not yet configurable:
        showRemovePin: true,
        details: {
            minWidth: 400,
            minHeight: 400
        }
    },
    constructor: function (conf){
        conf.details.useExtLayout = true;
        this.initConfig(conf);
		viewer.components.Search.superclass.constructor.call(this, this.config);
        this.renderButton(); 
        var notUrlConfigs = [];
        this.onlyUrlConfig = [];
        if(this.config.searchconfigs === null) {
            this.config.searchconfigs = [];
        }
        for(var i = 0 ; i < this.config.searchconfigs.length ;i++){
            var config = this.config.searchconfigs[i];
            if(Ext.isDefined(config.urlOnly) && config.urlOnly ){
                this.onlyUrlConfig.push(config);
            }else{
                notUrlConfigs.push(config);
            }
        }
        this.searchconfigs = notUrlConfigs; 
        this.currentSeachId = this.searchconfigs.length > 0 ? this.searchconfigs[0].id : null; 
        this.dynamicSearchEntries = [];
        this.loadWindow();
        return this;
    },
    renderButton: function() {
        var me = this;
        viewer.components.Search.superclass.renderButton.call(this,{
            text: me.config.title,
            icon: me.config.iconUrl,
            tooltip: me.config.tooltip,
            label: me.config.label,
            handler: function() {
                me.popup.show();
                if(me.searchField) {
                    me.searchField.focus();
                }
            }
        });
    },
    loadWindow : function(){
        var me = this;
        if(this.form){
            this.form.destroy();
        }
        this.form = Ext.create("Ext.form.Panel",{
            frame: false,
            height: this.config.formHeight,
            padding: 0,
            items: this.getFormItems(),
            border: 0,
            layout: {
                type: 'vbox',
                align: 'stretch'
            }
        });

        this.resultPanel = Ext.create('Ext.container.Container', {
            xtype: "container",
            flex: 1,
            componentCls: 'resultPanel',
            scrollable: true
        });

        var options = {
            title: this.getPanelTitle(),
            tools: this.getHelpToolConfig(),
            itemId: this.name + 'Container',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            style: {
                backgroundColor: 'White'
            },
            items: [ this.form, this.resultPanel ]
        };
        if(!this.config.isPopup) {
            options.bodyPadding = this.config.viewerController.layoutManager.isTabComponent(this.name) ? '10 0 10 10' : '10 5 10 5';
        } else {
            options.items.push({
                itemId: this.name + 'ClosingPanel',
                xtype: "container",
                style: {
                    marginTop: '5px',
                    marginRight: '5px'
                },
                layout: {
                    type:'hbox',
                    pack:'end'
                },
                items: [
                    {xtype: 'button', text: i18next.t('viewer_components_search_0'), handler: function() {
                        me.popup.hide();
                    }}
                ]
            });
        }
        this.mainContainer = Ext.create(this.config.isPopup ? 'Ext.container.Container' : 'Ext.panel.Panel', options);
        if(this.config.isPopup) {
            this.popup.getContentContainer().add(this.mainContainer);
        } else {
            this.getContentContainer().add(this.mainContainer);
        }
        this.form.query("#cancel"+ this.name)[0].setVisible(false);
        this.loadingContainer = this.resultPanel;
    },
    getFormItems: function(){
        var me = this;
        var itemList = [];
        if (this.searchconfigs) {
            var configs = Ext.create('Ext.data.Store', {
                fields: ['id', 'name', 'url'],
                data: this.searchconfigs
            });
            this.searchName = Ext.create('Ext.form.ComboBox',{
                fieldLabel: i18next.t('viewer_components_search_1'),
                store: configs,
                queryMode: 'local',
                hidden: this.searchconfigs.length === 1,
                displayField: 'name',
                valueField: 'id',
                anchor: '100%',
                emptyText: i18next.t('viewer_components_search_2'),
                name: 'searchName' + this.name,
                itemId: 'searchName' + this.name,
                value: this.searchconfigs.length > 0 ? this.searchconfigs[0].id : null,
                listeners: {
                    change: {
                        fn: function(combo, newValue) {
                            this.searchConfigChanged(newValue);
                        },
                        scope: this
                    }
                }
            });
            itemList.push(this.searchName);
            if (this.searchconfigs.length> 0){
                var queryMode = 'local';
                var extraParams = {};
                if(this.searchconfigs.length === 1 && (this.searchconfigs[0].type === "solr" || this.searchconfigs[0].type === "pdok" ) ){
                    queryMode = "remote";
                    
                    extraParams["searchName"]=this.searchconfigs[0].id;
                    extraParams["appId"]= FlamingoAppLoader.get("appId");
                    extraParams["componentName"]=this.name;
                }
                this.autosuggestStore = Ext.create('Ext.data.Store',  {
                    autoLoad: false,
                    fields: ['label', 'searchConfig', 'type'],
                    // model: 'Doc',
                    proxy: {
                        type: 'ajax',
                        url: actionBeans["autosuggest"],
                        extraParams: extraParams,
                        reader: {
                            type: 'json',
                            rootProperty: 'results'
                        }
                    }
                });
                this.searchField = Ext.create( Ext.form.field.ComboBox,{ 
                    name: 'searchfield',
                    hideTrigger: me.searchFieldTriggers === null,
                    triggers: me.searchFieldTriggers === null ? {} : me.searchFieldTriggers,
                    flex: 1,
                    margin: this.showSearchButtons ? '0 1 0 0' : 0,
                    editable: true,
                    triggerAction: 'query',
                    queryParam: "searchText",
                    autoSelect:false,
                    displayField: "label",
                    queryMode: queryMode,
                    itemId: 'searchfield' + this.name,
                    minChars: 2,
                    pickerAlign: this.pickerAlignment,
                    listConfig: {
                        maxHeight: this.getPickerMaxHeight(),
                        listeners:{
                            itemclick:function(list, node){
                                this.searchHighlightedSuggestion(node);
                            },
                            scope:me
                        }
                    },
                    listeners: {
                        specialkey: function(field, e){
                            if (e.getKey() === e.ENTER) {
                                var item = null;
                                if(field.picker && field.picker.highlightedItem && !me.simpleSearchResults){
                                    item = field.picker.highlightedItem;
                                }
                                if(!item){
                                    me.search();
                                }
                            }
                        },
                        beforeQuery : function(request){
                            if(this.getCurrentSearchType() !== "solr" && this.getCurrentSearchType() !== "pdok" ){
                                    return false;
                            }
                            var q = request.query;
                            var combo = request.combo;
                            var minChars = combo.minChars;
                            if(q.length >= minChars){
                                this.setVisibleLayers();
                            }
                        },
                        scope:this
                    },
                    store:this.autosuggestStore
                });
                Ext.view.BoundListKeyNav.override({
                    selectHighlighted: function() {
                        if(!this.record) {
                            me.search();
                            return;
                        }
                        //If an item is selected, the user did that. So go directly to that result. Otherwise search with the user typed string
                        me.searchHighlightedSuggestion(this.record);
                    }
                });
                
                var searchFieldAndButton = Ext.create('Ext.container.Container', {
                    layout: {
                        type: this.showSearchButtons ? 'hbox' : 'fit'
                    },
                    scrollable: false,
                    padding: '0 1 0 0',
                    items: [
                        this.searchField,
                        {
                            xtype: 'button',
                            text: i18next.t('viewer_components_search_3'),
                            hidden: !this.showSearchButtons,
                            listeners: {
                                click: {
                                    scope: this,
                                    fn: this.search
                                }
                            }
                        }
                    ]
                });
                itemList.push(searchFieldAndButton);
            }
        }
        itemList.push({ 
            xtype: 'button',
            text: i18next.t('viewer_components_search_4'),
            name: 'cancel',
            itemId: 'cancel'+ this.name,
            hidden: !this.showSearchButtons,
            listeners: {
                click:{
                    scope: this,
                    fn: this.cancel
                }
            }
        });
        //remove pin button
        itemList.push({
            xtype: 'button',
            text: i18next.t('viewer_components_search_5'),
            name: 'removePin',
            itemId: 'removePin'+ this.name,
            hidden: true,
            listeners: {
                click: {
                    scope: this,
                    fn: this.removePin
                }
            }
            
        });
        return itemList;
    },
    getPickerMaxHeight: function() {
        var viewportHeight = Ext.dom.Element.getViewportHeight();
        if(viewportHeight < 600) {
            return Math.floor(viewportHeight * 0.5);
        }
        return 300; // default
    },
    searchHighlightedSuggestion: function(node){
        var data = node.raw !== undefined ? node.raw : node.data;
        this.searchField.setValue(data.originalLabel || data.label);
        if(data.location){
            this.handleSearchResult(data);
            this.searchField.collapse();
            this.resultPanel.removeAll();
        }else{
            this.search();
        }
    },
    hideWindow : function(){
        this.searchField.collapse();
        this.popup.hide();
    },
    search : function(){
        this.searchRequestId++;
        if(this.results !== null){
            this.results.destroy();
        }
        this.searchField.getPicker().hide();
        var searchText = Ext.ComponentQuery.query( "#searchfield" + this.name)[0].getValue();
        var searchName = '';
        if(this.searchconfigs.length === 1){
            searchName = this.searchconfigs[0].id;
        }else{
            searchName = this.form.query("#searchName" + this.name)[0].getValue();
{'fraction_non_alphanumeric': 0.10584120321790835, 'fraction_numerical': 0.00696047569080098, 'mean_word_length': 1.2261932570271743, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5213686', 'n_tokens_mistral': 7366, 'n_tokens_neox': 6926, 'n_words': 1473}