source: vlo/branches/vlo-3.0/vlo-solr/src/main/webapp/js/scripts/plugins.js @ 4734

Last change on this file since 4734 was 4734, checked in by teckart@informatik.uni-leipzig.de, 10 years ago

Added files for Solr admin interface (directories: css, img, js, tpl + admin.html), updated web.xml

File size: 12.0 KB
Line 
1/*
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements.  See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License.  You may obtain a copy of the License at
8
9     http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16*/
17
18var core_basepath = null;
19var content_element = null;
20var selected_type = null;
21var context_path = null;
22var active_context = null;
23var changes = null;
24var reference_xml = null;
25
26var compute_plugin_data = function( response, changeset )
27{
28  var types = [];
29  var sort_table = {};
30  var plugin_data = {};
31
32  var types_obj = {};
33  var plugin_key = null;
34
35  changes = { count : {}, list : {} }
36
37  for( var i = 0; i < response['solr-mbeans'].length; i++ )
38  {
39    if( !( i % 2 ) )
40    {
41      plugin_key = response['solr-mbeans'][i];
42    }
43    else
44    {
45      plugin_data[plugin_key] = response['solr-mbeans'][i];
46    }
47  }
48
49  for( var key in plugin_data )
50  {
51    sort_table[key] = {
52      url : [],
53      component : [],
54      handler : []
55    };
56    for( var part_key in plugin_data[key] )
57    {
58      if( plugin_data[key][part_key]['_changed_'] )
59      {
60        delete plugin_data[key][part_key]['_changed_'];
61
62        changes.count[key] = changes.count[key] || 0;
63        changes.count[key]++;
64
65        changes.list[key] = changes.list[key] || {};
66        changes.list[key][part_key] = true;
67      }
68
69      if( 0 < part_key.indexOf( '.' ) )
70      {
71        types_obj[key] = true;
72        sort_table[key]['handler'].push( part_key );
73      }
74      else if( 0 === part_key.indexOf( '/' ) )
75      {
76        types_obj[key] = true;
77        sort_table[key]['url'].push( part_key );
78      }
79      else
80      {
81        types_obj[key] = true;
82        sort_table[key]['component'].push( part_key );
83      }
84    }
85  }
86
87  for( var type in types_obj )
88  {
89    types.push( type );
90  }
91  types.sort();
92
93  return {
94    'plugin_data' : plugin_data,
95    'sort_table' : sort_table,
96    'types' : types
97  };
98};
99
100var render_plugin_data = function( plugin_data, plugin_sort, types )
101{
102  var frame_element = $( '#frame', content_element );
103  var navigation_element = $( '#navigation ul', content_element );
104
105  var navigation_content = [];
106  for( var i = 0; i < types.length; i++ )
107  {
108    var type_url = active_context.params.splat[0] + '/' + active_context.params.splat[1] + '/' + types[i].toLowerCase();
109
110    var navigation_markup = '<li class="' + types[i].toLowerCase().esc() + '">' +
111                            '<a href="#/' + type_url + '" rel="' + types[i].esc() + '">' + types[i].esc();
112
113    if( changes.count[types[i]] )
114    {
115      navigation_markup += ' <span>' + changes.count[types[i]].esc() + '</span>';
116    }
117
118    navigation_markup += '</a>' +
119                         '</li>';
120
121    navigation_content.push( navigation_markup );
122  }
123
124  navigation_content.push( '<li class="PLUGINCHANGES"><a href="#">Watch Changes</a></li>' );
125  navigation_content.push( '<li class="RELOAD"><a href="#" onClick="window.location.reload()">Refresh Values</a></li>' );
126
127  navigation_element
128    .html( navigation_content.join( "\n" ) );
129   
130  $( '.PLUGINCHANGES a', navigation_element )
131    .die( 'click' )
132    .live
133    (
134      'click',
135      function( event )
136      { 
137        load_reference_xml();
138       
139        changes = { count : {}, list : {} }
140        $( 'a > span', navigation_element ).remove();
141        $( '.entry.changed', frame_element ).removeClass( 'changed' );
142
143        $.blockUI
144        (
145          {
146            message: $('#recording'),
147            css: { width: '450px' }
148          }
149        );
150
151        return false;
152      }
153    ); 
154
155  $( '#recording button' )
156    .die( 'click' )
157    .live
158    (
159      'click',
160      function( event )
161      { 
162        $.ajax
163        (
164          {
165            type: 'POST',
166            url: core_basepath + '/admin/mbeans',
167            dataType : 'json',
168            data: { 
169              'stats': 'true',
170              'wt': 'json', 
171              'diff': 'true',
172              'all': 'true',
173              'stream.body': reference_xml 
174            },
175            success : function( response, text_status, xhr )
176            {
177              load_reference_xml();
178
179              app.plugin_data = compute_plugin_data( response );
180              render_plugin_data( app.plugin_data.plugin_data, app.plugin_data.sort_table, app.plugin_data.types );
181            }
182          }
183        );
184        $.unblockUI();
185        return false;
186      }
187    ); 
188             
189  $( 'a[href="' + context_path + '"]', navigation_element )
190    .parent().addClass( 'current' );
191           
192  var content = '<ul>';
193  for( var sort_key in plugin_sort[selected_type] )
194  {
195    plugin_sort[selected_type][sort_key].sort();
196    var plugin_type_length = plugin_sort[selected_type][sort_key].length;
197               
198    for( var i = 0; i < plugin_type_length; i++ )
199    {
200      var bean = plugin_sort[selected_type][sort_key][i];
201      var classes = [ 'entry' ];
202
203      if( changes.list[selected_type] && changes.list[selected_type][bean] )
204      {
205        classes.push( 'changed' );
206      }
207
208      content += '<li class="' + classes.join( ' ' ) + '">' + "\n";
209      content += '<a href="' + context_path + '?entry=' + bean.esc() + '" data-bean="' + bean.esc() + '">';
210      content += '<span>' + bean.esc() + '</span>';
211      content += '</a>' + "\n";
212      content += '<ul class="detail">' + "\n";
213                   
214      var details = plugin_data[selected_type][ plugin_sort[selected_type][sort_key][i] ];
215      for( var detail_key in details )
216      {
217        if( 'stats' !== detail_key )
218        {
219          var detail_value = details[detail_key];
220
221          if( 'description' === detail_key )
222          {
223            // Link component list to their MBeans page
224            if(detail_value.match(/^Search using components: /)) {
225              var idx = detail_value.indexOf(':');
226              var url = '#/'+active_context.params.splat[0]+'/plugins/other?entry=';
227              var tmp = 'Search using components:<ul>';
228              $.each(detail_value.substr(idx+1).split(","), function(index, value) { 
229                value = $.trim(value);
230                tmp += '<li><a href="'+url+value+'" class="linker">'+value+"</a></li>";
231              });
232              tmp += "</ul>";
233              detail_value = tmp;
234            }
235          }
236
237          content += '<li><dl class="clearfix">' + "\n";
238          content += '<dt>' + detail_key + ':</dt>' + "\n";
239          if($.isArray(detail_value)) {
240            $.each(detail_value, function(index, value) { 
241              content += '<dd>' + value + '</dd>' + "\n";
242            });
243          }
244          else {
245            content += '<dd>' + detail_value + '</dd>' + "\n";
246          }
247          content += '</dl></li>' + "\n";
248        }
249        else if( 'stats' === detail_key && details[detail_key] )
250        {
251          content += '<li class="stats clearfix">' + "\n";
252          content += '<span>' + detail_key + ':</span>' + "\n";
253          content += '<ul>' + "\n";
254
255          for( var stats_key in details[detail_key] )
256          {
257            var stats_value = new String( details[detail_key][stats_key] );
258            stats_value = stats_value.replace( /([\(@])/g, '$1&#8203;' );
259
260            content += '<li><dl class="clearfix">' + "\n";
261            content += '<dt>' + stats_key + ':</dt>' + "\n";
262            content += '<dd>' + stats_value + '</dd>' + "\n";
263            content += '</dl></li>' + "\n";
264          }
265
266          content += '</ul></li>' + "\n";
267        }
268      }
269                   
270      content += '</ul>' + "\n";
271    }
272  }
273  content += '</ul>' + "\n";
274
275  frame_element
276    .html( content );
277
278 
279  var path = active_context.path.split( '?entry=' );
280  var entries = ( path[1] || '' ).split( ',' );
281 
282  var entry_count = entries.length;
283  for( var i = 0; i < entry_count; i++ )
284  {
285    $( 'a[data-bean="' + entries[i] + '"]', frame_element )
286      .parent().addClass( 'expanded' );
287  }
288
289  $( 'a', frame_element )
290    .off( 'click' )
291    .on
292    (
293      'click',
294      function( event )
295      { 
296        var self = $( this );
297        var bean = self.data( 'bean' );
298
299        var split = '?entry=';
300        var path = active_context.path.split( split );
301        var entry = ( path[1] || '' );
302
303        var regex = new RegExp( bean.replace( /\//g, '\\/' ) + '(,|$)' );
304        var match = regex.test( entry );
305
306        var url = path[0] + split;
307
308        url += match
309             ? entry.replace( regex, '' )
310             : entry + ',' + bean;
311
312        url = url.replace( /=,/, '=' );
313        url = url.replace( /,$/, '' );
314        url = url.replace( /\?entry=$/, '' );
315
316        active_context.redirect( url );
317        return false;
318      }
319    );
320 
321  // Try to make links for anything with http (but leave the rest alone)
322  $( '.detail dd' ).each(function(index) {
323    var txt = $(this).html();
324    if(txt.indexOf("http") >= 0) {
325      $(this).linker({
326         className : 'linker'
327      });
328    }
329  });
330 
331  // Add invisible whitespace after each slash
332  $( '.detail a.linker' ).each(function(index) {
333    $(this).html( $(this).html().replace( /\//g, '/&#8203;' ) );
334  });
335 
336           
337  $( '.entry', frame_element )
338    .each
339    (
340      function( i, entry )
341      {
342        $( '.detail > li', entry ).not( '.stats' ).filter( ':even' )
343          .addClass( 'odd' );
344
345        $( '.stats li:odd', entry )
346          .addClass( 'odd' );
347      }
348    );
349};
350
351var load_reference_xml = function()
352{
353  $.ajax
354  (
355    {
356      type: 'GET',
357      url: core_basepath + '/admin/mbeans?stats=true&wt=xml',
358      dataType : 'text',
359      success: function( data )
360      {
361        reference_xml = data;
362      }
363    }
364  );
365}
366
367sammy.bind
368(
369  'plugins_load',
370  function( event, params )
371  {
372    var callback = function()
373    {
374      params.callback( app.plugin_data.plugin_data, app.plugin_data.sort_table, app.plugin_data.types );
375    }
376       
377    if( app.plugin_data )
378    {
379      callback( app.plugin_data );
380      return true;
381    }
382
383    $.ajax
384    (
385      {
386        url : core_basepath + '/admin/mbeans?stats=true&wt=json',
387        dataType : 'json',
388        beforeSend : function( xhr, settings )
389        {
390        },
391        success : function( response, text_status, xhr )
392        {
393          app.plugin_data = compute_plugin_data( response );
394
395          $.get
396          (
397            'tpl/plugins.html',
398            function( template )
399            {
400              $( '#content' )
401                .html( template );
402                           
403              callback( app.plugin_data );
404            }
405          );
406        },
407        error : function( xhr, text_status, error_thrown)
408        {
409        },
410        complete : function( xhr, text_status )
411        {
412        }
413      }
414    );
415  }
416);
417
418// #/:core/plugins/$type
419sammy.get
420(
421  new RegExp( app.core_regex_base + '\\/(plugins)\\/(\\w+)$' ),
422  function( context )
423  {
424    core_basepath = this.active_core.attr( 'data-basepath' );
425    content_element = $( '#content' );
426    selected_type = context.params.splat[2].toUpperCase();
427    context_path = context.path.split( '?' ).shift();
428    active_context = context;
429   
430    sammy.trigger
431    (
432      'plugins_load',
433      {
434        active_core : this.active_core,
435        callback : render_plugin_data
436      }
437    );               
438  }
439);
440
441// #/:core/plugins
442sammy.get
443(
444  new RegExp( app.core_regex_base + '\\/(plugins)$' ),
445  function( context )
446  {
447    core_basepath = this.active_core.attr( 'data-basepath' );
448    delete app.plugin_data;
449
450    sammy.trigger
451    (
452      'plugins_load',
453      {
454        active_core : this.active_core,
455        callback :  function( plugin_data, plugin_sort, types )
456        {
457          context.redirect( context.path + '/' + types[0].toLowerCase() );
458        }
459      }
460    );
461  }
462);
Note: See TracBrowser for help on using the repository browser.