<commit_before>/**
 * @author <NAME> <<EMAIL>>
 * @public
 */
(function( $, undefined ) {
    $.KBWidget({
        name: 'kbaseNarrativeDataList',
        parent: 'kbaseAuthenticatedWidget',
        version: '1.0.0',
        options: {
            ws_name: null, // must be the WS name, not the WS Numeric ID

            ws_url:"https://kbase.us/services/ws",
            landing_page_url: "/functional-site/#/", // !! always include trailing slash
            lp_url: "/functional-site/#/dataview/",

            user_name_fetch_url:"https://kbase.us/services/genome_comparison/users?usernames=",

            loadingImage: 'static/kbase/images/ajax-loader.gif',
            methodStoreURL: 'http://dev19.berkeley.kbase.us/narrative_method_store',

            ws_chunk_size:10000,  // this is the limit of the number of objects to retrieve from the ws on each pass
            ws_max_objs_to_fetch: 75000, // this is the total limit of the number of objects before we stop trying to get more
                                         // note that if there are more objects than this, then sorts/search filters may
                                         // not show accurate results

            objs_to_render_to_start:40, // initial number of rows to display
            objs_to_render_on_scroll:5, // number of rows to add when the user scrolls to the bottom, should be <=5, much more and
                                        // the addition of new rows becomes jerky

            max_objs_to_prevent_filter_as_you_type_in_search:50000, //if there are more than this # of objs, user must click search
                                                                    //instead of updating as you type

            max_objs_to_prevent_initial_sort:10000, // initial sort makes loading slower, so we can turn it off if
                                                    // there are more than this number of objects

            max_name_length:33,
            refresh_interval:30000,

            parentControlPanel: null
        },
        // private variables
        mainListPanelHeight : '340px',
        refreshTimer: null,

        ws_name: null,
        ws: null,
        ws_last_update_timestamp: null,
        ws_obj_count: null,

        n_objs_rendered:0,

        real_name_lookup: {},

        $searchInput: null,
        $filterTypeSelect: null,
        availableTypes:{},

        $searchDiv: null,
        $sortByDiv: null,
        $filterTypeDiv: null,

        $addDataButton:null,
        $controllerDiv: null,
        $mainListDiv:null,
        mainListId:null,
        $loadingDiv:null,

        methClient: null,

        obj_list : [],
        obj_data : {}, // old style - type_name : info

        my_user_id: null,

        /**
         * @method init
         * Builds the DOM structure for the widget.
         * Includes the tables and panel.
         * If any data was passed in (options.data), that gets shoved into the datatable.
         * @param {Object} - the options set.
         * @returns {Object} this shiny new widget.
         * @private
         */
        init: function(options) {
            this._super(options);
            var self = this;

            this.$controllerDiv = $('<div>');
            this.$elem.append(this.$controllerDiv);
            this.renderController();
            this.$loadingDiv = $('<div>').addClass('kb-data-loading')
                                 .append('<img src="' + this.options.loadingImage + '">');
            this.$elem.append(this.$loadingDiv);
            this.mainListId=this.genUUID();
            this.$mainListDiv = $('<div id='+this.mainListId+'>')
                .css({'overflow-x' : 'hidden', 'overflow-y':'auto', 'height':this.mainListPanelHeight })
                .on('scroll', function() {
                    if($(this).scrollTop() + $(this).innerHeight() >= this.scrollHeight) {
                        self.renderMore();
                    }
                });

            this.$addDataButton = $('<span>').addClass('kb-data-list-add-data-button fa fa-plus fa-2x')
                                    .css({'position':'absolute', bottom:'15px', right:'25px', 'z-index':'5'})
                                    .click(function() {
                                        self.trigger('hideGalleryPanelOverlay.Narrative');
                                        self.trigger('toggleSidePanelOverlay.Narrative', self.options.parentControlPanel.$overlayPanel);
                                    });
            var $mainListDivContainer = $('<div>').css({'position':'relative'})
                                            .append(this.$mainListDiv)
                                            .append(this.$addDataButton.hide());
            this.$elem.append($mainListDivContainer);

            if (window.kbconfig === undefined || window.kbconfig.urls === undefined ||
                window.kbconfig.icons === undefined) {
                KBFatal("kbaseNarrativeDataList.init", "Failed to load base configuration");
            }
            this.options.methodStoreURL = window.kbconfig.urls.narrative_method_store;
            this.options.ws_url = window.kbconfig.urls.workspace;

            if (window.kbconfig.urls.landing_pages) {
                this.options.lp_url = window.kbconfig.urls.landing_pages;
            }
            
            if (this._attributes.auth) {
                this.ws = new Workspace(this.options.ws_url, this._attributes.auth);
            }

            // listener for refresh
            $(document).on('updateDataList.Narrative', function() {
                self.refresh();
            })

            this.showLoading();
            if (this.options.ws_name) {
                this.setWorkspace(this.options.ws_name);
            }

            this.methClient = new NarrativeMethodStore(this.options.methodStoreURL);

            return this;
        },

        setWorkspace : function(ws_name) {
            this.ws_name = ws_name;
            //this.ws_name = "janakacore"; // for testing a bigish workspace
            //this.ws_name = "KBasePublicGenomesV4"; // for testing a very big workspace
            this.refresh();
        },

        refresh: function() {
            var self = this;

            // Set the refresh timer on the first refresh. From  here, it'll refresh itself
            // every this.options.refresh_interval (30000) ms
            if (self.refreshTimer === null) {
                self.refreshTimer = setInterval(function(){self.refresh();}, this.options.refresh_interval); // check if there is new data every X ms
            }
            if (self.ws_name && self.ws) {
                self.ws.get_workspace_info({
                        workspace: this.ws_name
                    },
                    function(workspace_info) {
                        //[0] ws_id id, [1] ws_name workspace, [2] username owner, [3] timestamp moddate,
                        //[4] int object, [5] permission user_permission, [6] permission globalread,
                        //[7] lock_status lockstat, [8] usermeta metadata
                        //console.log('I have: '+self.ws_last_update_timestamp+ " remote has: "+workspace_info[3]);
                        if (self.ws_last_update_timestamp) {
                            if (self.ws_last_update_timestamp !== workspace_info[3]) {
                                self.ws_last_update_timestamp = workspace_info[3];
                                self.ws_obj_count = workspace_info[4];
                                self.reloadWsData();
                            } else {
                                //console.log('updating times');
                                self.refreshTimeStrings();
                            }
                        } else {
                            self.ws_last_update_timestamp = workspace_info[3];
                            self.ws_obj_count = workspace_info[4];
                            self.reloadWsData();
                        }
                    },
                    function(error) {
                        console.error(error);

                        self.$mainListDiv.show();
                        self.$mainListDiv.empty();
                        self.$mainListDiv.append($('<div>').css({'color':'#F44336','margin':'10px'})
                                                 .append('Error: '+error.error.message));
                        self.hideLoading();
                    });
            }
            else {
                var where = "kbaseNarrativeDataList.refresh";
                if (!self.ws) {
                    KBFatal(where, "Workspace not connected");
                }
                else {
                    KBFatal(where, "Workspace name is empty");
                }
            }
        },<commit_msg>data list no longer shows error if network connection lost temporarily<commit_after>/**
 * @author <NAME> <<EMAIL>>
 * @public
 */
(function( $, undefined ) {
    $.KBWidget({
        name: 'kbaseNarrativeDataList',
        parent: 'kbaseAuthenticatedWidget',
        version: '1.0.0',
        options: {
            ws_name: null, // must be the WS name, not the WS Numeric ID

            ws_url:"https://kbase.us/services/ws",
            landing_page_url: "/functional-site/#/", // !! always include trailing slash
            lp_url: "/functional-site/#/dataview/",

            user_name_fetch_url:"https://kbase.us/services/genome_comparison/users?usernames=",

            loadingImage: 'static/kbase/images/ajax-loader.gif',
            methodStoreURL: 'http://dev19.berkeley.kbase.us/narrative_method_store',

            ws_chunk_size:10000,  // this is the limit of the number of objects to retrieve from the ws on each pass
            ws_max_objs_to_fetch: 75000, // this is the total limit of the number of objects before we stop trying to get more
                                         // note that if there are more objects than this, then sorts/search filters may
                                         // not show accurate results

            objs_to_render_to_start:40, // initial number of rows to display
            objs_to_render_on_scroll:5, // number of rows to add when the user scrolls to the bottom, should be <=5, much more and
                                        // the addition of new rows becomes jerky

            max_objs_to_prevent_filter_as_you_type_in_search:50000, //if there are more than this # of objs, user must click search
                                                                    //instead of updating as you type

            max_objs_to_prevent_initial_sort:10000, // initial sort makes loading slower, so we can turn it off if
                                                    // there are more than this number of objects

            max_name_length:33,
            refresh_interval:30000,

            parentControlPanel: null
        },
        // private variables
        mainListPanelHeight : '340px',
        refreshTimer: null,

        ws_name: null,
        ws: null,
        ws_last_update_timestamp: null,
        ws_obj_count: null,

        n_objs_rendered:0,

        real_name_lookup: {},

        $searchInput: null,
        $filterTypeSelect: null,
        availableTypes:{},

        $searchDiv: null,
        $sortByDiv: null,
        $filterTypeDiv: null,

        $addDataButton:null,
        $controllerDiv: null,
        $mainListDiv:null,
        mainListId:null,
        $loadingDiv:null,

        methClient: null,

        obj_list : [],
        obj_data : {}, // old style - type_name : info

        my_user_id: null,

        /**
         * @method init
         * Builds the DOM structure for the widget.
         * Includes the tables and panel.
         * If any data was passed in (options.data), that gets shoved into the datatable.
         * @param {Object} - the options set.
         * @returns {Object} this shiny new widget.
         * @private
         */
        init: function(options) {
            this._super(options);
            var self = this;

            this.$controllerDiv = $('<div>');
            this.$elem.append(this.$controllerDiv);
            this.renderController();
            this.$loadingDiv = $('<div>').addClass('kb-data-loading')
                                 .append('<img src="' + this.options.loadingImage + '">');
            this.$elem.append(this.$loadingDiv);
            this.mainListId=this.genUUID();
            this.$mainListDiv = $('<div id='+this.mainListId+'>')
                .css({'overflow-x' : 'hidden', 'overflow-y':'auto', 'height':this.mainListPanelHeight })
                .on('scroll', function() {
                    if($(this).scrollTop() + $(this).innerHeight() >= this.scrollHeight) {
                        self.renderMore();
                    }
                });

            this.$addDataButton = $('<span>').addClass('kb-data-list-add-data-button fa fa-plus fa-2x')
                                    .css({'position':'absolute', bottom:'15px', right:'25px', 'z-index':'5'})
                                    .click(function() {
                                        self.trigger('hideGalleryPanelOverlay.Narrative');
                                        self.trigger('toggleSidePanelOverlay.Narrative', self.options.parentControlPanel.$overlayPanel);
                                    });
            var $mainListDivContainer = $('<div>').css({'position':'relative'})
                                            .append(this.$mainListDiv)
                                            .append(this.$addDataButton.hide());
            this.$elem.append($mainListDivContainer);

            if (window.kbconfig === undefined || window.kbconfig.urls === undefined ||
                window.kbconfig.icons === undefined) {
                KBFatal("kbaseNarrativeDataList.init", "Failed to load base configuration");
            }
            this.options.methodStoreURL = window.kbconfig.urls.narrative_method_store;
            this.options.ws_url = window.kbconfig.urls.workspace;

            if (window.kbconfig.urls.landing_pages) {
                this.options.lp_url = window.kbconfig.urls.landing_pages;
            }
            
            if (this._attributes.auth) {
                this.ws = new Workspace(this.options.ws_url, this._attributes.auth);
            }

            // listener for refresh
            $(document).on('updateDataList.Narrative', function() {
                self.refresh();
            })

            this.showLoading();
            if (this.options.ws_name) {
                this.setWorkspace(this.options.ws_name);
            }

            this.methClient = new NarrativeMethodStore(this.options.methodStoreURL);

            return this;
        },

        setWorkspace : function(ws_name) {
            this.ws_name = ws_name;
            //this.ws_name = "janakacore"; // for testing a bigish workspace
            //this.ws_name = "KBasePublicGenomesV4"; // for testing a very big workspace
            this.refresh();
        },

        refresh: function(showError) {
            var self = this;

            // Set the refresh timer on the first refresh. From  here, it'll refresh itself
            // every this.options.refresh_interval (30000) ms
            if (self.refreshTimer === null) {
                self.refreshTimer = setInterval(function(){self.refresh();}, this.options.refresh_interval); // check if there is new data every X ms
            }
            if (self.ws_name && self.ws) {
                self.ws.get_workspace_info({
                        workspace: this.ws_name
                    },
                    function(workspace_info) {
                        //[0] ws_id id, [1] ws_name workspace, [2] username owner, [3] timestamp moddate,
                        //[4] int object, [5] permission user_permission, [6] permission globalread,
                        //[7] lock_status lockstat, [8] usermeta metadata
                        //console.log('I have: '+self.ws_last_update_timestamp+ " remote has: "+workspace_info[3]);
                        if (self.ws_last_update_timestamp) {
                            if (self.ws_last_update_timestamp !== workspace_info[3]) {
                                self.ws_last_update_timestamp = workspace_info[3];
                                self.ws_obj_count = workspace_info[4];
                                self.reloadWsData();
                            } else {
                                //console.log('updating times');
                                self.refreshTimeStrings();
                            }
                        } else {
                            self.ws_last_update_timestamp = workspace_info[3];
                            self.ws_obj_count = workspace_info[4];
                            self.reloadWsData();
                        }
                    },
                    function(error) {
                        console.error('DataList: when checking for updates:',error);
                        if (showError) {
                            self.$mainListDiv.show();
                            self.$mainListDiv.empty();
                            self.$mainListDiv.append($('<div>').css({'color':'#F44336','margin':'10px'})
                                                     .append('Error: Unable to connect to KBase data.'));
                            self.hideLoading();
                        }
                    });
            }
            else {
                var where = "kbaseNarrativeDataList.refresh";
                if (!self.ws) {
                    KBFatal(where, "Workspace not connected");
                }
                else {
                    KBFatal(where, "Workspace name is empty");
                }
            }
        },
{'fraction_non_alphanumeric': 0.10694141955659797, 'fraction_numerical': 0.008264924331267102, 'mean_word_length': 1.4186925985953538, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6547401', 'n_tokens_mistral': 4647, 'n_tokens_neox': 4387, 'n_words': 993}