incubator-blur-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amccu...@apache.org
Subject [24/50] [abbrv] Initial Blur Console commit.
Date Fri, 17 May 2013 03:24:51 GMT
http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/hdfs_metrics.js
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/hdfs_metrics.js b/src/contrib/blur-console/blur-admin/app/assets/javascripts/hdfs_metrics.js
new file mode 100644
index 0000000..1c761bb
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/hdfs_metrics.js
@@ -0,0 +1,406 @@
+//= require d3/d3
+//= require flot/flot
+//= require flot/jquery.flot.resize.min
+//= require flot/jquery.flot.selection.min
+//= require flot/jquery.flot.crosshair.min
+//= require jquery.timepicker
+//= require jquery.rangeslider.js
+//= require underscore
+//= require_self
+
+$(document).ready(function(){
+  // Datastore for the current data on the plot
+  var hdfs_data = {};
+  // The max range of data that can be returned (in days)
+  var num_days_back = 14;
+  // starting range for the graphs
+  var default_range = 60 * 24;
+  // refresh speed for pulling new info (while live)
+	var refresh_time = 20000;
+  // timezone offset
+  var epoc_offset = new Date().getTimezoneOffset() * 60 * 1000
+  // refresh timeout
+  var refresh_timer;
+  // Different tab actions
+	var actions = ['disk', 'nodes', 'block'];
+  // Xaxis range 
+	// Hash of labels and object lookup strings for the various actions
+  var hdfs_request_lookup =
+  {
+		disk:
+		{
+			label_1: "Hdfs Disk Capacity (GB) - Left axis <span class='axis-value'></span>",
+			label_2: "Hdfs Disk Usage (GB) - Right axis <span class='axis-value'></span>",
+			stat_1: "capacity",
+			stat_2: "used"
+		},
+		nodes:
+		{
+			label_1: "Live Nodes - Left axis <span class='axis-value'></span>",
+			label_2: "Dead Nodes - Right axis <span class='axis-value'></span>",
+			stat_1: "live_nodes",
+			stat_2: "dead_nodes"
+		},
+		block:
+		{
+			label_1: "Under Replicated Blocks - Left axis <span class='axis-value'></span>",
+      label_2: "Missing Blocks - Right axis <span class='axis-value'></span>",
+			stat_1: "under_replicated",
+      stat_2: "missing_blocks"
+		}
+	};
+
+  //------------- Page Methods -------------
+
+  /*
+   * Returns a new object used to initialize a new hdfs
+   */
+  var default_hdfs_data = function(){
+    return {
+      disk: { metrics: [] },
+      nodes: { metrics: [] },
+      block: { metrics: [] },
+      // Initial range starts at now and goes til 1 day ago (in minutes)
+      max: 0,
+      min: -default_range,
+      // Whether the data is being added to an old set
+      updating: false,
+      largest_id: 0
+    };
+  }
+
+  /* 
+   * Draw the graph
+   * @arg graph_data an object containing all the data related to a graph
+   * @arg selector a jquery selector representing the desired location of the graph
+   */
+  var draw_graph = function(graph_data, selector, min, max){
+    // get the min and max
+    var now = new Date().getTime();
+    min = now + (min * 60 * 1000) - epoc_offset;
+    max = now + (max * 60 * 1000) - epoc_offset;
+
+    graph_data.plot = $.plot(selector, graph_data.metrics,
+		{
+      // Set the xaxis to a time plot
+			xaxis: {
+        mode: "time",
+        timeformat: "%0m/%0d %H:%M %p",
+        max: max,
+        min: min
+      },
+      // Set the yaxis to 2 separate scales
+      yaxes:[
+        { position: 'left', tickDecimals: 1 },
+        { position: 'right', tickDecimals: 1 }
+      ],
+      // Set the legend container
+      legend: { container: $(".graph-legend") },
+      // Set the crosshair to only show in the y direction
+      crosshair: { mode: "x" },
+      // Set the grid to hoverable (for value grabbing)
+      grid: { hoverable: true, autoHighlight: false },
+      // Do not show the lines (looks odd with non contiguous data)
+      lines: { show: false },
+      // Show the points
+      points: { show: true, radius: 2 }
+		});
+	};
+
+	/* 
+   * Request new graph data
+	 * @arg id of the hdfs
+   * @arg req_data data object for the ajax request
+	 *   req_data.stat_id requests data after a certain ID (update)
+	 *   req_data.stat_min specifies a min for the range (update / overwrite)
+   *   req_data.stat_max specifies a min for the range (overwrite)
+   */
+	var request_data = function(id, req_data){
+    $.ajax({
+			url: Routes.stats_hdfs_metric_path(id),
+			type: 'GET',
+			data: _.extend(req_data, {format: 'json'}),
+			success: function(data){
+        // If no data was returned then set the no data message
+        if (data.length <= 0 && !hdfs_data[id]){
+          $.each($('.graph_instance#' + id + ' .graph'), function(index, value) {
+            this.innerHTML = 'No data available';
+          });
+          return;
+				}
+
+        // Loop over every action set and build with the returned data
+				for(var action in hdfs_request_lookup){
+          var request_options = hdfs_request_lookup[action];
+          // Create the buffers for parsing the returned data
+					var hdfs_data_1 = {label: request_options.label_1, data: []};
+          var hdfs_data_2 = {label: request_options.label_2, data: [], yaxis: 2};
+          // Grab the correct container from the page
+          var graph_container = $('.graph_instance#' + id).find('.tab-pane#' + action + '_' + id);
+
+          // Add all of the data points to the buffers
+          for( var i in data ){
+						var point = data[i];
+						var entry_date = new Date(point.created_at).getTime();
+            // Convert the dates to epoc time
+            hdfs_data_1.data.push([entry_date - epoc_offset, point[request_options.stat_1]]);
+						hdfs_data_2.data.push([entry_date - epoc_offset, point[request_options.stat_2]]);
+          }
+
+          // if we are updating the current data set then add the new data
+          // NOTE: the data is a fixed size queue (time) therefore data out of view is dropped
+					if (req_data && req_data.stat_id){
+            var length = hdfs_data[id][action].metrics[0].data.length;
+            var now = new Date();
+              for(var find = 0; find <= length; find++){
+                if (hdfs_data[id][action].metrics[0].data[find] < now + hdfs_data[id].min * 60 * 1000) break;
+              }
+              
+              // remove all data outside of the range
+              if(find > 0){
+                hdfs_data[id][action].metrics[0].data.splice(0, find);
+                hdfs_data[id][action].metrics[1].data.splice(0, find);
+              }
+
+							hdfs_data[id][action].metrics[0].data = hdfs_data[id][action].metrics[0].data.concat(hdfs_data_1.data);
+							hdfs_data[id][action].metrics[1].data = hdfs_data[id][action].metrics[1].data.concat(hdfs_data_2.data);
+					// otherwise we are loading a new dataset (clear and then add)
+          }	else {
+            hdfs_data[id][action].metrics = []
+						hdfs_data[id][action].metrics.push(hdfs_data_1, hdfs_data_2);
+					}
+
+          // Mark the largest id for update requests (only if it is the largest)
+					if (point && hdfs_data[id].largest_id <  point.id) hdfs_data[id].largest_id = point.id
+
+          // Only redraw the active graph
+					if (graph_container.hasClass('active')){
+            draw_graph(hdfs_data[id][action], graph_container.find('.graph'), hdfs_data[id].min, hdfs_data[id].max);
+					}
+
+          // Sync up the sliders / pickers to the newest date returned (may not change depending on ranges)
+          sync_slider(id);
+          sync_date_fields(id);
+				}
+			}
+		});
+	};
+
+  /* 
+   * Loops over every graph instance and requests the new data 
+   * @arg id id of the hdfs we are targetting
+   */
+	var update_live_graphs = function(id){
+    $('.graph_instance').each(function(){
+      // Grab the id of the current graph
+			var hdfs_id = $(this).attr('id');
+      // if an id is defined then we only want to update the graph with that id
+      if (id && hdfs_id !== id) return;
+      
+      // if the max is now
+      if (hdfs_data[hdfs_id].max === 0){
+        // Clear the timeout of the old refresh
+        clearTimeout(refresh_timer);
+        // if we are grabbing an update to a current range
+        if (hdfs_data[hdfs_id].updating){
+          request_data(hdfs_id, {stat_id: hdfs_data[hdfs_id].largest_id});
+        // otherwise it is a newly selected range with a max of 0
+        } else {
+          request_data(hdfs_id, {stat_min: -hdfs_data[hdfs_id].min});
+          // set the updating to true because the max is now
+          hdfs_data[hdfs_id].updating = true;
+        }
+        refresh_timer = setTimeout(update_live_graphs, refresh_time);
+      // otherwise request the range
+      } else {
+        request_data(hdfs_id, {stat_min: -hdfs_data[hdfs_id].min, stat_max: -hdfs_data[hdfs_id].max});
+      }
+    });
+	};
+
+  /*
+   * Sets the time fields to the minDate and maxDate
+   */
+  var sync_slider = function(hdfs_id){
+    // the range values are stored as slider offsets simply set the slider to those values
+    var range_values = [hdfs_data[hdfs_id].min, hdfs_data[hdfs_id].max]
+    $('.graph_instance#' + hdfs_id + ' .slider').dragslider('option', 'values', range_values);
+  };
+
+  /*
+   * Sets the time fields to match the slider
+   * @arg hdfs_id target hdfs
+   * @arg min(optional) min value for date picker
+   * @arg max(optional) max value for date picker
+   */
+  var sync_date_fields = function(hdfs_id, min, max) {
+    // get the current time
+    var now = new Date().getTime();
+
+    // grab the min date and max dates
+    min = typeof min !== "undefined" ? min : hdfs_data[hdfs_id].min;
+    max = typeof max !== "undefined" ? max : hdfs_data[hdfs_id].max;
+    var min_date = now + min * 60 * 1000;
+    var max_date = now + max * 60 * 1000;
+
+    // set the time pickers to the correct time and max/min time
+    var graph = $(".graph_instance#" + hdfs_id)
+    graph.find(".min-date")
+      .datetimepicker("option", "maxDate", new Date(max_date))
+      .datetimepicker("setDate", new Date(min_date));
+    graph.find(".max-date").datetimepicker("option", "maxDate", new Date())
+      .datetimepicker("option", "minDate", new Date(min_date))
+      .datetimepicker("setDate", new Date(max_date));
+  };
+
+	//------------- Page Events -------------
+
+  // Request the first set of data for every graph (starts the page)
+  // Uses the initial time length on
+  $('.graph_instance').each(function(){
+    var hdfs_id = $(this).attr('id');
+    hdfs_data[hdfs_id] = default_hdfs_data();
+    update_live_graphs(hdfs_id);
+  });
+
+  // Draws the new graph when a new tab is shown
+  $('.graph_instance').on('shown', 'a[data-toggle="tab"]', function(e){
+    var instance = $(this).closest('.graph_instance')
+		var hdfs_id = instance.attr('id');
+		var container = instance.find('.active > .graph');
+		var action = $(this).data('action');
+    if (hdfs_data[hdfs_id]){
+      draw_graph(hdfs_data[hdfs_id][action], container, hdfs_data[hdfs_id].min, hdfs_data[hdfs_id].max);
+    };
+	});
+
+  // Show the loading spinner when there is an ajax request taking place
+  $('.loading-spinner').on('ajaxStart', function(){
+    $(this).removeClass('hidden');
+  }).on('ajaxStop', function(){
+    $(this).addClass('hidden');
+  });
+
+    // Update the legend on crosshair show     
+  $(".graph").bind("plothover",  function (event, pos, item) {    
+    // grab the plot from the global store
+    var graph_definition = $(event.target).closest('.active').attr('id');
+    var pieces = graph_definition.split('_');
+    var plot = hdfs_data[pieces[1]][pieces[0]].plot
+    var show_offset = 15; // (in minutes)
+     
+    // get the datasets for searching
+    var axes = plot.getAxes();
+    var datasets = plot.getData();
+    var series = datasets[0];
+
+    // legend holder
+    var legends = $(this).closest('.graph_data').find('.axis-value');
+
+    // break if we are hovering off the viewport
+    if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
+        pos.y < axes.yaxis.min || pos.y > axes.yaxis.max){
+      legends.text('');
+      return;
+    }
+
+    // find the nearest points, x-wise
+    // ToDo: Change this so that it only reads a val if it is within a certain distance
+    for (index = 0; index < series.data.length - 1; ++index)
+      if (series.data[index][0] + show_offset * 60 * 1000 > pos.x)
+        break;
+
+    // absolute distance from mouse to nearest point
+    var current_delta = Math.abs(pos.x - series.data[index][0]);
+
+    // if the point is more than 5 min away draw nothing
+    if ((current_delta / (1000 * 60)) > show_offset){
+      legends.text('');
+      return;
+    }
+            
+    // draw to the legend
+    for (plot_index = 0; plot_index < datasets.length; plot_index++){
+      var point = datasets[plot_index].data[index];
+      legends.eq(plot_index).text('(' + point[1].toFixed(2) + ')');
+    }
+  });
+
+  //------------- Page Elements -------------
+
+  /* 
+   * Creates the date slider
+   */
+  $(".slider").dragslider({
+    range: true,
+    // allows for dragging of the range
+    rangeDrag: true,
+    // Max range
+    min: -1 * 60 * 24 * num_days_back,
+    // Min range (now)
+    max: 0,
+    // Starting selected range is the default
+    values: [-1 * default_range, 0],
+    // A new value has been picked
+    stop: function(event, ui) {
+      // grab the current hdfs_id
+      var hdfs_id = $(this).closest('.graph_instance').attr('id');
+      // set the values for the hdfs
+      hdfs_data[hdfs_id].min = ui.values[0];
+      hdfs_data[hdfs_id].max = ui.values[1];
+      // set the updating to false because a range was selected
+      hdfs_data[hdfs_id].updating = false;
+      // Sync the date fields with the range selected
+      sync_date_fields(hdfs_id);
+      // update the graph for this hdfs
+      update_live_graphs(hdfs_id);
+    },
+    // Update the date values while sliding (feedback for user)
+    slide: function(event, ui){
+      // grab the current hdfs_id
+      var hdfs_id = $(this).closest('.graph_instance').attr('id');
+      // Sync the date fields with the range selected
+      sync_date_fields(hdfs_id, ui.values[0], ui.values[1]);
+    }
+  });
+
+  $(".min-date").datetimepicker({
+    minDate: -1 * num_days_back,
+    defaultDate: -1,
+    onSelect: function (selectedDateTime){
+      // grab the current hdfs_id
+      var hdfs_id = $(this).closest('.graph_instance').attr('id');
+      // get the new date as minutes
+      var min_date = Math.round((new Date().getTime() - new Date(selectedDateTime).getTime()) / (-1 * 1000 * 60))
+      // set the new min range
+      hdfs_data[hdfs_id].min = min_date;
+      // set the updating to false because a range was selected
+      hdfs_data[hdfs_id].updating = false;
+      $(".max-date").datetimepicker("option", "minDate", new Date(selectedDateTime));
+      // reload the data
+      sync_slider(hdfs_id);
+      update_live_graphs(hdfs_id);
+    }
+  })
+
+  // Create the Date pickers for each graph
+  $(".max-date").datetimepicker({
+    // Earliest date available is the max of min-date
+    minDate: -1 * default_range / (60 * 24),
+    defaultDate: 0,
+    onSelect: function (selectedDateTime){
+      // grab the current hdfs_id
+      var hdfs_id = $(this).closest('.graph_instance').attr('id');
+      // get the new date as minutes
+      var max_date = Math.round((new Date().getTime() - new Date(selectedDateTime).getTime()) / (-1 * 1000 * 60));
+      // set the new min range
+      hdfs_data[hdfs_id].max = max_date;
+      // set the updating to false because a range was selected
+      hdfs_data[hdfs_id].updating = false;
+      $(".min-date").datetimepicker("option", "maxDate", new Date(selectedDateTime));
+      // reload the data
+      sync_slider(hdfs_id);
+      update_live_graphs(hdfs_id);
+    }
+  });
+});

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/help.js
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/help.js b/src/contrib/blur-console/blur-admin/app/assets/javascripts/help.js
new file mode 100644
index 0000000..89ff4fd
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/help.js
@@ -0,0 +1,11 @@
+//= require jquery
+//= require_self
+
+$(document).ready(function(){
+  // toggles help sections on click
+  $('.help-section').on('click', function(){
+    $(this).children('.help-content').slideToggle('fast')
+  });
+  // remove the padding at the bottom of the help menu
+  $('body:has(#help-window)').css('padding-bottom', '0');
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/placeholder.js
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/placeholder.js b/src/contrib/blur-console/blur-admin/app/assets/javascripts/placeholder.js
new file mode 100644
index 0000000..99e81cb
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/placeholder.js
@@ -0,0 +1,25 @@
+$(document).ready(function() {
+  if (!Modernizr.input.placeholder) {
+    $('[placeholder]').focus(function() {
+      var input = $(this);
+      if (input.val() === input.attr('placeholder')) {
+        input.val('');
+        input.removeClass('placeholder');
+      }
+      if (input.attr('placeholder') === 'Password') input[0].type = 'password';
+    }).blur(function() {
+      var input = $(this);
+      if (input.val() === '' || input.val() === input.attr('placeholder')) {
+        input.addClass('placeholder');
+        input.val(input.attr('placeholder'));
+        if (input.attr('placeholder') === 'Password') input[0].type = 'text';
+      }
+    }).blur();
+    $('[placeholder]').parents('form').submit(function() {
+      $(this).find('[placeholder]').each(function() {
+      	var input = $(this);
+      	if (input.val() === input.attr('placeholder')) input.val('');
+      });
+    });
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/search.js
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/search.js b/src/contrib/blur-console/blur-admin/app/assets/javascripts/search.js
new file mode 100644
index 0000000..5205e75
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/search.js
@@ -0,0 +1,449 @@
+//= require jquery.dynatree
+
+$(document).ready(function() {
+  // PUSH STATE SEARCH QUERIES
+  // When the history is popped add the query and table
+  // then submit the query
+  window.onpopstate = function(e) {
+    if(e.state){
+      $('#blur_table').val(e.state.table_id);
+      $('#query_string').val(e.state.query);
+      $('#search_submit').click();
+    }
+  };
+
+  $('#search_form').on('submit', function(e) {
+    // if the browser doesnt support push state return
+    if (!Modernizr.history) {
+      return;
+    }
+
+    // History state object
+    var state = {
+      table_id: $('#blur_table').find('option:selected').val(),
+      query: $('#query_string').val()
+    };
+
+    // Build the new stateful query search
+    var stateful_url = '?table_id=' + state.table_id + '&query=' + encodeURIComponent(state.query);
+    var base_url = location.protocol + "//" + location.host + location.pathname;
+    var full_url = base_url + stateful_url;
+
+    // If the length is zero it is the first search
+    // and we want replace (avoid going back twice)
+    if(location.search.length === 0){
+      history.replaceState(state, "Search | Blur Console", full_url);
+    // Otherwise we need to check that we arent searching
+    // using the same query (dont push if it is the same)
+    } else if(location.search !== stateful_url){
+      history.pushState(state, "Search | Blur Console", full_url);
+    }
+  });
+
+  /********** METHODS **********/
+  var resizeSearch = function() {
+    var footerHeight, headerHeight, resultWrapper;
+    headerHeight = parseInt($('.navbar').css('height'));
+    footerHeight = parseInt($('#ft').css('height'));
+    resultWrapper = $('#results_wrapper');
+    $('#results_wrapper').css('max-height', window.innerHeight - (footerHeight + headerHeight + parseInt(resultWrapper.css('margin-top')) + 50));
+  };
+
+  var hide_all_tabs = function() {
+    $('.tab:visible').slideUp('fast');
+    $('.arrow_up').hide();
+    $('.arrow_down').show();
+  };
+
+  // method to initialize the filter tree
+  var setup_filter_tree = function() {
+    $('.column_family_filter').dynatree({
+      checkbox: true,
+      selectMode: 3,
+      initAjax: get_filter_ajax(),
+      onSelect: toggle_submit
+    });
+  };
+
+  var get_filter_ajax = function() {
+    return {
+      url: Routes.filters_zookeeper_searches_path(CurrentZookeeper, $('#blur_table').val(), {format: 'json'}),
+      type: 'get'
+    };
+  };
+
+  // Function to enable or disable submit button based on checkbox status
+  var toggle_submit = function() {
+    if ($(".column_family_filter").dynatree("getTree").getSelectedNodes().length > 0 && $('#query_string').val() !== '') {
+      $('#search_submit').removeAttr('disabled');
+      if ($('#save_name').val() !== '') {
+        $('#save_button, #update_button').removeAttr('disabled');
+      }
+    } else {
+      $('#save_button, #update_button, #search_submit').attr('disabled', 'disabled');
+    }
+  };
+
+  /********** PAGE ACTIONS **********/
+  // Setup the filters onload
+  $.ui.dynatree.nodedatadefaults["icon"] = false;
+  setup_filter_tree();
+  $(window).resize(function() {
+    var prevHeight;
+    if (prevHeight !== window.innerHeight) {
+      resizeSearch();
+    }
+    prevHeight = window.innerHeight;
+  });
+
+  /********** PAGE ELEMENT LISTENERS **********/
+  // Reload the filters when the table selector is changed
+  $('#blur_table').change(function() {
+    var prevMode, tree;
+    $(".column_family_filter").dynatree("option", "initAjax", get_filter_ajax());
+    tree = $(".column_family_filter").dynatree("getTree");
+    prevMode = tree.enableUpdate(false);
+    tree.reload();
+    tree.enableUpdate(prevMode);
+  });
+
+  // listener that checks if the submit button should be enabled on keystrokes
+  $('#query_string, #save_name').live("keydown", function(name) {
+    if (name.keyCode === 13 && !name.shiftKey) {
+      return name.preventDefault();
+    }
+  });
+
+  $('#query_string, #save_name').live("keyup", function(name) {
+    var error_content;
+    if (name.keyCode === 13 && !name.shiftKey) {
+      name.preventDefault();
+      if ($('#search_submit').attr('disabled')) {
+        error_content = '<div style="color:red;font-style:italic; font-weight:bold">Invalid query search.</div>';
+        $('#results_container').html(error_content);
+        $('#results_wrapper').removeClass('hidden');
+      } else {
+        $('#search_form').submit();
+      }
+    } else {
+      toggle_submit();
+    }
+  });
+
+  // listener that accordion the filter sections
+  $('.header').live('click', function() {
+    if ($('.tab:visible').length > 0) {
+      if ($(this).siblings('.tab:visible').length > 0) {
+        $(this).siblings('.tab:visible').slideUp('fast');
+        $(this).find('.arrow_up').hide();
+        $(this).find('.arrow_down').show();
+      } else {
+        $('.tab').slideToggle('fast');
+        $('.arrow').toggle();
+      }
+    } else {
+      $(this).siblings('.body').slideDown('fast');
+      $(this).find('.arrow_down').hide();
+      $(this).find('.arrow_up').show();
+    }
+  });
+
+  /********** more Functions **********/
+
+  var fetch_error = function(error) {
+    $('#results_container').html("<div class='no-results'>An error has occured: " + error + "</div>");
+    $('#results_wrapper').addClass('noResults').removeClass('hidden');
+  };
+
+  var no_results = function() {
+    $('#results_container').html('<div class="no-results">No results for your search.</div>');
+    $('#results_wrapper').addClass('noResults').removeClass('hidden');
+  };
+
+  // disable buttons on load
+  toggle_submit();
+  //set up listeners for ajax to show spinner and disable buttons
+  $('#loading-spinner').bind('ajaxStart', function() {
+    $(this).removeClass('hidden');
+  });
+  $('#loading-spinner').bind('ajaxStop', function() {
+    $(this).addClass('hidden');
+  });
+  $('#search_submit, #update_button, #save_button').bind('ajaxStart', function() {
+    $(this).attr('disabled', 'disabled');
+  });
+  $('#search_submit, #update_button, #save_button').bind('ajaxStop', function() {
+    toggle_submit();
+  });
+  $('html').live('click', function() {
+    hide_all_tabs();
+  });
+  $('.tab:visible, .header').live('click', function(e) {
+    return e.stopPropagation();
+  });
+
+  var populate_form = function(data) {
+    var column, _i, _len, _ref;
+    var oldTableName = $('#blur_table').val();
+    $(".column_family_filter").dynatree("getRoot").visit(function(node) {
+      return node.select(false);
+    });
+    $('#result_count').val(data.fetch);
+    $('#offset').val(data.offset);
+    $('#query_string').val(data.query);
+    $('#save_name').val(data.name);
+    //Checks to see if table still exists in hdfs before changing selector
+    if ($('#blur_table').find('option[value='+ data.blur_table_id + ']').length != 0){
+      $('#blur_table').val(data.blur_table_id);
+    }
+    /*
+    *This seems backwards, but the .change trigger was not firing when jQuery was changing the dropdown selector.
+    *This check forces the filter tree to refresh if the table changed
+    */
+    if (oldTableName != data.blur_table_id){
+      var prevMode, tree;
+      $(".column_family_filter").dynatree("option", "initAjax", get_filter_ajax());
+      tree = $(".column_family_filter").dynatree("getTree");
+      prevMode = tree.enableUpdate(false);
+      tree.reload();
+      tree.enableUpdate(prevMode);
+    }
+    if (data.super_query) {
+      $('#search_row').prop('checked', true);
+      $('#search_record').prop('checked', false);
+      $('#return_row').prop('checked', true);
+      $('#return_record').prop('checked', false).prop('disabled', true);
+    } else if (data.record_only) {
+      $('#search_row').prop('checked', false);
+      $('#search_record').prop('checked', true);
+      $('#return_row').prop('checked', false);
+      $('#return_record').prop('checked', true).prop('disabled', false);
+    } else {
+      $('#search_row').prop('checked', false);
+      $('#search_record').prop('checked', true);
+      $('#return_row').prop('checked', true);
+      $('#return_record').prop('checked', false).prop('disabled', false);
+    }
+    if (data.search_row) {
+      $('#search_row').click();
+    }
+    if (data.search_record) {
+      $('#search_record').click();
+    }
+    if (data.return_row) {
+      $('#return_row').click();
+    }
+    if (data.return_record) {
+      $('#return_record').click();
+    }
+    if (data.pre_filter){
+      $('#pre_filter').val(data.pre_filter);
+    }
+    if (data.post_filter){
+      $('#post_filter').val(data.post_filter);
+    }
+    //check everything in the tree
+    raw_columns = data.column_object;
+    for(index = 0; index < raw_columns.length; index++){
+      column = raw_columns[index];
+      $(".column_family_filter").dynatree("getTree").selectKey(column);
+    }
+
+    $('#search_submit').removeAttr('disabled');
+    $('#save_button').removeAttr('disabled');
+    $('#update_button').removeAttr('disabled');
+  };
+
+  var retrieve_search = function(id) {
+    $.ajax(Routes.search_path(id, {format: 'json'}), {
+      type: 'GET',
+      success: function(data) {
+        populate_form(data);
+      }
+    });
+  };
+
+   /********** PAGE AJAX LISTENERS **********/
+   // fetch the results of a new search
+  $('#search_form').submit(function() {
+    function runQuery(){
+      $('#results_wrapper').addClass('noResults').removeClass('hidden');
+      $('#results_wrapper').html('<div id="results_container"><div class="no-results">Loading...</div></div>');
+      $().closePopup();
+      $.ajax(Routes.fetch_results_zookeeper_searches_path(CurrentZookeeper, $('#blur_table').val()), {
+        data: form_data,
+        type: 'post',
+        success: function(data, status, xhr) {
+          if (data) {
+            $('#results_container').html(data);
+            resizeSearch();
+            $('#results_wrapper').removeClass('hidden noResults');
+          } else {
+            no_results();
+          }
+        },
+       error: function(xhr, status, error) {
+          fetch_error(error);
+        }
+      });
+    };
+
+    var form_data = $(this).serializeArray();
+    var tree = $('.column_family_filter').dynatree('getTree');
+    form_data = form_data.concat(tree.serializeArray());
+
+    if ($('#query_string').val().match(searchValidator.query)) {
+      var table = $('#blur_table option:selected').text();
+      if (!table.match(searchValidator.table)){
+        var buttons = {
+          "Ok": {
+            func: function() {
+              $().closePopup();
+            }
+          }
+        };
+        $().popup({
+          btns: buttons,
+          title: "Dangerous Query Detected",
+          titleClass: 'title',
+          body: "This query is not allowed on the \"" + table + "\" table, Please contact your admin for more information!"
+        });
+      } else {
+        var buttons = {
+        "Send Query": {
+          "class": 'primary',
+          func: runQuery
+        },
+          "Cancel": {
+            func: function() {
+              $().closePopup();
+            }
+          }
+        };
+
+        $().popup({
+          btns: buttons,
+          title: "Send this query?",
+          titleClass: 'title',
+          body: "This will run a potentially dangerous query on the \"" + table + "\" table, do you wish to continue?"
+        });
+      }
+    } else {
+      runQuery();
+    }
+    return false;
+  });
+
+  // ajax listener for the edit action
+  $('#edit_icon').live('click', function() {
+    retrieve_search($(this).parents('.search_element').attr('id'));
+    hide_all_tabs();
+  });
+
+  // ajax listener for the delete action
+  $('#delete_icon').live('click', function() {
+    var parent = $(this).parents('.search_element');
+    var buttons = {
+      "Delete Query": {
+        "class": 'primary',
+        func: function() {
+          $().closePopup();
+          $.ajax(Routes.search_path(parent.attr("id")), {
+            type: 'DELETE',
+            success: function(data) {
+              $('#saved .body .saved').html(data);
+            }
+          });
+        }
+      },
+    "Cancel": {
+        func: function() {
+          $().closePopup();
+        }
+      }
+    };
+    $().popup({
+      btns: buttons,
+      title: "Delete this saved query?",
+      titleClass: 'title',
+      body: "This will permanently delete the selected saved query. Do you wish to continue?"
+    });
+  });
+
+  //ajax listener for the save action
+  $('#save_button').live('click', function(evt) {
+    var form_data = $('#search_form').serializeArray();
+    var tree = $('.column_family_filter').dynatree('getTree');
+    form_data = form_data.concat(tree.serializeArray());
+    $.ajax(Routes.save_zookeeper_searches_path(CurrentZookeeper), {
+      type: 'POST',
+      data: form_data,
+      success: function(data) {
+        if (data) {
+          $('#searches').replaceWith(data);
+        }
+      }
+    });
+  });
+
+  //ajax listener for the update action
+  $('#update_button').live('click', function(evt) {
+    var match_found = false;
+    var send_request = false;
+    var search_id = "";
+    //if the name in the "name" field matches a search then we can update
+    $('.search_element').each(function(index, value) {
+      if ($.trim($(value).children('.search-name').text()) === $.trim($('#save_name').val())) {
+        //if we found another matching item do not send the update request
+        if (match_found) {
+          send_request = false;
+        }
+        send_request = true;
+        match_found = true;
+        search_id = $(value).attr('id');
+      }
+    });
+    if (send_request) {
+      var form_data = $('#search_form').serializeArray();
+      var tree = $('.column_family_filter').dynatree('getTree');
+      form_data = form_data.concat(tree.serializeArray());
+      $.ajax(Routes.search_path(search_id, {format: 'json'}), {
+        type: 'PUT',
+        data: form_data
+      });
+    } else {
+      if (match_found) {
+        var contentBody = "There are multiple saves with the same name.";
+      } else {
+        var contentBody = "There are no saved searches with that name.";
+      }
+      var message = "An error occurred while trying to update the saved search: " + contentBody + " To fix this error try changing the name.";
+      return $().popup({
+        title: 'Update Error',
+        titleClass: 'title',
+        body: message
+      });
+    }
+  });
+
+  //listener for the Search and Return Radiobuttons
+  $('#search_row, #search_record, #return_row, #return_record').live('change', function(evt) {
+    var search_row = $('#search_row');
+    var search_record = $('#search_record');
+    var return_row = $('#return_row');
+    var return_record = $('#return_record');
+    if (search_row[0] === $(this)[0]) {
+      search_record.prop('checked', false);
+      return_record.prop('checked', false);
+      return_record.prop('disabled', true);
+      return_row.prop('checked', true);
+    } else if (search_record[0] === $(this)[0]) {
+      search_row.prop('checked', false);
+      return_record.prop('disabled', false);
+    } else if (return_row[0] === $(this)[0]) {
+      return_record.prop('checked', false);
+    } else {
+      return_row.prop('checked', false);
+    }
+  });
+});

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates.js
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates.js b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates.js
new file mode 100644
index 0000000..388fd03
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates.js
@@ -0,0 +1 @@
+//= require_tree ./templates
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/active_tables.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/active_tables.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/active_tables.jst.ejs
new file mode 100644
index 0000000..248c6df
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/active_tables.jst.ejs
@@ -0,0 +1,18 @@
+<% if (cluster.get('can_update')) { %>
+  <button class="btn btn-primary" disabled="disabled" data-action="disable">Disable Tables</button>
+<% } %>
+<table class="table table-striped table-bordered sortable" blur_cluster_id='<%= cluster.get('id') %>' id="active_tables">
+  <thead>
+    <tr>
+      <th class="checkbox-td sorttable_nosort"><input class="check-all" type="checkbox" disabled="disabled"/></th>
+      <th>Name</th>
+      <th class="sorttable_nosort">Comments</th>
+      <th class="sorttable_nosort">Hosts | Shards</th>
+      <th>Row Count</th>
+      <th>Record Count</th>
+      <th class="sorttable_nosort">Info</th>
+    </tr>
+  </thead>
+  <tbody class="active-table">
+  </tbody>
+</table>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/cluster_view.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/cluster_view.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/cluster_view.jst.ejs
new file mode 100644
index 0000000..ecedac2
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/cluster_view.jst.ejs
@@ -0,0 +1,20 @@
+<ul class="cluster-tabs nav-tabs nav" id="<%= 'inner-tabs-cluster_' + cluster.get('id') %>">
+  <li class="active">
+    <a href="<%= '#cluster_' + cluster.get('id') + '_active' %>" data-toggle="tab">
+      Active Tables ( <span class="active-counter"><%= cluster.get('tables').where({table: 'active'}).length %></span> )
+    </a>
+  </li>
+  <li>
+    <a href="<%= '#cluster_' + cluster.get('id') + '_disabled' %>" data-toggle="tab">
+      Disabled Tables ( <span class="disabled-counter"><%= cluster.get('tables').where({table: 'disabled'}).length %></span> )
+    </a>
+  </li>
+</ul>
+<div class="tab-content">
+  <div class="tab-pane active" id="<%= 'cluster_' + cluster.get('id') + '_active' %>" data-state="active">
+    <%= JST['templates/blur_table/active_tables']({cluster: cluster}) %>
+  </div>
+  <div class="tab-pane" id="<%= 'cluster_' + cluster.get('id') + '_disabled' %>" data-state="disabled">
+    <%= JST['templates/blur_table/disabled_tables']({cluster: cluster}) %>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/comments.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/comments.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/comments.jst.ejs
new file mode 100644
index 0000000..226de5d
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/comments.jst.ejs
@@ -0,0 +1,4 @@
+<% { %>    
+    Comments:
+    <textarea id="comments" style="width: 75%;"><%=table.get('comments')%></textarea>
+<% } %>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/disabled_tables.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/disabled_tables.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/disabled_tables.jst.ejs
new file mode 100644
index 0000000..83566b2
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/disabled_tables.jst.ejs
@@ -0,0 +1,17 @@
+<% if (cluster.get('can_update')){ %>
+  <button class="btn btn-primary" disabled="disabled" data-action="enable">Enable Tables</button>
+  <button class="btn btn-danger" disabled="disabled" data-action="delete">Delete Tables</button>
+<% } %>
+<table class="table table-striped table-bordered sortable" blur_cluster_id='<%= cluster.get('id') %>' id="disabled_tables">
+  <thead>
+    <tr>
+      <th class="checkbox-td sorttable_nosort"><input class="check-all" type="checkbox" disabled="disabled"/></th>
+      <th>Name</th>
+			<th class="sorttable_nosort">Comments</th>
+      <th>Row Count</th>
+      <th>Record Count</th>
+    </tr>
+  </thead>
+  <tbody class="disabled-table">
+  </tbody>
+</table>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/hosts.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/hosts.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/hosts.jst.ejs
new file mode 100644
index 0000000..3aef7bb
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/hosts.jst.ejs
@@ -0,0 +1,19 @@
+<% if (hosts) { %>
+  <div class="hosts table_info_tree">
+    <b>Hosts</b>
+    <ul>
+      <% _.each(hosts, function(shards, host){ %>
+        <li class="host" id="<%= host %>">
+          <a href=""><%= host %></a>
+          <ul>
+            <% _.each(shards, function(shard){ %>
+              <li class="shard"><%= shard %></li>
+            <% }); %>
+          </ul>
+        </li>
+      <% }); %>
+    </ul>
+  </div>
+<% } else { %>
+  <div>Not Available</div>
+<% } %>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/schema.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/schema.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/schema.jst.ejs
new file mode 100644
index 0000000..519891f
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/schema.jst.ejs
@@ -0,0 +1,40 @@
+<% if(schema){ %>
+  <div class="schema_wrap">
+    <h4>Location</h4>
+    <a href="<%= '/hdfs/' + table.get('cluster_id') + '/show/' + table.parse_uri('path') %>"><%= table.get('table_uri') %></a>
+    <h4>Schema</h4>
+    <div class="info table_info_tree">
+      <ul>
+        <% _.each(schema, function(family){ %>
+          <li>
+            <a href="#"><%= family.name + ' (' + table.get('table_analyzer') + ')'%></a>
+            <ul>
+              <% _.each(family.columns, function(column){ %>
+                <li>
+                  <a href="#"><%= column.name %></a>
+                  <ul>
+                    <li><a href="#">Has Data?: <%= column.live %></a></li>
+                    <li><a href="#">Searchable?: <%= column.searchable %></a></li>
+                    <li><a href="#">Analyzer: <%= column.analyzer %></a></li>
+                    <li><a href="#">Full Text?: <%= column.fullText %></a></li>
+                    <% if(column.live && column.searchable) { %>
+                      <li data-family_name="<%= family.name%>" data-column_name="<%= column.name %>">
+                        <a href="#">
+                          <span class="terms" data-family-name="<%= family.name %>" data-column-name="<%= column.name %>">
+                              View Terms
+                          </span>
+                        </a>
+                      </li>
+                    <% } %>
+                  </ul>
+                </li>
+              <% }); %>
+            </ul>
+          </li>
+        <% }); %>
+      </ul>
+    </div>
+  </div>
+<% } else { %>
+  <div> Not Available </div>
+<% } %>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/table_row.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/table_row.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/table_row.jst.ejs
new file mode 100644
index 0000000..2d08c19
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/table_row.jst.ejs
@@ -0,0 +1,50 @@
+<% var state = table.get('state'); %>
+<% if (['disabling', 'enabling', 'deleting'].indexOf(state) >= 0){ %>
+  <% var colspan = table.colspan_lookup[table.get('table')]; %>
+  <td class='table-updating checkbox-td'>
+    <img id="loading-spinner" alt="Loading..." src="/assets/loader.gif"/>
+  </td>
+  <td colspan="<%= colspan %>"><%= table.capitalize_first(state) + ' ' + table.get('table_name') + '...' %></td>
+<% } else { %>
+  <td class='checkbox-td'>
+    <input class='bulk-action-checkbox' type='checkbox'/>
+  </td>
+  <td class='blur_table_name'>
+    <%= table.get('table_name') %>
+    <i class="icon-exclamation-sign queries-running-icon" title="Has been queried within last 5 minutes" style="<% if (!table.get('queried_recently')) { %><%= 'display:none' %><% } %>"></i>
+  </td>
+  <td class='comment_row' title= "<%= table.get('comments')%>" >
+    <%if (table.get('comments') != null) { %>
+      <% if (table.get('comments').length > 30) { %>
+        <%= table.get('comments').substring(0, 30) + "..." %>
+      <% }else { %>
+        <%= table.get('comments')%>
+      <% } %>
+    <% } %>
+    <a class='comments' href="#" style="float: right">
+      <button class="btn" type="submit" style="padding: 2px 5px"> <i class="icon-pencil"></i> </button>
+    </a>
+  </td>
+  <% if (state === 'active'){ %>
+    <td class='blur_table_hosts_shards'>
+      <a class='hosts' href="#">
+        <%= table.get('server_info') %>
+      </a>
+    </td>
+  <% } %>
+  <% if (state !== 'deleted'){ %>
+    <td class='blur_table_row_count'>
+      <%= table.get('row_count') %>
+    </td>
+    <td class='blur_table_record_count'>
+      <%= table.get('record_count') %>
+    </td>
+  <% } %>
+  <% if (state === 'active'){ %>
+    <td class='blur_table_info'>
+      <a class='info' href="#">
+        View
+      </a>
+    </td>
+  <% } %>
+<% } %>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_list.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_list.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_list.jst.ejs
new file mode 100644
index 0000000..ddd6578
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_list.jst.ejs
@@ -0,0 +1,14 @@
+<% if(terms.length > 0){ %>
+  <%_.each(terms, function(term){ %>
+    <li class="input-prepend term-li">
+      <span class="add-on search-term-link" term="<%= term %>">
+        <i class="icon-search"></i>
+      </span>
+      <span class="input uneditable-input term-input">
+        <span><%= term %></span>
+      </span>
+    </li>
+    <% }); %>
+<% } else { %>
+  <li class="no-items"> No terms matched your search conditions </li>
+<% } %>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_view.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_view.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_view.jst.ejs
new file mode 100644
index 0000000..598ce6f
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/blur_table/terms_view.jst.ejs
@@ -0,0 +1,11 @@
+<div id="new-popover-search" class="form-search" table_id="<%= table_id %>" family_name="<%= family %>" column_name="<%= column %>">
+  <input type="search" class="term-search span2" placeholder="Search..."/>
+  <a class="btn btn-primary term-search-btn">Search</a>
+</div>
+<ul class="terms-list well">
+  <%= JST['templates/blur_table/terms_list']({terms: terms}) %>
+</ul>
+<div class="more-terms btn-group">
+  <a href="#" class="more-terms-btn btn btn-primary">More...</a>
+  <a href="#" class="reset-terms btn"><i class="icon-refresh"></i></a>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/hdfs.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/hdfs.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/hdfs.jst.ejs
new file mode 100644
index 0000000..7520c32
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/hdfs.jst.ejs
@@ -0,0 +1,41 @@
+<% var stats = hdfs.get('most_recent_stats'); %>
+<div class="hdfs-title label">
+  <% if(hdfs.get('recent_stats')) { %>
+    <img src="/assets/online.png" title="HDFS Stats are current"/>
+  <% } else { %>
+    <img src="/assets/offline.png" title="HDFS Stats are haven't been updated in over a minute"/>
+  <% } %>
+  <span>
+    <%= hdfs.get('name') %>
+  </span>
+  <span class="title-subtle"><%= hdfs.get('host') %></span>
+</div>
+<div class="hdfs-body">
+	<% if (stats === null) { %>
+		<table>
+			<tr>
+				<td>Unable to retrieve stats.</td>
+			</tr>
+		</table>
+	<% } else { %>
+	  <table>
+	    <tr>
+	      <td class="hdfs-chart-container">
+					<div class="zk-cont-info">
+						<h6 class="<%= stats.missing_blocks === 0 ? '' : 'error-label'%>">Missing Blocks ( <%= stats.missing_blocks %> )</h6>
+						<h6 class="<%= stats.under_replicated === 0 ? '' : 'error-label'%>">Under-Replicated Blocks ( <%= stats.under_replicated %> )</h6>
+	      </td>
+	      <td class="hdfs-bar-container">
+	        <div class="hdfs-live progress progress-status <% if(stats.total_nodes < 1){ %>faded-bar<% }else{ %>red-bar<% } %>">
+	          <div class="bar green-bar" style="width:<%= hdfs.node_width() %>%"></div>
+	        </div>
+	        <%= stats.live_nodes %> out of <%= stats.total_nodes %> live nodes<br /><br />
+	        <div class="hdfs-dfs progress progress-status faded-bar">
+	          <div class="bar <% if(hdfs.usage_width()<70){ %>green-bar<% }else if(hdfs.usage_width()<90){ %>yellow-bar<% }else{ %>red-bar<% } %>" style="width:<%= hdfs.usage_width() %>%"></div>
+	        </div>
+	        <%= hdfs.percent_used() %> dfs usage
+	      </td>
+	    </tr>
+	  </table>
+	<% } %>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/long_running.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/long_running.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/long_running.jst.ejs
new file mode 100644
index 0000000..1738762
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/long_running.jst.ejs
@@ -0,0 +1,8 @@
+<% _.each(data, function(datum){ %>
+  <li class="long-running-entry">
+    <div class="icon" title="Cancel This Query" data-id="<%= datum.id %>">
+      <i class="icon-remove"/></div><div class="info">
+      <%= 'User Id: ' + datum.userid + ' | Query: ' + datum.query %>
+    </div>
+  </li>
+<% }); %>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/zookeeper.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/zookeeper.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/zookeeper.jst.ejs
new file mode 100644
index 0000000..cbfefce
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/dashboard/zookeeper.jst.ejs
@@ -0,0 +1,55 @@
+<div class="zookeeper-title label">
+  <%= zookeeper.status_image() %>
+  <span>
+    <%= zookeeper.get('name') %>
+  </span>
+</div>
+<div class="zookeeper-body">
+  <table>
+    <tr>
+      <td class="zk-chart">
+        <div class="cont-chart"></div>
+        <div class="chart-title-text">Controllers</div>
+      </td>
+      <td class="zookeeper-cont-info">
+        <div class="zk-cont-info">
+          <h6><%= zookeeper.get('controller_total') - zookeeper.get('controller_offline_node') %> Online<br /></h6>
+          <h6><%= zookeeper.get('controller_offline_node') %> Offline<br /></h6>
+          <% if(zookeeper.consistent_controller_versions()){ %>
+            <h6 title="Consistent Blur Versions">Version <i class="icon-ok"></i></h6>
+          <% } else { %>
+            <h6 class="error-label" title="Inconsistent Blur Versions">Version <i class="icon-remove"></i></h6>
+          <% } %>
+        </div>
+      </td>
+      <td class="zookeeper-shard-info">
+        <div class="zk-shard-info">
+          <h6><%= zookeeper.get('shard_total') - zookeeper.get('shard_offline_node') %> Online<br /></h6>
+          <h6><%= zookeeper.get('shard_offline_node') %> Offline<br /></h6>
+          <% if(zookeeper.consistent_shard_versions()){ %>
+            <h6 title="Consistent Blur Versions">Version <i class="icon-ok"></i></h6>
+          <% } else { %>
+            <h6 class="error-label" title="Inconsistent Blur Versions">Version <i class="icon-remove"></i></h6>
+          <% } %>
+        </div>
+      </td>
+      <td class="zk-chart">
+        <div class="shard-chart"></div>
+        <div class="chart-title-text">Shards</div>
+      </td>
+    </tr>
+    <% if(zookeeper.get('long_running_queries') > 0){ %>
+      <tr>
+        <td colspan="4">
+          <div class="query-warning">
+            <% if(zookeeper.get('long_running_queries') === 1){ %>
+              1 query has been running for more than a minute!
+            <% } else { %>
+              <%= zookeeper.get('long_running_queries') %> queries have been running for more than a minute!
+            <% } %>
+          </div>
+        </td>
+      </tr>
+    <% } %>
+  </table>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/cluster.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/cluster.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/cluster.jst.ejs
new file mode 100644
index 0000000..ed911c6
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/cluster.jst.ejs
@@ -0,0 +1,13 @@
+<td><%= cluster.get('name') %>
+ <i class="icon-exclamation-sign queries-running-icon" title="Has been queried within last 5 minutes" style="<% if (!cluster.get('cluster_queried')) { %><%= 'display:none' %><% } %>"></i>
+ </td>
+<td><%= cluster.get('shard_blur_version') %></td>
+<td><%= cluster.safe_mode() %></td>
+<td>
+  <a class="more-shard-info">
+    <%= cluster.get('shard_status') %>
+  </a>
+</td>
+<td>
+  <i class="icon-remove-sign destroy-cluster confirm-action" title="Remove This Cluster" />
+</td>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/controller.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/controller.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/controller.jst.ejs
new file mode 100644
index 0000000..5b60ca9
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/controller.jst.ejs
@@ -0,0 +1,7 @@
+<td><%= controller.get('node_name') %></td>
+<td><%= controller.get('blur_version') %></td>
+<td>
+  <% if(controller.get('status') == 0){ %>
+    <i class="icon-remove-sign icon-white destroy-controller confirm-action" title="Remove This Controller" />
+  <% } %>
+</td>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/shard.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/shard.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/shard.jst.ejs
new file mode 100644
index 0000000..670e113
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/shard.jst.ejs
@@ -0,0 +1,8 @@
+<% if (shard.get('status') == 0){%>
+  <div class="icon" title="Remove This Shard" data-id="<%= shard.get('id') %>">
+    <i class="icon-remove-sign"/>
+  </div>
+<% } %>
+<div class="info">
+  <%= shard.status() %>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/zookeeper.jst.ejs
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/zookeeper.jst.ejs b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/zookeeper.jst.ejs
new file mode 100644
index 0000000..3e9dd18
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/templates/environment/zookeeper.jst.ejs
@@ -0,0 +1,21 @@
+<h2 class="zookeeper-name">
+  <%= zookeeper.header() %>
+  <div class='nodes'>
+    <% if (zookeeper.get('ensemble').length > 0 ) { %>
+      <span class='states' data-original-title="<%= zookeeper.get('ensemble').join('</br>') %>">
+        Online (<%= zookeeper.get('ensemble').length %>)
+      </span>
+    <% } %>
+    <% if (zookeeper.get('ensemble').length > 0 && zookeeper.offline_nodes().length > 0) { %>
+      |
+    <% } %>
+    <% if (zookeeper.offline_nodes().length > 0 ) { %>
+      <span class='states' data-original-title="<%= zookeeper.offline_nodes().join('</br>') %>">
+        Offine (<%= zookeeper.offline_nodes().length %>)
+      </span>
+    <% } %>
+  </div>
+  <% if(zookeeper.get('status') == 0 && !zookeeper.quarum_failed()){ %>
+    <i class="icon-remove-sign destroy-zk icon-white" title="Forget this Zookeeper"/>
+  <% } %>
+</h2>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/javascripts/users.js
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/javascripts/users.js b/src/contrib/blur-console/blur-admin/app/assets/javascripts/users.js
new file mode 100644
index 0000000..50b8d65
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/javascripts/users.js
@@ -0,0 +1,105 @@
+$(document).ready(function(){
+  //Ajax request that serializes your columns and persists them to the DB
+  var save_pref = function(){
+    var user_id = $('#show_user_wrapper').attr('data-user-id');
+    $.ajax(Routes.user_preference_path(user_id, 'column', {format: 'json'}),
+    {
+      type: 'PUT',
+      data: $('#my-cols').sortable('serialize'),
+    });
+  };
+
+  //Sortable list of your chosen columns
+  $('#my-cols').sortable({
+    connectWith: "#actual-trash",
+    stop: function(){
+      save_pref();
+    }
+  });
+
+  //Trash can droppable, removes from your chosen preferences
+  $('#actual-trash').droppable({
+    drop: function(event, ui){
+      $(ui.draggable).remove();
+      $('.sort#my-cols').sortable('refresh');
+      $('.fam#' + $(ui.draggable).attr('id')).toggleClass('my-select');
+      save_pref();
+    }
+  });
+
+  //Click event for selecting a column from all possible columns
+  $('.fam').live('click', function(){
+    $(this).toggleClass('my-select');
+    var clicked = $('#' + $(this).attr('id') + '.sel-fam');
+
+    //if the element isnt in the list of selected columns
+    //add the column to your pref list
+    if (clicked.length == 0)
+    {
+      $('#no-saved').hide();
+      var app = $(this).clone().removeClass('fam my-select').addClass('sel-fam');
+      $('#my-cols').append(app.hide());
+      app.fadeIn('slow', function(){ save_pref(); });
+    }
+
+    //else the element is already in the list of selected columns
+    //remove it from the list of selected columns
+    else
+    {
+      clicked.fadeOut('slow', function(){
+        clicked.remove();
+        if ($('#my-cols').children().length == 1)
+        {
+          $('#no-saved').fadeIn('fast');
+        }
+        save_pref();
+      });
+    }
+  });
+
+  $('#pref-title').on('ajaxStart', function(){
+    $(this).removeClass('hidden-spinner');
+  });
+  $('#pref-title').on('ajaxStop', function(){
+    $(this).addClass('hidden-spinner');
+  });
+
+  //*******Zookeeper dropdown code********
+  //Helper functions
+  var checkSelectionStatus = function(){
+    if ($('#zookeeper_pref option:selected').val() != 1){
+      $('#zookeeper_num').hide();
+    } else{
+      $('#zookeeper_num').show();
+    }
+    $('#zookeeper_submit').removeAttr('disabled');
+  };
+  //Page Listeners
+  $('#zookeeper_pref').on('change', function(){
+   checkSelectionStatus();
+  });
+  $('#zookeeper_num').on('change', function(){
+    $('#zookeeper_submit').removeAttr('disabled');
+  });
+  $('#zookeeper_submit').on('click', function(){
+    var selected_pref = $('#zookeeper_pref option:selected').val();
+    var selected_zk = '';
+    if (selected_pref == 1 || 2){
+      selected_zk = $('#zookeeper_num option:selected').val();
+    }
+    var user_id = $('#show_user_wrapper').attr('data-user-id');
+    $.ajax(Routes.user_preference_path(user_id, 'zookeeper', {format: 'json'}), {
+      type: 'PUT',
+      data: {
+        name: selected_pref,
+        value: selected_zk
+      }
+    });
+    $('#zookeeper_submit').attr('disabled', 'disabled');
+  });
+  //Code for onLoad
+  checkSelectionStatus();
+  $('#zookeeper_submit').attr('disabled', 'disabled');
+
+});
+

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/application.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/application.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/application.scss
new file mode 100644
index 0000000..69520ea
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/application.scss
@@ -0,0 +1,32 @@
+//= require_self
+//= require ui.dynatree
+//= require jquery-ui
+
+// over ride any bootstrap variables
+$gridColumnWidth: 80px;
+
+//import libraries and root styles
+@import "bootstrap";
+@import "mixins";
+@import "base";
+@import "help";
+@import "navigation";
+@import "bootstrap_addons";
+
+// JQuery ones to look at
+@import "jquery.contextMenu";
+@import "jquery.osxFinder";
+@import "jquery.timepicker";
+
+// Application specific pages
+@import "search";
+@import "blur_queries";
+@import "blur_tables";
+@import "dashboard";
+@import "zookeeper";
+@import "user_session";
+@import "users";
+@import "hdfs";
+@import "hdfs_metrics";
+@import "audits";
+@import "errors";

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/audits.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/audits.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/audits.scss
new file mode 100644
index 0000000..a97ad0d
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/audits.scss
@@ -0,0 +1,90 @@
+#audits_wrapper{
+  #audits_table{
+      .row {
+        & > div:first-child {
+          vertical-align: top;
+          padding-top: 15px;
+        }
+
+        & > div:last-child {
+          float: right;
+        }
+
+        .span2, .span3{
+          float: right;
+        }
+
+        .span2{
+          width: 325px;
+          input{
+            width: 100px;
+            margin-right: 5px;
+          }
+          label{
+            display: inline-block;
+            width: 300px;
+            margin-bottom: 0px;
+          }
+          button{
+            margin-bottom: 10px;
+          }
+          .dataTables_processing{
+            display: none;
+          }
+        }
+      }
+
+      .dataTables_filter{ 
+        width: 100%;
+        float: right;
+        input{ width: 96%; }
+      }
+      
+      .dataTables_info {
+        padding-top: 8px;
+      }
+
+      .dataTables_processing {
+        padding-top: 8px;
+      }
+    th{
+      cursor: pointer;
+      margin-right: 10px;
+      .header_content {
+        position: relative;
+        div {
+          display: inline-block;
+          margin-right: 10px;
+        }
+      }
+
+      &.sorting_disabled{
+        cursor: default;
+      }
+
+      &.headerSortDown{
+        .icon-chevron-up{ display: none; }
+        .icon-chevron-down{ display: block; }
+      }
+
+      &.headerSortUp{
+        .icon-chevron-up{ display: block; }
+        .icon-chevron-down{ display: none; }
+      }
+
+      i{
+        position:absolute;
+        display: none;
+        &.icon-chevron-up{
+          top: 5px;
+          right: 10px;
+        }
+
+        &.icon-chevron-down{
+          bottom: 5px;
+          right: 10px;
+        }
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/base.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/base.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/base.scss
new file mode 100644
index 0000000..d1236b0
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/base.scss
@@ -0,0 +1,175 @@
+$base-theme-color: #f6a828;
+
+$red-state-color: #B81900;
+$red-border-color: #CD0A0A;
+$green-border-color: #62A630;
+
+$table-hd-color: #E4EDFF;
+$table-hd-text: #667495;
+
+$grey-color: #EEEEEE;
+$grey-div-color: #F0F0F0;
+
+$row-hover: #FFE4A3;
+
+$font-color: #555;
+$border_color: #999;
+$zk-header-color: #93A7AC;
+
+$border_width: 1px;
+$border_style: solid;
+
+$twitter-border: 1px solid #ccc;
+
+$blue-dashboard-color: #93A7AC;
+$faded-blue-dashboard-color: #CED7DA;
+$green-dashboard-color:  #7DC77D;
+$blue-chart-dashboard-color: #AFD8F8;
+$red-dashboard-color: #FF1919;
+$yellow-dashboard-color: #EDC240;
+
+// Page settings
+$footer-height: 45px;
+
+html{
+  height: 100%;
+  //min-height: 400px;
+	min-width: 1240px;
+  overflow: auto;
+  body{
+    position: relative;
+    padding-bottom: $footer-height;
+  }
+}
+h2{
+    color:$blue-dashboard-color;
+}
+#modal{
+	max-height:500px;
+	overflow:none;
+	.modal-body{
+		max-height:440px;
+		overflow-y:auto;
+		margin-bottom:60px;
+	}
+	.modal-footer{
+		position:absolute;
+		bottom:0px;
+		width: 530px;
+	}
+}
+
+input[placeholder].placeholder{
+	color: #888 !important;
+}
+
+#login_wrapper{
+	#error_explanation{
+		ul{
+			list-style: none;
+			color:red;
+		}
+	}
+
+	.help-inline{
+		color: red;
+		padding: 0px;
+		margin: 5px;
+	}
+
+	input:not(.btn){
+		display:block;
+		margin:auto;
+	}
+}
+
+.dynatree-connector ~ .dynatree-title{
+	cursor: default;
+}
+
+// Tree overrides
+ul.dynatree-container {
+	background-color: inherit !important;
+	color: inherit !important;
+	border: none !important;
+	a:focus, span.dynatree-focused a:link {
+		background-color: inherit !important;
+	}
+	li {
+	  line-height: 16px;
+		a:focus {
+			outline: none !important;
+		}
+		a {
+			background-color: inherit !important;
+			color: inherit !important;
+		}
+		border: none !important
+	}
+}
+.modal-list{
+  &.no-well{ background-color: white; }
+  list-style-type:none;
+  max-height:400px;
+  overflow: auto;
+  padding: 5px;
+  background-color: whitesmoke;
+  li{
+    &.error div{
+      background-color: rgba(218, 79, 73, .8);
+      color: white;
+      border-color: #DA4F49;
+      &.icon:hover{
+        background-color: rgba(218, 79, 73, .6);
+      }
+    }
+
+    &.no-error div{
+      //background-color: rgba(91, 183, 91, .9);
+      //color: white;
+      //border-color: #5BB75B;
+      &.icon:hover{
+        //background-color: rgba(91, 183, 91, .7);
+      }
+    }
+
+    &:not(:last-child){
+      padding-bottom: 3px;
+    }
+    height: 30px;
+    div{
+      border: solid 1px #CCC;
+    }
+    .icon ~ .info{
+      @include border-radius-left(0px);
+    }
+    .info{
+      background-color: white;
+      padding: 5px;
+      @include border-radius;
+      overflow-x: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+    .icon{
+      float: left;
+      display: inline-block;
+      @include border-radius-left;
+      @include clearfix;
+      background-color: whitesmoke;
+      border-right: none;
+      cursor: pointer;
+      vertical-align: top;
+      &:hover{
+        background-color: #999;
+        border-color: #999;
+      }
+      & > i {
+        margin: 6px;
+        margin-bottom: 7px;
+        background-color: transparent;
+      }
+    }
+  }
+}
+.hidden{ display: none !important; }

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_queries.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_queries.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_queries.scss
new file mode 100644
index 0000000..7754a70
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_queries.scss
@@ -0,0 +1,125 @@
+#queries-table_wrapper > .row:first-child > div:last-child {
+  float: right;
+}
+
+#blur_queries_wrapper {
+  padding-top: 2em;
+  padding-bottom: 2em;
+  @include standard-font;
+  @include clearfix;
+  .dataTables_filter{
+    width: 100%;
+    float: right;
+    input{
+      width: 96%;
+    }
+  }
+
+  .span2{
+    position: relative;
+    right:200px;
+    top:35px;
+  }
+  .span4{
+    position: relative;
+    left: 100px;
+    .dataTables_info{
+      text-align: center;
+    }
+  }
+  .dataTables_info {
+    padding-top: 8px;
+  }
+  .row > *:first-child {
+    vertical-align: top;
+    padding-top: 15px;
+  }
+  .range_select{
+    select{
+      width: 100px;
+    }
+  }
+  .dataTables_processing {
+    padding-top: 8px;
+  }
+  #queries-table{
+    table-layout:relative;
+    font-weight: normal;
+    td{
+      vertical-align: middle;
+      word-wrap: break-word
+    }
+    .cancel_query_button{
+      margin: 0;
+    }
+
+    form.cancel {
+      display: inline-block;
+      @include ie7-inline-block;
+      margin-right: 3px;
+      margin-bottom: 0;
+    }
+    tbody tr:not(.oldRunning){
+      & + .oldRunning, .oldRunning:first-child{
+        td{
+          border-top: 1px solid #FF0000;
+        }
+      }
+      height: 45px;
+    }
+    .oldRunning{
+      td{
+        background: rgba(247, 225, 225, 0.8);
+        border-bottom: 1px solid #FF0000;
+      }
+    }
+    th{
+      cursor: pointer;
+      margin-right: 10px;
+      .header_content {
+        position: relative;
+        div {
+          display: inline-block;
+          margin-right: 10px;
+        }
+      }
+
+      &.headerSortDown{
+        .icon-chevron-up{
+          display: none;
+        }
+        .icon-chevron-down{
+          display: block;
+        }
+      }
+
+      &.headerSortUp{
+        .icon-chevron-up{
+          display: block;
+        }
+        .icon-chevron-down{
+          display: none;
+        }
+      }
+
+      i{
+        position:absolute;
+        display: none;
+        &.icon-chevron-up{
+          top: 5px;
+          right: 10px;
+        }
+
+        &.icon-chevron-down{
+          bottom: 5px;
+          right: 10px;
+        }
+      }
+    }
+  }
+}
+
+#more-info-table {
+  td { color: #555; }
+  .more-info-label { white-space: nowrap; font-weight: bold;}
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_tables.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_tables.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_tables.scss
new file mode 100644
index 0000000..5bf5276
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/blur_tables.scss
@@ -0,0 +1,92 @@
+#blur_tables {
+  width: 99%;
+  border: none;
+  margin: 15px 10px 0;
+  table { margin-bottom: 5px; }
+  .active a, .active a:hover{ background-color:#F9F9F9; }
+}
+#tables-wrapper{
+  border: $twitter-border;
+  padding:10px;
+  @include border-radius(5px);
+}
+
+.cluster-tabs{
+  margin:15px 0;
+  .active a, .active a:hover{ background-color:#F9F9F9; }
+}
+.bulk-action-selector{ margin: 10px 5px 10px 0px; }
+tr.highlighted-row td{ background:#FAD08A !important; }
+.live-col{
+  color: $green-border-color ! important;
+}
+.disabled-col{
+  color: $red-border-color ! important;
+}
+.popover-close{
+  position:absolute;
+  top:15px;
+  right:15px;
+  &:hover{
+    cursor: pointer;
+    background-color:#CCC;
+    border-radius:3px;
+  }
+}
+.terms{
+  color:#08C;
+  text-decoration:none;
+  cursor:pointer;
+  &:hover{
+    color:#048;
+    text-decoration:underline;
+  }
+}
+.reset-term-search{
+  display:none;
+}
+
+.terms-list{
+  list-style-type:none;
+  max-height:400px;
+  overflow-y:auto;
+  padding:5px;
+  padding-bottom: 0px;
+  .uneditable-input{
+    margin-bottom: 0px;
+  }
+}
+.search-term-link{
+  cursor:pointer;
+  &:hover{
+    background-color:#CCC;
+  }
+}
+.term-input{
+  cursor:default;
+  & > span{
+    cursor:text;
+    padding-left:10px;
+  }
+}
+.more-terms{
+  margin-top:10px;
+}
+.table .checkbox-td{
+  width:20px;
+  text-align: center;
+}
+
+.popover{
+  #loading-spinner{
+    padding: 5px;
+  }
+}
+.comment_row{
+  width: 250px;
+}
+.blur_table_row_count{
+  width:150px;
+}
+
+th:not(.sorttable_nosort) { cursor: pointer; }

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/bootstrap_addons.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/bootstrap_addons.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/bootstrap_addons.scss
new file mode 100644
index 0000000..2745167
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/bootstrap_addons.scss
@@ -0,0 +1,6 @@
+input[type="text"],input[type="email"],input[type="password"],textarea,select{color:#000 !important;}
+
+table {
+  margin: 1em 0;
+  clear: both;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/dashboard.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/dashboard.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/dashboard.scss
new file mode 100644
index 0000000..265f515
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/dashboard.scss
@@ -0,0 +1,161 @@
+@mixin box-title {
+  position:absolute;
+  display:block;
+  top:-18px;
+  left:20px;
+  background:#fff;
+}
+
+@mixin zoo-widget {
+  border-top:$twitter-border;
+  padding-top:20px;
+  position:relative;
+}
+
+@mixin zoo-status {
+	text-align: center;
+  display: inline-block;
+  padding:1px 15px 1px;
+  margin: 2px 0 2px;
+  &.important{font-style:italic;}
+}
+
+#zookeepers_wrapper, #hdfs_dash_wrapper {
+  @include standard-font;
+  @include zoo-widget;
+  margin-top: 2em;
+
+  .zookeeper_info, .hdfs_info {
+    width: 450px;
+    margin: 0px 10px 20px 20px;
+    display: inline-block;
+    border: 1px solid;
+    font-size: 15px;
+    border-color: $blue-dashboard-color;
+    @include border-radius(5px);
+
+    table{ margin:0; width:100%; }
+    table tbody th { text-align:center; vertical-align:middle; }
+    .status-bar{ @include border-radius() }
+
+    &:hover{
+      cursor: pointer;
+      background: #F4F5F6;
+    }
+  }
+
+  .zookeeper-title, .hdfs-title {
+    font-size: 130%;
+    padding: 5px 10px;
+    text-align: left;
+		@include border-radius-bottom(0);
+    img {
+      height: 18px;
+    }
+  }
+
+	.hdfs-body {
+		min-height: 177px;
+	}
+
+  .zookeeper-body, .hdfs-body {
+    width: 430px;
+    margin: 10px;
+
+    td {text-align: center;}
+    h6{ color: $font-color; }
+
+    .zookeeper-cont-info, .zookeeper-shard-info {
+      width: 65px;
+      vertical-align: middle;
+      .zk-shard-info { text-align: right; }
+      .zk-cont-info{ text-align: left; }
+    }
+
+    .hdfs-chart { margin: 0 0 10px 30px; }
+    .cont-chart, .shard-chart { margin-left: 5px; }
+
+    .query-warning {
+      color: $red-dashboard-color;
+      margin-top: 10px;
+    }
+
+    .chart-title-text {
+      margin-top: -136px;
+      z-index: 1;
+    }
+
+    .legend{
+      margin: -124px 0 0 77px;
+      z-index: 1;
+      h6{ float: left; }
+
+      .legend-box {
+        width: 12px;
+        height: 12px;
+        float: left;
+        margin: 2px 5px 0 0;
+        border: 1px solid $border_color;
+      }
+
+      .healthy{ background-color: $green-dashboard-color; }
+      .corrupt{ background-color: $blue-chart-dashboard-color; }
+      .missing{ background-color: $red-dashboard-color; }
+      .under-replicated{ background-color: $yellow-dashboard-color; }
+    }
+
+    .error-label{ color: $red-dashboard-color; }
+
+    .zk-chart{
+      $zk-size: 135px;
+      width: $zk-size;
+      line-height: $zk-size;
+      height: $zk-size;
+      position: relative;
+      text-align: center;
+    }
+
+    .hdfs-chart-container {
+      $hdfs-size: 175px;
+      width: $hdfs-size;
+      height: $hdfs-size;
+      position: relative;
+      text-align: center;
+    }
+
+    .hdfs-chart { margin-top: -50px }
+
+    .hdfs-bar-container {
+      width: 130px;
+      padding-right: 20px;
+    }
+  }
+
+  #zookeepers,#hdfses{ height: 100%; }
+	h2 { color: $zk-header-color; @include box-title;}
+
+  .progress-status{
+    background-image: none;
+    position: relative;
+    margin: 0px;
+    @include border-radius();
+    .bar{
+      @include border-radius();
+      background-image: none;
+    }
+  }
+  .red-bar { background-color: $red-dashboard-color; }
+  .faded-bar { background-color: $faded-blue-dashboard-color; }
+  .green-bar { background-color: $green-dashboard-color; }
+  .yellow-bar { background-color: $yellow-dashboard-color; }
+
+  span.title-subtle{
+    float: right;
+    opacity: .7;
+  }
+
+  .label{
+    background-color: $blue-dashboard-color;
+    width: 430px;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/errors.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/errors.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/errors.scss
new file mode 100644
index 0000000..92a0394
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/errors.scss
@@ -0,0 +1,23 @@
+#error_wrapper{
+  h1 {
+    text-align:center;
+  }
+  h2 {
+    text-align:center;
+    color:black;
+  }
+  img {
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+  }
+  h3 {
+    text-align:center;
+    color:black;
+  }
+}
+#error_message {
+  display: block;
+  margin-left:auto;
+  margin-right:auto;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs.scss
new file mode 100644
index 0000000..7429ea2
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs.scss
@@ -0,0 +1,129 @@
+#newFolder {
+  text-align: center;
+  input {
+    width: 20em;
+  }
+}
+
+
+#hdfs_wrapper{
+  @include standard-font;
+  padding-bottom: 20px;
+  @include box-sizing(border-box);
+  height: 300px;
+
+  #hdfs_browser {
+    background-color: #F8F8F8;
+    @include border;
+    @include border-radius;
+    overflow-y: auto;
+    div.innerWindow {
+      @include border;
+      background-color: white;
+      .noFiles {
+        font-size: 1.2em;
+        font-style: italic;
+        text-align: center;
+      }
+      >ul>li {
+        &.file, &.folder, &.hdfs_instance {
+          a {
+            @include box-sizing(border-box);
+            display: block;
+            width: 225px;
+            overflow-x: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            padding-right: 20px;
+          }
+        }
+        &.folder, &.hdfs_instance {
+          background: url("expand_folder.png") no-repeat scroll right center transparent;
+        }
+        &.file a {
+          background: url("file16.png") no-repeat scroll left center transparent;
+          padding-left: 20px;
+        }
+        &.hdfs_instance a {
+          background: url("database16.png") no-repeat scroll left center transparent;
+          padding-left: 20px;
+        }
+        &.folder a {
+          background: url("folder16.png") no-repeat scroll left center transparent;
+          padding-left: 20px;
+        }
+        &:hover, &.rclicked{
+          border:  1px solid #B8D6FD;
+        }
+        &.osxSelected {
+          background-color:#3875D7;
+          border:  1px solid #3875D7;
+          a {
+            color: white;
+          }
+        }
+      }
+    }
+  }
+
+  #file_details_table {
+    tr:nth-child(even) { background-color: white; };
+    tr:nth-child(odd) { background-color: $grey-div-color; }
+    table { margin: 0; @include border;}
+    th {
+      background-color: $table-hd-color;
+      color: $table-hd-text;
+    }
+    th.name, td.name {text-align: left; }
+    th, td {
+      @include standard-font;
+      text-align: center;
+    }
+    tr:hover {
+      cursor: pointer;
+      background: $row-hover;
+    }
+  }
+
+  .to-cut {
+    a { color: #AAA; }
+  }
+}
+
+#modal{
+  max-height: 600px;
+  .search-info-section{
+    width: 49%;
+    display: inline-block;
+    vertical-align: top;
+    .radial-graph{
+      position: relative;
+      text-align: center;
+      height: 400px;
+      width: 100%;
+      path{
+        cursor: pointer;
+        &:hover{
+          opacity: .6;
+        }
+      }
+      .graphtip{
+        position: absolute;
+        display: block;
+        z-index: 50;
+        #tipcontent{
+          padding: 1px 6px 1px 6px;
+          border: 4px solid #e2e2e2;
+          max-width: 400px;
+          background: white;
+          color: black;
+          @include border-radius(5px);
+        }
+      }
+    }
+  }
+  .hidden{ display: none; }
+  #upload_file_warning{ color: red; font-weight: bold; }
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs_metrics.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs_metrics.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs_metrics.scss
new file mode 100644
index 0000000..3ca2f69
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/hdfs_metrics.scss
@@ -0,0 +1,110 @@
+$title_height: 35px;
+$graph_height: 240px;
+$total_graph_height: $graph_height + 60px;
+$instance_height: $title_height + $total_graph_height;
+
+@mixin graph_component{
+	display: inline-block;
+	@include box-sizing(border-box);
+}
+
+@mixin clickable_title{
+	height: $title_height;
+	h3{ line-height: $title_height; }
+	text-align: center;
+	border: 1px solid #ccc;
+	@include gradient-vertical(#fff, #F4F4F4);
+}
+
+@mixin clickable{
+	cursor: pointer;
+	&:hover{
+		opacity: .6;
+	}
+}
+
+#metrics_page_wrapper {
+	.create_graph_prompt{
+		margin-top: 10px;
+		@include clickable_title;
+		@include clickable;
+	}
+	.joined_instance{
+		.graph_title{
+			position: relative;
+			i{
+				position: absolute;
+				top: 10px;
+				right: 10px;
+				@include clickable;
+			}
+		}
+	}
+
+	.graph_instance, .joined_instance {
+		margin: 10px 0 10px 0;
+		position: relative;
+		height: $instance_height;
+		&:not(:last-child){
+			.graph_content{
+				border-bottom: none;
+			}
+		}
+		.graph_title{
+			@include clickable_title;
+			border-bottom: none;
+		}
+		.graph_content{
+			@include graph_component;
+			width: 100%;
+			height: $total_graph_height;
+			border: 1px solid #ccc;
+			position: absolute;
+			.graph_data{
+				@include box-sizing(border-box);
+				width: 100%;
+				padding: 10px 10px 0 10px;
+				.graph{
+          margin: 5px 5px 5px 5px;
+					height: $graph_height - 20;
+				}
+			}
+      .graph_info {
+				padding: 0 50px 0 205px;
+        bottom: 0;
+        .graph-info-table {
+          width: 100%;
+          margin: -5px 0 0 0;
+          .slider-info{
+            text-align: right;
+            .slider-time{
+              text-align: right;
+              width: 14px;
+            }
+            .min-date, .max-date {
+              text-align: right;
+              width: 100px;
+            }
+            .slider-redraw { margin: 0 5px 9px 0; }
+          }
+          .slider-box {
+            width: 350px;
+            .slider{
+              width: 300px;
+              margin-right: 15px;
+              float: right;
+            }
+          }
+          span.axis-value{
+            font-weight: bold;
+          }
+        }
+      }
+		}
+	}
+  .loading-spinner {
+    float: left;
+    position: absolute;
+    padding: 9px 0 0 9px;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b5b86c7e/src/contrib/blur-console/blur-admin/app/assets/stylesheets/help.scss
----------------------------------------------------------------------
diff --git a/src/contrib/blur-console/blur-admin/app/assets/stylesheets/help.scss b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/help.scss
new file mode 100644
index 0000000..6c55908
--- /dev/null
+++ b/src/contrib/blur-console/blur-admin/app/assets/stylesheets/help.scss
@@ -0,0 +1,23 @@
+
+#page-help{ text-decoration: none; }
+#help-window{
+  overflow: auto;
+  height: 600px;
+	max-width: 500px;
+  .help-section{
+    cursor: pointer;
+    margin: 2px;
+    padding: 8px;
+    padding-left: 10px;
+    background: #EEE;
+    @include standard-border;
+    .help-label{
+      margin: 0px;
+      margin-bottom: 5px;
+    }
+    .head{
+      margin-bottom: 2px;
+    }
+    ul{ margin-top: 3px; }
+  }
+}


Mime
View raw message