| /* |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| var dataimport_timeout = 2000; |
| var cookie_dataimport_autorefresh = 'dataimport_autorefresh'; |
| |
| sammy.bind |
| ( |
| 'dataimport_queryhandler_load', |
| function( event, params ) |
| { |
| var core_basepath = params.active_core.attr( 'data-basepath' ); |
| |
| $.ajax |
| ( |
| { |
| url : core_basepath + '/admin/mbeans?cat=QUERYHANDLER&wt=json', |
| dataType : 'json', |
| beforeSend : function( xhr, settings ) |
| { |
| }, |
| success : function( response, text_status, xhr ) |
| { |
| var handlers = response['solr-mbeans'][1]; |
| var dataimport_handlers = []; |
| for( var key in handlers ) |
| { |
| if( handlers[key]['class'] !== key && |
| handlers[key]['class'] === 'org.apache.solr.handler.dataimport.DataImportHandler' ) |
| { |
| dataimport_handlers.push( key ); |
| } |
| } |
| params.callback( dataimport_handlers.sort(naturalSort) ); |
| }, |
| error : function( xhr, text_status, error_thrown) |
| { |
| }, |
| complete : function( xhr, text_status ) |
| { |
| } |
| } |
| ); |
| } |
| ); |
| |
| // #/:core/dataimport |
| sammy.get |
| ( |
| new RegExp( app.core_regex_base + '\\/(dataimport)$' ), |
| function( context ) |
| { |
| sammy.trigger |
| ( |
| 'dataimport_queryhandler_load', |
| { |
| active_core : this.active_core, |
| callback : function( dataimport_handlers ) |
| { |
| if( 0 === dataimport_handlers.length ) |
| { |
| $( '#content' ) |
| .html( 'sorry, no dataimport-handler defined!' ); |
| |
| return false; |
| } |
| |
| context.redirect( context.path + '/' + dataimport_handlers[0] ); |
| } |
| } |
| ); |
| } |
| ); |
| |
| // #/:core/dataimport |
| sammy.get |
| ( |
| new RegExp( app.core_regex_base + '\\/(dataimport)\\/' ), |
| function( context ) |
| { |
| var core_basepath = this.active_core.attr( 'data-basepath' ); |
| var content_element = $( '#content' ); |
| |
| var path_parts = this.path.match( /^(.+\/dataimport\/)(.*)$/ ); |
| var handler_url = core_basepath + path_parts[2]; |
| |
| $( 'li.dataimport', this.active_core ) |
| .addClass( 'active' ); |
| |
| $.get |
| ( |
| 'tpl/dataimport.html', |
| function( template ) |
| { |
| content_element |
| .html( template ); |
| |
| var dataimport_element = $( '#dataimport', content_element ); |
| var form_element = $( '#form', dataimport_element ); |
| var config_element = $( '#config', dataimport_element ); |
| var error_element = $( '#error', dataimport_element ); |
| var debug_response_element = $( '#debug_response', dataimport_element ); |
| |
| var autorefresh_status = false; |
| var debug_mode = false; |
| |
| // handler |
| |
| sammy.trigger |
| ( |
| 'dataimport_queryhandler_load', |
| { |
| active_core : context.active_core, |
| callback : function( dataimport_handlers ) |
| { |
| var handlers_element = $( '#navigation ul', form_element ); |
| var handlers = []; |
| |
| for( var i = 0; i < dataimport_handlers.length; i++ ) |
| { |
| handlers.push |
| ( |
| '<li><a href="' + path_parts[1] + dataimport_handlers[i] + '">' + |
| dataimport_handlers[i] + |
| '</a></li>' |
| ); |
| } |
| |
| $( handlers_element ) |
| .html( handlers.join( "\n") ) ; |
| |
| $( 'a[href="' + context.path + '"]', handlers_element ).closest( 'li' ) |
| .addClass( 'current' ); |
| |
| $( 'form', form_element ) |
| .show(); |
| } |
| } |
| ); |
| |
| // config |
| |
| function dataimport_fetch_config() |
| { |
| $.ajax |
| ( |
| { |
| url : handler_url + '?command=show-config&indent=true', |
| dataType : 'xml', |
| context : $( '#dataimport_config', config_element ), |
| beforeSend : function( xhr, settings ) |
| { |
| error_element |
| .empty() |
| .hide(); |
| }, |
| success : function( config, text_status, xhr ) |
| { |
| dataimport_element |
| .removeClass( 'error' ); |
| |
| config_element |
| .addClass( 'hidden' ); |
| |
| var entities = [ '<option value=""></option>' ]; |
| |
| $( 'document > entity', config ) |
| .each |
| ( |
| function( i, element ) |
| { |
| entities.push( '<option>' + $( element ).attr( 'name' ).esc() + '</option>' ); |
| } |
| ); |
| |
| $( '#entity', form_element ) |
| .html( entities.join( "\n" ) ); |
| |
| $( '.editable textarea', this ) |
| .val( xhr.responseText.replace( /\n+$/, '' ) ); |
| }, |
| error : function( xhr, text_status, error_thrown ) |
| { |
| if( 'parsererror' === error_thrown ) |
| { |
| dataimport_element |
| .addClass( 'error' ); |
| |
| error_element |
| .text( 'Dataimport XML-Configuration is not valid' ) |
| .show(); |
| |
| config_element |
| .removeClass( 'hidden' ); |
| } |
| }, |
| complete : function( xhr, text_status ) |
| { |
| var code = $( |
| '<pre class="syntax language-xml"><code>' + |
| xhr.responseText.esc() + |
| '</code></pre>' |
| ); |
| $( '.formatted', this ).html( code ); |
| |
| if( 'success' === text_status ) |
| { |
| hljs.highlightBlock( code.get(0) ); |
| } |
| } |
| } |
| ); |
| } |
| dataimport_fetch_config(); |
| |
| $( '.block .toggle', dataimport_element ) |
| .die( 'click' ) |
| .live |
| ( |
| 'click', |
| function( event ) |
| { |
| $( this ).parents( '.block' ) |
| .toggleClass( 'hidden' ); |
| |
| return false; |
| } |
| ) |
| |
| var reload_config_element = $( '.reload_config', config_element ); |
| reload_config_element |
| .die( 'click' ) |
| .live |
| ( |
| 'click', |
| function( event ) |
| { |
| $.ajax |
| ( |
| { |
| url : handler_url + '?command=reload-config', |
| dataType : 'xml', |
| context: $( this ), |
| beforeSend : function( xhr, settings ) |
| { |
| this |
| .removeClass( 'error' ) |
| .addClass( 'loader' ); |
| }, |
| success : function( response, text_status, xhr ) |
| { |
| this |
| .addClass( 'success' ); |
| |
| window.setTimeout |
| ( |
| function() |
| { |
| reload_config_element |
| .removeClass( 'success' ); |
| }, |
| 5000 |
| ); |
| }, |
| error : function( xhr, text_status, error_thrown ) |
| { |
| this |
| .addClass( 'error' ); |
| }, |
| complete : function( xhr, text_status ) |
| { |
| this |
| .removeClass( 'loader' ); |
| |
| dataimport_fetch_config(); |
| } |
| } |
| ); |
| return false; |
| } |
| ); |
| |
| var debug_mode_element = $( '.debug_mode', config_element ); |
| debug_mode_element |
| .die( 'click' ) |
| .live |
| ( |
| 'click', |
| function( event ) |
| { |
| var self = $( this ); |
| var block = self.closest( '.block' ) |
| |
| var debug_checkbox = $( 'input[name="debug"]', form_element ); |
| var submit_span = $( 'button[type="submit"] span', form_element ); |
| |
| debug_mode = !debug_mode; |
| |
| block.toggleClass( 'debug_mode', debug_mode ); |
| |
| if( debug_mode ) |
| { |
| block.removeClass( 'hidden' ); |
| |
| debug_checkbox |
| .attr( 'checked', 'checked' ) |
| .trigger( 'change' ); |
| |
| submit_span |
| .data( 'original', submit_span.text() ) |
| .text( submit_span.data( 'debugmode' ) ); |
| } |
| else |
| { |
| submit_span |
| .text( submit_span.data( 'original' ) ) |
| .removeData( 'original' ); |
| } |
| } |
| ); |
| |
| // abort |
| |
| var abort_import_element = $( '.abort-import', dataimport_element ); |
| abort_import_element |
| .off( 'click' ) |
| .on |
| ( |
| 'click', |
| function( event ) |
| { |
| var span_element = $( 'span', this ); |
| |
| $.ajax |
| ( |
| { |
| url : handler_url + '?command=abort&wt=json', |
| dataType : 'json', |
| type: 'GET', |
| context: $( this ), |
| beforeSend : function( xhr, settings ) |
| { |
| span_element |
| .addClass( 'loader' ); |
| }, |
| success : function( response, text_status, xhr ) |
| { |
| span_element |
| .data( 'original', span_element.text() ) |
| .text( span_element.data( 'aborting' ) ); |
| |
| this |
| .removeClass( 'warn' ) |
| .addClass( 'success' ); |
| |
| window.setTimeout |
| ( |
| function() |
| { |
| $( 'span', abort_import_element ) |
| .removeClass( 'loader' ) |
| .text( span_element.data( 'original' ) ) |
| .removeData( 'original' ); |
| |
| abort_import_element |
| .removeClass( 'success' ) |
| .addClass( 'warn' ); |
| }, |
| dataimport_timeout * 2 |
| ); |
| |
| dataimport_fetch_status(); |
| } |
| } |
| ); |
| return false; |
| } |
| ); |
| |
| // state |
| |
| var status_button = $( 'form button.refresh-status', form_element ); |
| |
| status_button |
| .off( 'click' ) |
| .on |
| ( |
| 'click', |
| function( event ) |
| { |
| dataimport_fetch_status(); |
| return false; |
| } |
| ) |
| .trigger( 'click' ); |
| |
| function dataimport_fetch_status( clear_timeout ) |
| { |
| if( clear_timeout ) |
| { |
| app.clear_timeout(); |
| } |
| |
| $.ajax |
| ( |
| { |
| url : handler_url + '?command=status&indent=true&wt=json', |
| dataType : 'json', |
| beforeSend : function( xhr, settings ) |
| { |
| $( 'span', status_button ) |
| .addClass( 'loader' ); |
| }, |
| success : function( response, text_status, xhr ) |
| { |
| var state_element = $( '#current_state', content_element ); |
| |
| var status = response.status; |
| var rollback_time = response.statusMessages.Rolledback || null; |
| var abort_time = response.statusMessages.Aborted || null; |
| |
| var messages = response.statusMessages; |
| var messages_count = 0; |
| for( var key in messages ) { messages_count++; } |
| |
| function dataimport_compute_details( response, details_element, elapsed_seconds ) |
| { |
| details_element |
| .show(); |
| |
| // -- |
| |
| var document_config = { |
| 'Requests' : 'Total Requests made to DataSource', |
| 'Fetched' : 'Total Rows Fetched', |
| 'Skipped' : 'Total Documents Skipped', |
| 'Processed' : 'Total Documents Processed' |
| }; |
| |
| var document_details = []; |
| for( var key in document_config ) |
| { |
| var value = parseInt( response.statusMessages[document_config[key]], 10 ); |
| |
| var detail = '<abbr title="' + document_config[key].esc() + '">' + key.esc() + '</abbr>: ' + app.format_number( value ).esc(); |
| if( elapsed_seconds && 'skipped' !== key.toLowerCase() ) |
| { |
| detail += ' <span>(' + app.format_number( Math.round( value / elapsed_seconds ) ).esc() + '/s)</span>' |
| } |
| |
| document_details.push( detail ); |
| }; |
| |
| $( '.docs', details_element ) |
| .html( document_details.join( ', ' ) ); |
| |
| // -- |
| |
| var dates_config = { |
| 'Started' : 'Full Dump Started', |
| 'Aborted' : 'Aborted', |
| 'Rolledback' : 'Rolledback' |
| }; |
| |
| var dates_details = []; |
| for( var key in dates_config ) |
| { |
| var value = response.statusMessages[dates_config[key]]; |
| |
| if( value ) |
| { |
| var detail = '<abbr title="' + dates_config[key].esc() + '">' + key.esc() + '</abbr>: ' |
| + '<abbr class="time">' + value.esc() + '</abbr>'; |
| dates_details.push( detail ); |
| } |
| }; |
| |
| var dates_element = $( '.dates', details_element ); |
| |
| dates_element |
| .html( dates_details.join( ', ' ) ); |
| |
| $( '.time', dates_element ) |
| .removeData( 'timeago' ) |
| .timeago(); |
| }; |
| |
| var get_time_taken = function get_default_time_taken() |
| { |
| var time_taken_text = response.statusMessages['Time taken']; |
| return app.convert_duration_to_seconds( time_taken_text ); |
| }; |
| |
| var get_default_info_text = function default_info_text() |
| { |
| var info_text = response.statusMessages[''] || ''; |
| |
| // format numbers included in status nicely |
| info_text = info_text.replace |
| ( |
| /\d{4,}/g, |
| function( match, position, string ) |
| { |
| return app.format_number( parseInt( match, 10 ) ); |
| } |
| ); |
| |
| var time_taken_text = app.convert_seconds_to_readable_time( get_time_taken() ); |
| if( time_taken_text ) |
| { |
| info_text += ' (Duration: ' + time_taken_text.esc() + ')'; |
| } |
| |
| return info_text; |
| }; |
| |
| var show_info = function show_info( info_text, elapsed_seconds ) |
| { |
| $( '.info strong', state_element ) |
| .text( info_text || get_default_info_text() ); |
| |
| $( '.info .details', state_element ) |
| .hide(); |
| }; |
| |
| var show_full_info = function show_full_info( info_text, elapsed_seconds ) |
| { |
| show_info( info_text, elapsed_seconds ); |
| |
| dataimport_compute_details |
| ( |
| response, |
| $( '.info .details', state_element ), |
| elapsed_seconds || get_time_taken() |
| ); |
| }; |
| |
| state_element |
| .removeAttr( 'class' ); |
| |
| var current_time = new Date(); |
| $( '.last_update abbr', state_element ) |
| .text( current_time.toTimeString().split( ' ' ).shift() ) |
| .attr( 'title', current_time.toUTCString() ); |
| |
| $( '.info', state_element ) |
| .removeClass( 'loader' ); |
| |
| if( 'busy' === status ) |
| { |
| state_element |
| .addClass( 'indexing' ); |
| |
| if( autorefresh_status ) |
| { |
| $( '.info', state_element ) |
| .addClass( 'loader' ); |
| } |
| |
| var time_elapsed_text = response.statusMessages['Time Elapsed']; |
| var elapsed_seconds = app.convert_duration_to_seconds( time_elapsed_text ); |
| time_elapsed_text = app.convert_seconds_to_readable_time( elapsed_seconds ); |
| |
| var info_text = time_elapsed_text |
| ? 'Indexing since ' + time_elapsed_text |
| : 'Indexing ...'; |
| |
| show_full_info( info_text, elapsed_seconds ); |
| } |
| else if( rollback_time ) |
| { |
| state_element |
| .addClass( 'failure' ); |
| |
| show_full_info(); |
| } |
| else if( abort_time ) |
| { |
| state_element |
| .addClass( 'aborted' ); |
| |
| show_full_info( 'Aborting current Import ...' ); |
| } |
| else if( 'idle' === status && 0 !== messages_count ) |
| { |
| state_element |
| .addClass( 'success' ); |
| |
| show_full_info(); |
| } |
| else |
| { |
| state_element |
| .addClass( 'idle' ); |
| |
| show_info( 'No information available (idle)' ); |
| } |
| |
| // show raw status |
| |
| var code = $( |
| '<pre class="syntax language-json"><code>' + |
| app.format_json( xhr.responseText ).esc() + |
| '</code></pre>' |
| ); |
| |
| $( '#raw_output_container', content_element ).html( code ); |
| hljs.highlightBlock( code.get(0) ); |
| |
| if( !app.timeout && autorefresh_status ) |
| { |
| app.timeout = window.setTimeout |
| ( |
| function() |
| { |
| dataimport_fetch_status( true ) |
| }, |
| dataimport_timeout |
| ); |
| } |
| }, |
| error : function( xhr, text_status, error_thrown ) |
| { |
| console.debug( arguments ); |
| |
| reload_config_element |
| .addClass( 'error' ); |
| }, |
| complete : function( xhr, text_status ) |
| { |
| $( 'span', status_button ) |
| .removeClass( 'loader' ) |
| .addClass( 'success' ); |
| |
| window.setTimeout |
| ( |
| function() |
| { |
| $( 'span', status_button ) |
| .removeClass( 'success' ); |
| }, |
| dataimport_timeout / 2 |
| ); |
| } |
| } |
| ); |
| } |
| |
| // form |
| |
| var form = $( 'form', form_element ); |
| |
| form |
| .ajaxForm |
| ( |
| { |
| url : handler_url, |
| data : { |
| wt : 'json', |
| indent : 'true' |
| }, |
| dataType : 'json', |
| type: 'POST', |
| beforeSend : function( xhr, settings ) |
| { |
| $( 'button[type="submit"] span', form_element ) |
| .addClass( 'loader' ); |
| |
| error_element |
| .empty() |
| .hide(); |
| }, |
| beforeSubmit : function( array, form, options ) |
| { |
| var entity = $( '#entity', form ).val(); |
| if( entity.length ) |
| { |
| array.push( { name : 'entity', value: entity } ); |
| } |
| |
| var start = parseInt( $( '#start', form ).val(), 10 ); |
| if( start ) |
| { |
| array.push( { name : 'start', value: start } ); |
| } |
| |
| var rows = parseInt( $( '#rows', form ).val(), 10 ); |
| if( rows ) |
| { |
| array.push( { name : 'rows', value: rows } ); |
| } |
| |
| $( 'input:checkbox', form ).not( ':checked' ) |
| .each( function( i, input ) |
| { |
| array.push( { name: input.name, value: 'false' } ); |
| } |
| ); |
| |
| var custom_parameters = $( '#custom_parameters', form ).val(); |
| if( custom_parameters.length ) |
| { |
| var params = custom_parameters.split( '&' ); |
| for( var i in params ) |
| { |
| var tmp = params[i].split( '=' ); |
| array.push( { name : tmp[0], value: tmp[1] } ); |
| } |
| } |
| |
| if( debug_mode ) |
| { |
| array.push( { name: 'dataConfig', value: $( '#dataimport_config .editable textarea' ).val() } ); |
| } |
| }, |
| success : function( response, text_status, xhr ) |
| { |
| }, |
| error : function( xhr, text_status, error_thrown ) |
| { |
| var response = null; |
| try |
| { |
| eval( 'response = ' + xhr.responseText + ';' ); |
| } |
| catch( e ){} |
| |
| error_element |
| .text( response.error.msg || 'Unknown Error (Exception w/o Message)' ) |
| .show(); |
| }, |
| complete : function( xhr, text_status ) |
| { |
| $( 'button[type="submit"] span', form_element ) |
| .removeClass( 'loader' ); |
| |
| var debug = $( 'input[name="debug"]:checked', form ); |
| if( 0 !== debug.size() ) |
| { |
| var code = $( |
| '<pre class="syntax language-json"><code>' + |
| app.format_json( xhr.responseText ).esc() + |
| '</code></pre>' |
| ); |
| |
| $( '.content', debug_response_element ).html( code ); |
| hljs.highlightBlock( code.get(0) ); |
| } |
| |
| dataimport_fetch_status(); |
| } |
| } |
| ); |
| |
| $( 'input[name="debug"]', form ) |
| .off( 'change' ) |
| .on |
| ( |
| 'change', |
| function( event ) |
| { |
| debug_response_element.toggle( this.checked ); |
| } |
| ); |
| |
| $( '#auto-refresh-status a', form_element ) |
| .off( 'click' ) |
| .on |
| ( |
| 'click', |
| function( event ) |
| { |
| $.cookie( cookie_dataimport_autorefresh, $.cookie( cookie_dataimport_autorefresh ) ? null : true ); |
| $( this ).trigger( 'state' ); |
| |
| dataimport_fetch_status(); |
| |
| return false; |
| } |
| ) |
| .off( 'state' ) |
| .on |
| ( |
| 'state', |
| function( event ) |
| { |
| autorefresh_status = !!$.cookie( cookie_dataimport_autorefresh ); |
| |
| $.cookie( cookie_dataimport_autorefresh ) |
| ? $( this ).addClass( 'on' ) |
| : $( this ).removeClass( 'on' ); |
| } |
| ) |
| .trigger( 'state' ); |
| } |
| ); |
| } |
| ); |