metron-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From omal...@apache.org
Subject [33/51] [partial] incubator-metron git commit: Initial import of code from https://github.com/OpenSOC/opensoc at ac0b00373f8f56dfae03a8109af5feb373ea598e.
Date Tue, 08 Dec 2015 06:37:57 GMT
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/components/kbn.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/components/kbn.js b/opensoc-ui/lib/public/app/components/kbn.js
new file mode 100755
index 0000000..a42e1cb
--- /dev/null
+++ b/opensoc-ui/lib/public/app/components/kbn.js
@@ -0,0 +1,632 @@
+define([
+  'jquery',
+  'lodash',
+  'moment',
+  'chromath'
+],
+function($, _, moment) {
+  'use strict';
+
+  var kbn = {};
+
+  kbn.get_object_fields = function(obj) {
+    var field_array = [];
+    obj = kbn.flatten_json(obj._source);
+    for (var field in obj) {
+      field_array.push(field);
+    }
+    return field_array.sort();
+  };
+
+  kbn.get_all_fields = function(data,flat) {
+    return _.uniq(_.without(_.reduce(data,function(memo,hit) {
+      return flat ? memo.concat(_.keys(kbn.flatten_json(hit._source))) : memo.concat(_.keys(hit._source));
+    },[]),'$$hashkey'));
+  };
+
+  kbn.has_field = function(obj,field) {
+    var obj_fields = kbn.get_object_fields(obj);
+    if (_.inArray(obj_fields,field) < 0) {
+      return false;
+    } else {
+      return true;
+    }
+  };
+
+  kbn.get_related_fields = function(docs,field) {
+    var field_array = [];
+    _.each(docs, function(doc) {
+      var keys = _.keys(doc);
+      if(_.contains(keys,field)) {
+        field_array = field_array.concat(keys);
+      }
+    });
+    var counts = _.countBy(_.without(field_array,field),function(field){return field;});
+    return _.map(counts, function(num, key){return {name:key,count:num};});
+  };
+
+  kbn.recurse_field_dots = function(object,field) {
+    var value = null;
+    var nested;
+    if (typeof object[field] !== 'undefined') {
+      value = object[field];
+    }
+    else if (nested = field.match(/(.*?)\.(.*)/)) {
+      if(typeof object[nested[1]] !== 'undefined') {
+        value = (typeof object[nested[1]][nested[2]] !== 'undefined') ?
+          object[nested[1]][nested[2]] : kbn.recurse_field_dots(
+            object[nested[1]],nested[2]);
+      }
+    }
+
+    return value;
+  };
+
+  kbn.top_field_values = function(docs,field,count,grouped) {
+    var all_values = _.pluck(docs,field),
+      groups = {},
+      counts,
+      hasArrays;
+    // manually grouping into pairs allows us to keep the original value,
+    _.each(all_values, function (value) {
+      var k;
+      if(_.isArray(value)) {
+        hasArrays =  true;
+      }
+      if(_.isArray(value) && !grouped) {
+        k = value;
+      } else {
+        k = _.isUndefined(value) ? '' : [value.toString()];
+      }
+      _.each(k, function(key) {
+        if (_.has(groups, key)) {
+          groups[key][1] ++;
+        } else {
+          groups[key] = [(grouped ? value : key), 1];
+        }
+      });
+    });
+
+    counts = _.values(groups).sort(function(a, b) {
+      return a[1] - b[1];
+    }).reverse().slice(0,count);
+
+    return {
+      counts: counts,
+      hasArrays : hasArrays
+    };
+  };
+
+   /**
+     * Calculate a graph interval
+     *
+     * from::           Date object containing the start time
+     * to::             Date object containing the finish time
+     * size::           Calculate to approximately this many bars
+     * user_interval::  User specified histogram interval
+     *
+     */
+  kbn.calculate_interval = function(from,to,size,user_interval) {
+    if(_.isObject(from)) {
+      from = from.valueOf();
+    }
+    if(_.isObject(to)) {
+      to = to.valueOf();
+    }
+    return user_interval === 0 ? kbn.round_interval((to - from)/size) : user_interval;
+  };
+
+  kbn.round_interval = function(interval) {
+    switch (true) {
+    // 0.5s
+    case (interval <= 500):
+      return 100;       // 0.1s
+    // 5s
+    case (interval <= 5000):
+      return 1000;      // 1s
+    // 7.5s
+    case (interval <= 7500):
+      return 5000;      // 5s
+    // 15s
+    case (interval <= 15000):
+      return 10000;     // 10s
+    // 45s
+    case (interval <= 45000):
+      return 30000;     // 30s
+    // 3m
+    case (interval <= 180000):
+      return 60000;     // 1m
+    // 9m
+    case (interval <= 450000):
+      return 300000;    // 5m
+    // 20m
+    case (interval <= 1200000):
+      return 600000;    // 10m
+    // 45m
+    case (interval <= 2700000):
+      return 1800000;   // 30m
+    // 2h
+    case (interval <= 7200000):
+      return 3600000;   // 1h
+    // 6h
+    case (interval <= 21600000):
+      return 10800000;  // 3h
+    // 24h
+    case (interval <= 86400000):
+      return 43200000;  // 12h
+    // 48h
+    case (interval <= 172800000):
+      return 86400000;  // 24h
+    // 1w
+    case (interval <= 604800000):
+      return 86400000;  // 24h
+    // 3w
+    case (interval <= 1814400000):
+      return 604800000; // 1w
+    // 2y
+    case (interval < 3628800000):
+      return 2592000000; // 30d
+    default:
+      return 31536000000; // 1y
+    }
+  };
+
+  kbn.secondsToHms = function(seconds){
+    var numyears = Math.floor(seconds / 31536000);
+    if(numyears){
+      return numyears + 'y';
+    }
+    var numdays = Math.floor((seconds % 31536000) / 86400);
+    if(numdays){
+      return numdays + 'd';
+    }
+    var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
+    if(numhours){
+      return numhours + 'h';
+    }
+    var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
+    if(numminutes){
+      return numminutes + 'm';
+    }
+    var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
+    if(numseconds){
+      return numseconds + 's';
+    }
+    return 'less then a second'; //'just now' //or other string you like;
+  };
+
+  kbn.to_percent = function(number,outof) {
+    return Math.floor((number/outof)*10000)/100 + "%";
+  };
+
+  kbn.addslashes = function(str) {
+    str = str.replace(/\\/g, '\\\\');
+    str = str.replace(/\'/g, '\\\'');
+    str = str.replace(/\"/g, '\\"');
+    str = str.replace(/\0/g, '\\0');
+    return str;
+  };
+
+  kbn.interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/;
+
+  // histogram & trends
+  kbn.intervals_in_seconds = {
+    y: 31536000,
+    M: 2592000,
+    w: 604800,
+    d: 86400,
+    h: 3600,
+    m: 60,
+    s: 1
+  };
+
+  kbn.describe_interval = function (string) {
+    var matches = string.match(kbn.interval_regex);
+    if (!matches || !_.has(kbn.intervals_in_seconds, matches[2])) {
+      throw new Error('Invalid interval string, expecting a number followed by one of "Mwdhmsy"');
+    } else {
+      return {
+        sec: kbn.intervals_in_seconds[matches[2]],
+        type: matches[2],
+        count: parseFloat(matches[1])
+      };
+    }
+  };
+
+  kbn.interval_to_ms = function(string) {
+    var info = kbn.describe_interval(string);
+    return Math.ceil(info.sec * 1000 * info.count);
+  };
+
+  kbn.interval_to_seconds = function (string) {
+    var info = kbn.describe_interval(string);
+    return Math.ceil(info.sec * info.count);
+  };
+
+  // This should go away, moment.js can do this
+  kbn.time_ago = function(string) {
+    return new Date(new Date().getTime() - (kbn.interval_to_ms(string)));
+  };
+
+  /* This is a simplified version of elasticsearch's date parser */
+  kbn.parseDate = function(text) {
+    if(_.isDate(text)) {
+      return text;
+    }
+    var time,
+      mathString = "",
+      index,
+      parseString;
+    if (text.substring(0,3) === "now") {
+      time = new Date();
+      mathString = text.substring("now".length);
+    } else {
+      index = text.indexOf("||");
+      parseString;
+      if (index === -1) {
+        parseString = text;
+        mathString = ""; // nothing else
+      } else {
+        parseString = text.substring(0, index);
+        mathString = text.substring(index + 2);
+      }
+      // We're going to just require ISO8601 timestamps, k?
+      time = new Date(parseString);
+    }
+
+    if (!mathString.length) {
+      return time;
+    }
+
+    //return [time,parseString,mathString];
+    return kbn.parseDateMath(mathString, time);
+  };
+
+  kbn.parseDateMath = function(mathString, time, roundUp) {
+    var dateTime = moment(time);
+    for (var i = 0; i < mathString.length; ) {
+      var c = mathString.charAt(i++),
+        type,
+        num,
+        unit;
+      if (c === '/') {
+        type = 0;
+      } else if (c === '+') {
+        type = 1;
+      } else if (c === '-') {
+        type = 2;
+      } else {
+        return false;
+      }
+
+      if (isNaN(mathString.charAt(i))) {
+        num = 1;
+      } else {
+        var numFrom = i;
+        while (!isNaN(mathString.charAt(i))) {
+          i++;
+        }
+        num = parseInt(mathString.substring(numFrom, i),10);
+      }
+      if (type === 0) {
+        // rounding is only allowed on whole numbers
+        if (num !== 1) {
+          return false;
+        }
+      }
+      unit = mathString.charAt(i++);
+      switch (unit) {
+      case 'y':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('year') : dateTime.startOf('year');
+        } else if (type === 1) {
+          dateTime.add('years',num);
+        } else if (type === 2) {
+          dateTime.subtract('years',num);
+        }
+        break;
+      case 'M':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('month') : dateTime.startOf('month');
+        } else if (type === 1) {
+          dateTime.add('months',num);
+        } else if (type === 2) {
+          dateTime.subtract('months',num);
+        }
+        break;
+      case 'w':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('week') : dateTime.startOf('week');
+        } else if (type === 1) {
+          dateTime.add('weeks',num);
+        } else if (type === 2) {
+          dateTime.subtract('weeks',num);
+        }
+        break;
+      case 'd':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('day') : dateTime.startOf('day');
+        } else if (type === 1) {
+          dateTime.add('days',num);
+        } else if (type === 2) {
+          dateTime.subtract('days',num);
+        }
+        break;
+      case 'h':
+      case 'H':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('hour') : dateTime.startOf('hour');
+        } else if (type === 1) {
+          dateTime.add('hours',num);
+        } else if (type === 2) {
+          dateTime.subtract('hours',num);
+        }
+        break;
+      case 'm':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('minute') : dateTime.startOf('minute');
+        } else if (type === 1) {
+          dateTime.add('minutes',num);
+        } else if (type === 2) {
+          dateTime.subtract('minutes',num);
+        }
+        break;
+      case 's':
+        if (type === 0) {
+          roundUp ? dateTime.endOf('second') : dateTime.startOf('second');
+        } else if (type === 1) {
+          dateTime.add('seconds',num);
+        } else if (type === 2) {
+          dateTime.subtract('seconds',num);
+        }
+        break;
+      default:
+        return false;
+      }
+    }
+    return dateTime.toDate();
+  };
+
+  // LOL. hahahahaha. DIE.
+  kbn.flatten_json = function(object,root,array) {
+    if (typeof array === 'undefined') {
+      array = {};
+    }
+    if (typeof root === 'undefined') {
+      root = '';
+    }
+    for(var index in object) {
+      var obj = object[index];
+      var rootname = root.length === 0 ? index : root + '.' + index;
+      if(typeof obj === 'object' ) {
+        if(_.isArray(obj)) {
+          if(obj.length > 0 && typeof obj[0] === 'object') {
+            var strval = '';
+            for (var objidx = 0, objlen = obj.length; objidx < objlen; objidx++) {
+              if (objidx > 0) {
+                strval = strval + ', ';
+              }
+
+              strval = strval + JSON.stringify(obj[objidx]);
+            }
+            array[rootname] = strval;
+          } else if(obj.length === 1 && _.isNumber(obj[0])) {
+            array[rootname] = parseFloat(obj[0]);
+          } else {
+            array[rootname] = typeof obj === 'undefined' ? null : obj;
+          }
+        } else {
+          kbn.flatten_json(obj,rootname,array);
+        }
+      } else {
+        array[rootname] = typeof obj === 'undefined' ? null : obj;
+      }
+    }
+    return kbn.sortObj(array);
+  };
+
+  kbn.xmlEnt = function(value) {
+    if(_.isString(value)) {
+      var stg1 = value.replace(/</g, '&lt;')
+        .replace(/>/g, '&gt;')
+        .replace(/\r\n/g, '<br/>')
+        .replace(/\r/g, '<br/>')
+        .replace(/\n/g, '<br/>')
+        .replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;')
+        .replace(/  /g, '&nbsp;&nbsp;')
+        .replace(/&lt;del&gt;/g, '<del>')
+        .replace(/&lt;\/del&gt;/g, '</del>');
+      return stg1;
+    } else {
+      return value;
+    }
+  };
+
+  kbn.sortObj = function(arr) {
+    // Setup Arrays
+    var sortedKeys = [];
+    var sortedObj = {};
+    var i;
+    // Separate keys and sort them
+    for (i in arr) {
+      sortedKeys.push(i);
+    }
+    sortedKeys.sort();
+
+    // Reconstruct sorted obj based on keys
+    for (i in sortedKeys) {
+      sortedObj[sortedKeys[i]] = arr[sortedKeys[i]];
+    }
+    return sortedObj;
+  };
+
+  kbn.query_color_dot = function (color, diameter) {
+    return '<div class="icon-circle" style="' + [
+        'display:inline-block',
+        'color:' + color,
+        'font-size:' + diameter + 'px',
+      ].join(';') + '"></div>';
+  };
+
+  kbn.colorSteps = function(col,steps) {
+
+    var _d = steps > 5 ? 1.6/steps : 0.25, // distance between steps
+      _p = []; // adjustment percentage
+
+    // Create a range of numbers between -0.8 and 0.8
+    for(var i = 1; i<steps+1; i+=1) {
+      _p.push(i%2 ? ((i-1)*_d*-1)/2 : i*_d/2);
+    }
+
+    // Create the color range
+    return _.map(_p.sort(function(a,b){return a-b;}),function(v) {
+      return v<0 ? Chromath.darken(col,v*-1).toString() : Chromath.lighten(col,v).toString();
+    });
+  };
+
+  // Find the smallest missing number in an array
+  kbn.smallestMissing = function(arr,start,end) {
+    start = start || 0;
+    end = end || arr.length-1;
+
+    if(start > end) {
+      return end + 1;
+    }
+    if(start !== arr[start]) {
+      return start;
+    }
+    var middle = Math.floor((start + end) / 2);
+
+    if (arr[middle] > middle) {
+      return kbn.smallestMissing(arr, start, middle);
+    } else {
+      return kbn.smallestMissing(arr, middle + 1, end);
+    }
+  };
+
+  kbn.byteFormat = function (size, decimals, min_resolution) {
+    var ext, steps = 0;
+
+    if (_.isUndefined(decimals)) {
+      decimals = 2;
+    }
+
+    if (_.isUndefined(min_resolution)) {
+      min_resolution = 0;
+    }
+
+
+    while (Math.abs(size) >= 1024) {
+      steps++;
+      size /= 1024;
+      min_resolution /= 1024;
+    }
+
+    switch (steps) {
+    case 0:
+      ext = " B";
+      break;
+    case 1:
+      ext = " KB";
+      break;
+    case 2:
+      ext = " MB";
+      break;
+    case 3:
+      ext = " GB";
+      break;
+    case 4:
+      ext = " TB";
+      break;
+    case 5:
+      ext = " PB";
+      break;
+    case 6:
+      ext = " EB";
+      break;
+    case 7:
+      ext = " ZB";
+      break;
+    case 8:
+      ext = " YB";
+      break;
+    }
+
+    if (min_resolution) {
+      min_resolution *= Math.pow(10, decimals);
+      while (min_resolution % 1 !== 0) {
+        decimals++;
+        min_resolution *= 10;
+      }
+    }
+
+    if (decimals === 0) {
+      decimals = undefined;
+    }
+
+    return (size.toFixed(decimals) + ext);
+  };
+
+  kbn.shortFormat = function (size, decimals, min_resolution) {
+    var ext, steps = 0;
+
+    if (_.isUndefined(decimals)) {
+      decimals = 2;
+    }
+    if (_.isUndefined(min_resolution)) {
+      min_resolution = 0;
+    }
+
+    while (Math.abs(size) >= 1000) {
+      steps++;
+      size /= 1000;
+      min_resolution /= 1000;
+    }
+
+    switch (steps) {
+    case 0:
+      ext = "";
+      break;
+    case 1:
+      ext = " K";
+      break;
+    case 2:
+      ext = " Mil";
+      break;
+    case 3:
+      ext = " Bil";
+      break;
+    case 4:
+      ext = " Tri";
+      break;
+    case 5:
+      ext = " Quadr";
+      break;
+    case 6:
+      ext = " Quint";
+      break;
+    case 7:
+      ext = " Sext";
+      break;
+    case 8:
+      ext = " Sept";
+      break;
+    }
+
+    if (min_resolution) {
+      min_resolution *= Math.pow(10, decimals);
+      while (min_resolution % 1 !== 0) {
+        decimals++;
+        min_resolution *= 10;
+      }
+    }
+
+    if (decimals === 0) {
+      decimals = undefined;
+    }
+
+    return (size.toFixed(decimals) + ext);
+  };
+
+  return kbn;
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/components/lodash.extended.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/components/lodash.extended.js b/opensoc-ui/lib/public/app/components/lodash.extended.js
new file mode 100755
index 0000000..fe9c3db
--- /dev/null
+++ b/opensoc-ui/lib/public/app/components/lodash.extended.js
@@ -0,0 +1,34 @@
+define([
+  'lodash-src'
+],
+function (_) {
+  'use strict';
+
+  /*
+    Mixins :)
+  */
+  _.mixin({
+    move: function (array, fromIndex, toIndex) {
+      array.splice(toIndex, 0, array.splice(fromIndex, 1)[0] );
+      return array;
+    },
+    remove: function (array, index) {
+      array.splice(index, 1);
+      return array;
+    },
+    // If variable is value, then return alt. If variable is anything else, return value;
+    toggle: function (variable, value, alt) {
+      return variable === value ? alt : value;
+    },
+    toggleInOut: function(array,value) {
+      if(_.contains(array,value)) {
+        array = _.without(array,value);
+      } else {
+        array.push(value);
+      }
+      return array;
+    }
+  });
+
+  return _;
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/components/require.config.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/components/require.config.js b/opensoc-ui/lib/public/app/components/require.config.js
new file mode 100755
index 0000000..5ea06e0
--- /dev/null
+++ b/opensoc-ui/lib/public/app/components/require.config.js
@@ -0,0 +1,98 @@
+/**
+ * Bootstrap require with the needed config, then load the app.js module.
+ */
+require.config({
+  baseUrl: 'app',
+  // urlArgs: 'r=@REV@',
+  paths: {
+    config:                   '../config',
+    settings:                 'components/settings',
+    kbn:                      'components/kbn',
+
+    vendor:                   '../vendor',
+    css:                      '../vendor/require/css',
+    text:                     '../vendor/require/text',
+    moment:                   '../vendor/moment',
+    blob:                     '../vendor/blob',
+    filesaver:                '../vendor/filesaver',
+    chromath:                 '../vendor/chromath',
+    angular:                  '../vendor/angular/angular',
+    'angular-cookies':        '../vendor/angular/angular-cookies',
+    'angular-dragdrop':       '../vendor/angular/angular-dragdrop',
+    'angular-strap':          '../vendor/angular/angular-strap',
+    'angular-sanitize':       '../vendor/angular/angular-sanitize',
+    timepicker:               '../vendor/angular/timepicker',
+    datepicker:               '../vendor/angular/datepicker',
+    bindonce:                 '../vendor/angular/bindonce',
+
+    lodash:                   'components/lodash.extended',
+    'lodash-src':             '../vendor/lodash',
+    bootstrap:                '../vendor/bootstrap/bootstrap',
+
+    jquery:                   '../vendor/jquery/jquery-1.8.0',
+    'jquery-ui':              '../vendor/jquery/jquery-ui-1.10.3',
+
+    'extend-jquery':          'components/extend-jquery',
+
+    'jquery.flot':            '../vendor/jquery/jquery.flot',
+    'jquery.flot.pie':        '../vendor/jquery/jquery.flot.pie',
+    'jquery.flot.events':     '../vendor/jquery/jquery.flot.events',
+    'jquery.flot.selection':  '../vendor/jquery/jquery.flot.selection',
+    'jquery.flot.stack':      '../vendor/jquery/jquery.flot.stack',
+    'jquery.flot.stackpercent':'../vendor/jquery/jquery.flot.stackpercent',
+    'jquery.flot.time':       '../vendor/jquery/jquery.flot.time',
+    'jquery.flot.byte':       '../vendor/jquery/jquery.flot.byte',
+
+
+    modernizr:                '../vendor/modernizr-2.6.1',
+    numeral:                '../vendor/numeral',
+    elasticjs:                '../vendor/elasticjs/elastic-angular-client',
+  },
+  shim: {
+    angular: {
+      deps: ['jquery','config'],
+      exports: 'angular'
+    },
+
+    bootstrap: {
+      deps: ['jquery']
+    },
+
+    modernizr: {
+      exports: 'Modernizr'
+    },
+
+    jquery: {
+      exports: 'jQuery'
+    },
+
+    // simple dependency declaration
+    //
+    'jquery-ui':            ['jquery'],
+    'jquery.flot':          ['jquery'],
+    'jquery.flot.byte':     ['jquery', 'jquery.flot'],
+    'jquery.flot.pie':      ['jquery', 'jquery.flot'],
+    'jquery.flot.events':   ['jquery', 'jquery.flot'],
+    'jquery.flot.selection':['jquery', 'jquery.flot'],
+    'jquery.flot.stack':    ['jquery', 'jquery.flot'],
+    'jquery.flot.stackpercent':['jquery', 'jquery.flot'],
+    'jquery.flot.time':     ['jquery', 'jquery.flot'],
+
+    'angular-sanitize':     ['angular'],
+    'angular-cookies':      ['angular'],
+    'angular-dragdrop':     ['jquery','jquery-ui','angular'],
+    'angular-loader':       ['angular'],
+    'angular-mocks':        ['angular'],
+    'angular-resource':     ['angular'],
+    'angular-route':        ['angular'],
+    'angular-touch':        ['angular'],
+    'bindonce':             ['angular'],
+    'angular-strap':        ['angular', 'bootstrap','timepicker', 'datepicker'],
+
+    timepicker:             ['jquery', 'bootstrap'],
+    datepicker:             ['jquery', 'bootstrap'],
+
+    elasticjs:              ['angular', '../vendor/elasticjs/elastic']
+  },
+  waitSeconds: 60,
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/components/settings.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/components/settings.js b/opensoc-ui/lib/public/app/components/settings.js
new file mode 100755
index 0000000..6416286
--- /dev/null
+++ b/opensoc-ui/lib/public/app/components/settings.js
@@ -0,0 +1,28 @@
+define(['lodash'],
+function (_) {
+  "use strict";
+
+  return function Settings (options) {
+    /**
+     * To add a setting, you MUST define a default. Also,
+     * THESE ARE ONLY DEFAULTS.
+     * They are overridden by config.js in the root directory
+     * @type {Object}
+     */
+    var defaults = {
+      elasticsearch     : "http://"+window.location.hostname+":9200",
+      panel_names       : [],
+      kibana_index      : 'kibana-int',
+      default_route     : '/dashboard/file/default.json'
+    };
+
+    // This initializes a new hash on purpose, to avoid adding parameters to
+    // config.js without providing sane defaults
+    var settings = {};
+    _.each(defaults, function(value, key) {
+      settings[key] = typeof options[key] !== 'undefined' ? options[key]  : defaults[key];
+    });
+
+    return settings;
+  };
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/controllers/all.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/controllers/all.js b/opensoc-ui/lib/public/app/controllers/all.js
new file mode 100755
index 0000000..05813c0
--- /dev/null
+++ b/opensoc-ui/lib/public/app/controllers/all.js
@@ -0,0 +1,6 @@
+define([
+  './dash',
+  './dashLoader',
+  './row',
+  './pulldown'
+], function () {});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/controllers/dash.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/controllers/dash.js b/opensoc-ui/lib/public/app/controllers/dash.js
new file mode 100755
index 0000000..c207d2b
--- /dev/null
+++ b/opensoc-ui/lib/public/app/controllers/dash.js
@@ -0,0 +1,111 @@
+define([
+  'angular',
+  'config',
+  'lodash',
+  'services/all'
+],
+function (angular, config, _) {
+  "use strict";
+
+  var module = angular.module('kibana.controllers');
+
+  module.controller('DashCtrl', function(
+    $scope, $route, ejsResource, fields, dashboard, alertSrv, panelMove, esVersion, kbnVersion) {
+
+    $scope.Math = Math;
+
+    $scope.editor = {
+      index: 0
+    };
+
+    // For moving stuff around the dashboard.
+    $scope.panelMoveDrop = panelMove.onDrop;
+    $scope.panelMoveStart = panelMove.onStart;
+    $scope.panelMoveStop = panelMove.onStop;
+    $scope.panelMoveOver = panelMove.onOver;
+    $scope.panelMoveOut = panelMove.onOut;
+
+
+    $scope.init = function() {
+      $scope.config = config;
+      $scope.kbnVersion = kbnVersion;
+      // Make stuff, including lodash available to views
+      $scope._ = _;
+      $scope.dashboard = dashboard;
+      $scope.dashAlerts = alertSrv;
+      $scope.esVersion = esVersion;
+
+      // Clear existing alerts
+      alertSrv.clearAll();
+
+      // Provide a global list of all seen fields
+      $scope.fields = fields;
+      $scope.reset_row();
+
+      $scope.ejs = ejsResource(config.elasticsearch);
+    };
+
+    $scope.isPanel = function(obj) {
+      if(!_.isNull(obj) && !_.isUndefined(obj) && !_.isUndefined(obj.type)) {
+        return true;
+      } else {
+        return false;
+      }
+    };
+
+    $scope.add_row = function(dash,row) {
+      dash.rows.push(row);
+    };
+
+    $scope.reset_row = function() {
+      $scope.row = {
+        title: '',
+        height: '150px',
+        editable: true,
+      };
+    };
+
+    $scope.row_style = function(row) {
+      return { 'min-height': row.collapse ? '5px' : row.height };
+    };
+
+    $scope.panel_path =function(type) {
+      if(type) {
+        return 'app/panels/'+type.replace(".","/");
+      } else {
+        return false;
+      }
+    };
+
+    $scope.edit_path = function(type) {
+      var p = $scope.panel_path(type);
+      if(p) {
+        return p+'/editor.html';
+      } else {
+        return false;
+      }
+    };
+
+    $scope.pulldownTabStyle = function(i) {
+      var classes = ['bgPrimary','bgSuccess','bgWarning','bgDanger','bgInverse','bgInfo'];
+      i = i%classes.length;
+      return classes[i];
+    };
+
+    $scope.setEditorTabs = function(panelMeta) {
+      $scope.editorTabs = ['General','Panel'];
+      if(!_.isUndefined(panelMeta.editorTabs)) {
+        $scope.editorTabs =  _.union($scope.editorTabs,_.pluck(panelMeta.editorTabs,'title'));
+      }
+      return $scope.editorTabs;
+    };
+
+    // This is whoafully incomplete, but will do for now
+    $scope.parse_error = function(data) {
+      var _error = data.match("nested: (.*?);");
+      return _.isNull(_error) ? data : _error[1];
+    };
+
+    $scope.init();
+  });
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/controllers/dashLoader.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/controllers/dashLoader.js b/opensoc-ui/lib/public/app/controllers/dashLoader.js
new file mode 100755
index 0000000..045cdd0
--- /dev/null
+++ b/opensoc-ui/lib/public/app/controllers/dashLoader.js
@@ -0,0 +1,128 @@
+define([
+  'angular',
+  'lodash'
+],
+function (angular, _) {
+  'use strict';
+
+  var module = angular.module('kibana.controllers');
+
+  module.controller('dashLoader', function($scope, $http, timer, dashboard, alertSrv, $location) {
+    $scope.loader = dashboard.current.loader;
+
+    $scope.init = function() {
+      $scope.gist_pattern = /(^\d{5,}$)|(^[a-z0-9]{10,}$)|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/;
+      $scope.gist = $scope.gist || {};
+      $scope.elasticsearch = $scope.elasticsearch || {};
+    };
+
+    $scope.showDropdown = function(type) {
+      if(_.isUndefined(dashboard.current.loader)) {
+        return true;
+      }
+
+      var _l = dashboard.current.loader;
+      if(type === 'load') {
+        return (_l.load_elasticsearch || _l.load_gist || _l.load_local);
+      }
+      if(type === 'save') {
+        return (_l.save_elasticsearch || _l.save_gist || _l.save_local || _l.save_default);
+      }
+      if(type === 'share') {
+        return (_l.save_temp);
+      }
+      return false;
+    };
+
+    $scope.set_default = function() {
+      if(dashboard.set_default($location.path())) {
+        alertSrv.set('Home Set','This page has been set as your default Kibana dashboard','success',5000);
+      } else {
+        alertSrv.set('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
+      }
+    };
+
+    $scope.purge_default = function() {
+      if(dashboard.purge_default()) {
+        alertSrv.set('Local Default Clear','Your Kibana default dashboard has been reset to the default',
+          'success',5000);
+      } else {
+        alertSrv.set('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
+      }
+    };
+
+    $scope.elasticsearch_save = function(type,ttl) {
+      dashboard.elasticsearch_save(
+        type,
+        ($scope.elasticsearch.title || dashboard.current.title),
+        ($scope.loader.save_temp_ttl_enable ? ttl : false)
+      ).then(
+        function(result) {
+        if(!_.isUndefined(result._id)) {
+          alertSrv.set('Dashboard Saved','This dashboard has been saved to Elasticsearch as "' +
+            result._id + '"','success',5000);
+          if(type === 'temp') {
+            $scope.share = dashboard.share_link(dashboard.current.title,'temp',result._id);
+          }
+        } else {
+          alertSrv.set('Save failed','Dashboard could not be saved to Elasticsearch','error',5000);
+        }
+      });
+    };
+
+    $scope.elasticsearch_delete = function(id) {
+      dashboard.elasticsearch_delete(id).then(
+        function(result) {
+          if(!_.isUndefined(result)) {
+            if(result.found) {
+              alertSrv.set('Dashboard Deleted',id+' has been deleted','success',5000);
+              // Find the deleted dashboard in the cached list and remove it
+              var toDelete = _.where($scope.elasticsearch.dashboards,{_id:id})[0];
+              $scope.elasticsearch.dashboards = _.without($scope.elasticsearch.dashboards,toDelete);
+            } else {
+              alertSrv.set('Dashboard Not Found','Could not find '+id+' in Elasticsearch','warning',5000);
+            }
+          } else {
+            alertSrv.set('Dashboard Not Deleted','An error occurred deleting the dashboard','error',5000);
+          }
+        }
+      );
+    };
+
+    $scope.elasticsearch_dblist = function(query) {
+      dashboard.elasticsearch_list(query,$scope.loader.load_elasticsearch_size).then(
+        function(result) {
+        if(!_.isUndefined(result.hits)) {
+          $scope.hits = result.hits.total;
+          $scope.elasticsearch.dashboards = result.hits.hits;
+        }
+      });
+    };
+
+    $scope.save_gist = function() {
+      dashboard.save_gist($scope.gist.title).then(
+        function(link) {
+        if(!_.isUndefined(link)) {
+          $scope.gist.last = link;
+          alertSrv.set('Gist saved','You will be able to access your exported dashboard file at '+
+            '<a href="'+link+'">'+link+'</a> in a moment','success');
+        } else {
+          alertSrv.set('Save failed','Gist could not be saved','error',5000);
+        }
+      });
+    };
+
+    $scope.gist_dblist = function(id) {
+      dashboard.gist_list(id).then(
+        function(files) {
+        if(files && files.length > 0) {
+          $scope.gist.files = files;
+        } else {
+          alertSrv.set('Gist Failed','Could not retrieve dashboard list from gist','error',5000);
+        }
+      });
+    };
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/controllers/pulldown.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/controllers/pulldown.js b/opensoc-ui/lib/public/app/controllers/pulldown.js
new file mode 100755
index 0000000..9534298
--- /dev/null
+++ b/opensoc-ui/lib/public/app/controllers/pulldown.js
@@ -0,0 +1,45 @@
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  var module = angular.module('kibana.controllers');
+
+  module.controller('PulldownCtrl', function($scope, $rootScope, $timeout,ejsResource, querySrv) {
+      var _d = {
+        collapse: false,
+        notice: false,
+        enable: true
+      };
+
+      _.defaults($scope.pulldown,_d);
+
+      $scope.init = function() {
+        $scope.querySrv = querySrv;
+
+        // Provide a combined skeleton for panels that must interact with panel and row.
+        // This might create name spacing issues.
+        $scope.panel = $scope.pulldown;
+        $scope.row = $scope.pulldown;
+      };
+
+      $scope.toggle_pulldown = function(pulldown) {
+        pulldown.collapse = pulldown.collapse ? false : true;
+        if (!pulldown.collapse) {
+          $timeout(function() {
+            $scope.$broadcast('render');
+          });
+        } else {
+          $scope.row.notice = false;
+        }
+      };
+
+      $scope.init();
+
+    }
+  );
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/controllers/row.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/controllers/row.js b/opensoc-ui/lib/public/app/controllers/row.js
new file mode 100755
index 0000000..07f7b0d
--- /dev/null
+++ b/opensoc-ui/lib/public/app/controllers/row.js
@@ -0,0 +1,112 @@
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  var module = angular.module('kibana.controllers');
+
+  module.controller('RowCtrl', function($scope, $rootScope, $timeout,ejsResource, querySrv) {
+      var _d = {
+        title: "Row",
+        height: "150px",
+        collapse: false,
+        collapsable: true,
+        editable: true,
+        panels: [],
+        notice: false
+      };
+
+      _.defaults($scope.row,_d);
+
+      $scope.init = function() {
+        $scope.querySrv = querySrv;
+        $scope.reset_panel();
+      };
+
+      $scope.toggle_row = function(row) {
+        if(!row.collapsable) {
+          return;
+        }
+        row.collapse = row.collapse ? false : true;
+        if (!row.collapse) {
+          $timeout(function() {
+            $scope.$broadcast('render');
+          });
+        } else {
+          row.notice = false;
+        }
+      };
+
+      $scope.rowSpan = function(row) {
+        var panels = _.filter(row.panels, function(p) {
+          return $scope.isPanel(p);
+        });
+        return _.reduce(_.pluck(panels,'span'), function(p,v) {
+          return p+v;
+        },0);
+      };
+
+      // This can be overridden by individual panels
+      $scope.close_edit = function() {
+        $scope.$broadcast('render');
+      };
+
+      $scope.add_panel = function(row,panel) {
+        $scope.row.panels.push(panel);
+      };
+
+      /** @scratch /panels/0
+       * [[panels]]
+       * = Panels
+       *
+       * [partintro]
+       * --
+       * *Kibana* dashboards are made up of blocks called +panels+. Panels are organized into rows
+       * and can serve many purposes, though most are designed to provide the results of a query or
+       * multiple queries as a visualization. Other panels may show collections of documents or
+       * allow you to insert instructions for your users.
+       *
+       * Panels can be configured easily via the Kibana web interface. For more advanced usage, such
+       * as templated or scripted dashboards, documentation of panel properties is available in this
+       * section. You may find settings here which are not exposed via the web interface.
+       *
+       * Each panel type has its own properties, hover there are several that are shared.
+       *
+      */
+
+      $scope.reset_panel = function(type) {
+        var
+          defaultSpan = 4,
+          _as = 12-$scope.rowSpan($scope.row);
+
+        $scope.panel = {
+          error   : false,
+          /** @scratch /panels/1
+           * span:: A number, 1-12, that describes the width of the panel.
+           */
+          span    : _as < defaultSpan && _as > 0 ? _as : defaultSpan,
+          /** @scratch /panels/1
+           * editable:: Enable or disable the edit button the the panel
+           */
+          editable: true,
+          /** @scratch /panels/1
+           * type:: The type of panel this object contains. Each panel type will require additional
+           * properties. See the panel types list to the right.
+           */
+          type    : type
+        };
+      };
+
+      /** @scratch /panels/2
+       * --
+       */
+
+      $scope.init();
+
+    }
+  );
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/alerts-dashboard.json
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/alerts-dashboard.json b/opensoc-ui/lib/public/app/dashboards/alerts-dashboard.json
new file mode 100644
index 0000000..5545e00
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/alerts-dashboard.json
@@ -0,0 +1,332 @@
+{
+  "title": " GoodBig Co.",
+  "services": {
+    "query": {
+      "list": {
+        "3": {
+          "id": 3,
+          "color": "#E5AC0E",
+          "alias": "Warning",
+          "pin": false,
+          "type": "lucene",
+          "enable": true,
+          "query": ""
+        }
+      },
+      "ids": [
+        3
+      ]
+    },
+    "filter": {
+      "list": {
+        "1": {
+          "type": "time",
+          "field": "message.timestamp",
+          "from": "now-12h",
+          "to": "now",
+          "mandate": "must",
+          "active": true,
+          "alias": "",
+          "id": 1
+        }
+      },
+      "ids": [
+        1
+      ]
+    }
+  },
+  "rows": [
+    {
+      "title": "Fixed Overview",
+      "height": "250px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 4,
+          "editable": true,
+          "type": "terms",
+          "loadingEditor": false,
+          "field": "_type",
+          "exclude": [
+            "pcap"
+          ],
+          "missing": false,
+          "other": false,
+          "size": 10,
+          "order": "count",
+          "style": {
+            "font-size": "10pt"
+          },
+          "donut": false,
+          "tilt": false,
+          "labels": true,
+          "arrangement": "horizontal",
+          "chart": "pie",
+          "counter_pos": "above",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              3
+            ]
+          },
+          "locked": false,
+          "tmode": "terms",
+          "tstat": "total",
+          "valuefield": "",
+          "title": "Alert Source"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "",
+      "height": "150px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 4,
+          "editable": true,
+          "type": "terms",
+          "loadingEditor": false,
+          "field": "message.protocol",
+          "exclude": [],
+          "missing": false,
+          "other": false,
+          "size": 10,
+          "order": "count",
+          "style": {
+            "font-size": "10pt"
+          },
+          "donut": false,
+          "tilt": false,
+          "labels": true,
+          "arrangement": "horizontal",
+          "chart": "table",
+          "counter_pos": "above",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              3
+            ]
+          },
+          "locked": false,
+          "tmode": "terms",
+          "tstat": "total",
+          "valuefield": "",
+          "title": "Protocol"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "",
+      "height": "150px",
+      "editable": true,
+      "collapse": true,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 12,
+          "editable": true,
+          "type": "table",
+          "loadingEditor": false,
+          "size": 100,
+          "pages": 5,
+          "offset": 0,
+          "sort": [
+            "alerts.triggered.priority",
+            "desc"
+          ],
+          "overflow": "min-height",
+          "fields": [
+            "_type",
+            "_index",
+            "alerts.triggered.priority"
+          ],
+          "highlight": [],
+          "sortable": true,
+          "header": true,
+          "paging": true,
+          "field_list": true,
+          "all_fields": false,
+          "trimFactor": 300,
+          "localTime": false,
+          "timeField": "@timestamp",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0,
+              1,
+              2,
+              3
+            ]
+          },
+          "locked": false,
+          "style": {
+            "font-size": "9pt"
+          },
+          "normTimes": true,
+          "title": "all"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "",
+      "height": "150px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 12,
+          "editable": true,
+          "type": "table",
+          "loadingEditor": false,
+          "size": 10,
+          "pages": 5000,
+          "offset": 0,
+          "sort": [
+            "_score",
+            "desc"
+          ],
+          "overflow": "min-height",
+          "fields": [
+            "alerts.triggered.type",
+            "alerts.triggered.priority",
+            "alerts.triggered.title",
+            "alerts.triggered.body",
+            "_type",
+            "message.ip_dst_port",
+            "message.ip_dst_addr",
+            "message.timestamp",
+            "message.protocol",
+            "message.ip_src_addr"
+          ],
+          "highlight": [],
+          "sortable": true,
+          "header": true,
+          "paging": true,
+          "field_list": true,
+          "all_fields": false,
+          "trimFactor": 300,
+          "localTime": false,
+          "timeField": "@timestamp",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              3
+            ]
+          },
+          "locked": true,
+          "style": {
+            "font-size": "9pt"
+          },
+          "normTimes": true,
+          "title": "Alerts Table"
+        }
+      ],
+      "notice": false
+    }
+  ],
+  "editable": true,
+  "failover": false,
+  "index": {
+    "interval": "none",
+    "pattern": "[logstash-]YYYY.MM.DD",
+    "default": "_all",
+    "warm_fields": false
+  },
+  "style": "dark",
+  "realtime": true,
+  "panel_hints": true,
+  "pulldowns": [
+    {
+      "type": "query",
+      "collapse": false,
+      "notice": false,
+      "enable": true,
+      "query": "*",
+      "pinned": true,
+      "history": [
+        "",
+        "alerts.triggered.type:warning",
+        "alerts.triggered.type:error",
+        "alerts.triggered.type:alert",
+        "alerts.triggered.priority:3",
+        "alerts.triggered.priority:2",
+        "alerts.triggered.priority:1",
+        "*"
+      ],
+      "remember": 10
+    },
+    {
+      "type": "filtering",
+      "collapse": false,
+      "notice": true,
+      "enable": true
+    }
+  ],
+  "nav": [
+    {
+      "type": "timepicker",
+      "collapse": false,
+      "notice": false,
+      "enable": true,
+      "status": "Stable",
+      "time_options": [
+        "5m",
+        "15m",
+        "1h",
+        "6h",
+        "12h",
+        "24h",
+        "2d",
+        "7d",
+        "30d"
+      ],
+      "refresh_intervals": [
+        "5s",
+        "10s",
+        "30s",
+        "1m",
+        "5m",
+        "15m",
+        "30m",
+        "1h",
+        "2h",
+        "1d"
+      ],
+      "timefield": "message.timestamp",
+      "now": true,
+      "filter_id": 1
+    }
+  ],
+  "loader": {
+    "save_gist": false,
+    "save_elasticsearch": true,
+    "save_local": true,
+    "save_default": true,
+    "save_temp": true,
+    "save_temp_ttl_enable": true,
+    "save_temp_ttl": "30d",
+    "load_gist": false,
+    "load_elasticsearch": true,
+    "load_elasticsearch_size": 20,
+    "load_local": false,
+    "hide": false
+  },
+  "refresh": false
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/blank.json
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/blank.json b/opensoc-ui/lib/public/app/dashboards/blank.json
new file mode 100755
index 0000000..614712e
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/blank.json
@@ -0,0 +1,32 @@
+{
+  "title": "New Dashboard",
+  "services": {
+    "query": {
+      "list": {
+        "0": {
+          "query": "*",
+          "alias": "",
+          "color": "#7EB26D",
+          "id": 0
+        }
+      },
+      "ids": [
+        0
+      ]
+    },
+    "filter": {
+      "list": {},
+      "ids": []
+    }
+  },
+  "rows": [
+  ],
+  "editable": true,
+  "failover": false,
+  "index": {
+    "interval": "none",
+    "pattern": "[logstash-]YYYY.MM.DD",
+    "default": "_all",
+    "warm_fields": false
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/default.json
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/default.json b/opensoc-ui/lib/public/app/dashboards/default.json
new file mode 100644
index 0000000..9cd224e
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/default.json
@@ -0,0 +1,535 @@
+{
+  "title": "New Dashboard",
+  "services": {
+    "query": {
+      "list": {
+        "0": {
+          "query": "alerts.triggered.priority:1",
+          "alias": "",
+          "color": "#BF1B00",
+          "id": 0,
+          "pin": true,
+          "type": "lucene",
+          "enable": true
+        },
+        "1": {
+          "id": 1,
+          "color": "#EAB839",
+          "alias": "",
+          "pin": true,
+          "type": "lucene",
+          "enable": true,
+          "query": "alerts.triggered.priority:2"
+        },
+        "2": {
+          "id": 2,
+          "color": "#6ED0E0",
+          "alias": "",
+          "pin": true,
+          "type": "lucene",
+          "enable": true,
+          "query": "alerts.triggered.priority:3"
+        },
+        "3": {
+          "id": 3,
+          "color": "#E5AC0E",
+          "alias": "Warning",
+          "pin": false,
+          "type": "lucene",
+          "enable": true,
+          "query": ""
+        },
+        "4": {
+          "id": 4,
+          "color": "#E24D42",
+          "alias": "1. Alert",
+          "pin": true,
+          "type": "lucene",
+          "enable": true,
+          "query": "alerts.triggered.type:alert"
+        },
+        "5": {
+          "id": 5,
+          "color": "#F2C96D",
+          "alias": "3. Error",
+          "pin": true,
+          "type": "lucene",
+          "enable": true,
+          "query": "alerts.triggered.type:error"
+        },
+        "6": {
+          "id": 6,
+          "color": "#F9934E",
+          "alias": "2. Warning",
+          "pin": true,
+          "type": "lucene",
+          "enable": true,
+          "query": "alerts.triggered.type:warning"
+        }
+      },
+      "ids": [
+        0,
+        1,
+        2,
+        3,
+        4,
+        6,
+        5
+      ]
+    },
+    "filter": {
+      "list": {
+        "0": {
+          "type": "field",
+          "field": "_type",
+          "query": "\"pcap\"",
+          "mandate": "mustNot",
+          "active": true,
+          "alias": "",
+          "id": 0
+        },
+        "1": {
+          "type": "time",
+          "field": "message.timestamp",
+          "from": "now-12h",
+          "to": "now",
+          "mandate": "must",
+          "active": true,
+          "alias": "",
+          "id": 1
+        }
+      },
+      "ids": [
+        0,
+        1
+      ]
+    }
+  },
+  "rows": [
+    {
+      "title": "Fixed Overview",
+      "height": "250px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 3,
+          "editable": true,
+          "type": "terms",
+          "loadingEditor": false,
+          "field": "alerts.triggered.type",
+          "exclude": [],
+          "missing": false,
+          "other": false,
+          "size": 10,
+          "order": "count",
+          "style": {
+            "font-size": "10pt"
+          },
+          "donut": false,
+          "tilt": false,
+          "labels": true,
+          "arrangement": "horizontal",
+          "chart": "bar",
+          "counter_pos": "above",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0,
+              1,
+              2,
+              3,
+              4,
+              5,
+              6
+            ]
+          },
+          "locked": false,
+          "tmode": "terms",
+          "tstat": "total",
+          "valuefield": "",
+          "title": "Alert Type"
+        },
+        {
+          "error": false,
+          "span": 4,
+          "editable": true,
+          "type": "terms",
+          "loadingEditor": false,
+          "field": "_type",
+          "exclude": [
+            "pcap"
+          ],
+          "missing": false,
+          "other": false,
+          "size": 10,
+          "order": "count",
+          "style": {
+            "font-size": "10pt"
+          },
+          "donut": false,
+          "tilt": false,
+          "labels": true,
+          "arrangement": "horizontal",
+          "chart": "pie",
+          "counter_pos": "above",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0,
+              1,
+              2,
+              3,
+              4,
+              5,
+              6
+            ]
+          },
+          "locked": false,
+          "tmode": "terms",
+          "tstat": "total",
+          "valuefield": "",
+          "title": "Alert Source"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "",
+      "height": "150px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "span": 8,
+          "editable": true,
+          "type": "histogram",
+          "loadingEditor": false,
+          "mode": "count",
+          "time_field": "message.timestamp",
+          "value_field": null,
+          "x-axis": true,
+          "y-axis": true,
+          "scale": 1,
+          "y_format": "none",
+          "grid": {
+            "max": null,
+            "min": 0
+          },
+          "queries": {
+            "mode": "selected",
+            "ids": [
+              4,
+              5,
+              6
+            ]
+          },
+          "locked": false,
+          "annotate": {
+            "enable": false,
+            "query": "*",
+            "size": 20,
+            "field": "_type",
+            "sort": [
+              "_score",
+              "desc"
+            ]
+          },
+          "auto_int": true,
+          "resolution": 100,
+          "interval": "5m",
+          "intervals": [
+            "auto",
+            "1s",
+            "1m",
+            "5m",
+            "10m",
+            "30m",
+            "1h",
+            "3h",
+            "12h",
+            "1d",
+            "1w",
+            "1y"
+          ],
+          "lines": false,
+          "fill": 0,
+          "linewidth": 3,
+          "points": false,
+          "pointradius": 5,
+          "bars": true,
+          "stack": true,
+          "spyable": true,
+          "zoomlinks": true,
+          "options": true,
+          "legend": true,
+          "show_query": true,
+          "interactive": true,
+          "legend_counts": true,
+          "timezone": "browser",
+          "percentage": false,
+          "zerofill": true,
+          "derivative": false,
+          "tooltip": {
+            "value_type": "cumulative",
+            "query_as_alias": true
+          },
+          "title": "Alert History Timeline"
+        },
+        {
+          "error": false,
+          "span": 4,
+          "editable": true,
+          "type": "terms",
+          "loadingEditor": false,
+          "field": "message.protocol",
+          "exclude": [],
+          "missing": false,
+          "other": false,
+          "size": 10,
+          "order": "count",
+          "style": {
+            "font-size": "10pt"
+          },
+          "donut": false,
+          "tilt": false,
+          "labels": true,
+          "arrangement": "horizontal",
+          "chart": "table",
+          "counter_pos": "above",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0,
+              1,
+              2,
+              3,
+              4,
+              5,
+              6
+            ]
+          },
+          "locked": false,
+          "tmode": "terms",
+          "tstat": "total",
+          "valuefield": "",
+          "title": "Protocol"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "",
+      "height": "150px",
+      "editable": true,
+      "collapse": true,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 12,
+          "editable": true,
+          "type": "table",
+          "loadingEditor": false,
+          "size": 100,
+          "pages": 5,
+          "offset": 0,
+          "sort": [
+            "alerts.triggered.priority",
+            "desc"
+          ],
+          "overflow": "min-height",
+          "fields": [
+            "_type",
+            "_index",
+            "alerts.triggered.priority"
+          ],
+          "highlight": [],
+          "sortable": true,
+          "header": true,
+          "paging": true,
+          "field_list": true,
+          "all_fields": false,
+          "trimFactor": 300,
+          "localTime": false,
+          "timeField": "@timestamp",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0,
+              1,
+              2,
+              3
+            ]
+          },
+          "locked": false,
+          "style": {
+            "font-size": "9pt"
+          },
+          "normTimes": true,
+          "title": "all"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "",
+      "height": "150px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 12,
+          "editable": true,
+          "type": "table",
+          "loadingEditor": false,
+          "size": 10,
+          "pages": 5000,
+          "offset": 0,
+          "sort": [
+            "_score",
+            "desc"
+          ],
+          "overflow": "min-height",
+          "fields": [
+            "alerts.triggered.type",
+            "alerts.triggered.priority",
+            "alerts.triggered.title",
+            "alerts.triggered.body",
+            "_type",
+            "message.ip_dst_port",
+            "message.ip_dst_addr",
+            "message.timestamp",
+            "message.protocol",
+            "message.ip_src_addr"
+          ],
+          "highlight": [],
+          "sortable": true,
+          "header": true,
+          "paging": true,
+          "field_list": true,
+          "all_fields": false,
+          "trimFactor": 300,
+          "localTime": false,
+          "timeField": "@timestamp",
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0,
+              1,
+              2,
+              3,
+              4,
+              5,
+              6
+            ]
+          },
+          "locked": true,
+          "style": {
+            "font-size": "9pt"
+          },
+          "normTimes": true,
+          "title": "Top Alerts"
+        }
+      ],
+      "notice": false
+    }
+  ],
+  "editable": true,
+  "failover": false,
+  "index": {
+    "interval": "none",
+    "pattern": "[logstash-]YYYY.MM.DD",
+    "default": "_all",
+    "warm_fields": false
+  },
+  "style": "dark",
+  "realtime": true,
+  "panel_hints": true,
+  "pulldowns": [
+    {
+      "type": "query",
+      "collapse": false,
+      "notice": false,
+      "enable": true,
+      "query": "*",
+      "pinned": true,
+      "history": [
+        "alerts.triggered.type:warning",
+        "alerts.triggered.type:alert",
+        "",
+        "alerts.triggered.priority:3",
+        "alerts.triggered.priority:2",
+        "alerts.triggered.priority:1",
+        "*"
+      ],
+      "remember": 10
+    },
+    {
+      "type": "filtering",
+      "collapse": false,
+      "notice": true,
+      "enable": true
+    }
+  ],
+  "nav": [
+    {
+      "type": "timepicker",
+      "collapse": false,
+      "notice": false,
+      "enable": true,
+      "status": "Stable",
+      "time_options": [
+        "5m",
+        "15m",
+        "1h",
+        "6h",
+        "12h",
+        "24h",
+        "2d",
+        "7d",
+        "30d"
+      ],
+      "refresh_intervals": [
+        "5s",
+        "10s",
+        "30s",
+        "1m",
+        "5m",
+        "15m",
+        "30m",
+        "1h",
+        "2h",
+        "1d"
+      ],
+      "timefield": "message.timestamp",
+      "now": true,
+      "filter_id": 1
+    }
+  ],
+  "loader": {
+    "save_gist": false,
+    "save_elasticsearch": true,
+    "save_local": true,
+    "save_default": true,
+    "save_temp": true,
+    "save_temp_ttl_enable": true,
+    "save_temp_ttl": "30d",
+    "load_gist": false,
+    "load_elasticsearch": true,
+    "load_elasticsearch_size": 20,
+    "load_local": false,
+    "hide": false
+  },
+  "refresh": false
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/logstash.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/logstash.js b/opensoc-ui/lib/public/app/dashboards/logstash.js
new file mode 100755
index 0000000..f9c805d
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/logstash.js
@@ -0,0 +1,138 @@
+/* global _ */
+
+/*
+ * Complex scripted Logstash dashboard
+ * This script generates a dashboard object that Kibana can load. It also takes a number of user
+ * supplied URL parameters, none are required:
+ *
+ * index :: Which index to search? If this is specified, interval is set to 'none'
+ * pattern :: Does nothing if index is specified. Set a timestamped index pattern. Default: [logstash-]YYYY.MM.DD
+ * interval :: Sets the index interval (eg: day,week,month,year), Default: day
+ *
+ * split :: The character to split the queries on Default: ','
+ * query :: By default, a comma separated list of queries to run. Default: *
+ *
+ * from :: Search this amount of time back, eg 15m, 1h, 2d. Default: 15m
+ * timefield :: The field containing the time to filter on, Default: @timestamp
+ *
+ * fields :: comma separated list of fields to show in the table
+ * sort :: comma separated field to sort on, and direction, eg sort=@timestamp,desc
+ *
+ */
+
+'use strict';
+
+// Setup some variables
+var dashboard, queries, _d_timespan;
+
+// All url parameters are available via the ARGS object
+var ARGS;
+
+// Set a default timespan if one isn't specified
+_d_timespan = '1d';
+
+// Intialize a skeleton with nothing but a rows array and service object
+dashboard = {
+  rows : [],
+  services : {}
+};
+
+// Set a title
+dashboard.title = 'Logstash Search';
+
+// Allow the user to set the index, if they dont, fall back to logstash.
+if(!_.isUndefined(ARGS.index)) {
+  dashboard.index = {
+    default: ARGS.index,
+    interval: 'none'
+  };
+} else {
+  // Don't fail to default
+  dashboard.failover = false;
+  dashboard.index = {
+    default: ARGS.index||'ADD_A_TIME_FILTER',
+    pattern: ARGS.pattern||'[logstash-]YYYY.MM.DD',
+    interval: ARGS.interval||'day'
+  };
+}
+
+// In this dashboard we let users pass queries as comma separated list to the query parameter.
+// Or they can specify a split character using the split aparameter
+// If query is defined, split it into a list of query objects
+// NOTE: ids must be integers, hence the parseInt()s
+if(!_.isUndefined(ARGS.query)) {
+  queries = _.object(_.map(ARGS.query.split(ARGS.split||','), function(v,k) {
+    return [k,{
+      query: v,
+      id: parseInt(k,10),
+      alias: v
+    }];
+  }));
+} else {
+  // No queries passed? Initialize a single query to match everything
+  queries = {
+    0: {
+      query: '*',
+      id: 0,
+    }
+  };
+}
+
+// Now populate the query service with our objects
+dashboard.services.query = {
+  list : queries,
+  ids : _.map(_.keys(queries),function(v){return parseInt(v,10);})
+};
+
+// Lets also add a default time filter, the value of which can be specified by the user
+dashboard.services.filter = {
+  list: {
+    0: {
+      from: "now-"+(ARGS.from||_d_timespan),
+      to: "now",
+      field: ARGS.timefield||"@timestamp",
+      type: "time",
+      active: true,
+      id: 0,
+    }
+  },
+  ids: [0]
+};
+
+// Ok, lets make some rows. The Filters row is collapsed by default
+dashboard.rows = [
+  {
+    title: "Chart",
+    height: "300px"
+  },
+  {
+    title: "Events",
+    height: "400px"
+  }
+];
+
+// And a histogram that allows the user to specify the interval and time field
+dashboard.rows[0].panels = [
+  {
+    title: 'events over time',
+    type: 'histogram',
+    time_field: ARGS.timefield||"@timestamp",
+    auto_int: true,
+    span: 12
+  }
+];
+
+// And a table row where you can specify field and sort order
+dashboard.rows[1].panels = [
+  {
+    title: 'all events',
+    type: 'table',
+    fields: !_.isUndefined(ARGS.fields) ? ARGS.fields.split(',') : [],
+    sort: !_.isUndefined(ARGS.sort) ? ARGS.sort.split(',') : [ARGS.timefield||'@timestamp','desc'],
+    overflow: 'expand',
+    span: 12
+  }
+];
+
+// Now return the object and we're good!
+return dashboard;

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/logstash.json
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/logstash.json b/opensoc-ui/lib/public/app/dashboards/logstash.json
new file mode 100755
index 0000000..2cefe7a
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/logstash.json
@@ -0,0 +1,227 @@
+{
+  "title": "Logstash Search",
+  "services": {
+    "query": {
+      "list": {
+        "0": {
+          "query": "{{ARGS.query || '*'}}",
+          "alias": "",
+          "color": "#7EB26D",
+          "id": 0,
+          "pin": false,
+          "type": "lucene"
+        }
+      },
+      "ids": [
+        0
+      ]
+    },
+    "filter": {
+      "list": {
+        "0": {
+          "type": "time",
+          "field": "@timestamp",
+          "from": "now-{{ARGS.from || '24h'}}",
+          "to": "now",
+          "mandate": "must",
+          "active": true,
+          "alias": "",
+          "id": 0
+        }
+      },
+      "ids": [
+        0
+      ]
+    }
+  },
+  "rows": [
+    {
+      "title": "Graph",
+      "height": "350px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "span": 12,
+          "editable": true,
+          "group": [
+            "default"
+          ],
+          "type": "histogram",
+          "mode": "count",
+          "time_field": "@timestamp",
+          "value_field": null,
+          "auto_int": true,
+          "resolution": 100,
+          "interval": "10m",
+          "fill": 3,
+          "linewidth": 3,
+          "timezone": "browser",
+          "spyable": true,
+          "zoomlinks": true,
+          "bars": true,
+          "stack": true,
+          "points": false,
+          "lines": false,
+          "legend": true,
+          "x-axis": true,
+          "y-axis": true,
+          "percentage": false,
+          "interactive": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0
+            ]
+          },
+          "title": "Events over time",
+          "intervals": [
+            "auto",
+            "1s",
+            "1m",
+            "5m",
+            "10m",
+            "30m",
+            "1h",
+            "3h",
+            "12h",
+            "1d",
+            "1w",
+            "1M",
+            "1y"
+          ],
+          "options": true,
+          "tooltip": {
+            "value_type": "cumulative",
+            "query_as_alias": false
+          }
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "Events",
+      "height": "350px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "title": "All events",
+          "error": false,
+          "span": 12,
+          "editable": true,
+          "group": [
+            "default"
+          ],
+          "type": "table",
+          "size": 100,
+          "pages": 5,
+          "offset": 0,
+          "sort": [
+            "@timestamp",
+            "desc"
+          ],
+          "style": {
+            "font-size": "9pt"
+          },
+          "overflow": "min-height",
+          "fields": [],
+          "localTime": true,
+          "timeField": "@timestamp",
+          "highlight": [],
+          "sortable": true,
+          "header": true,
+          "paging": true,
+          "spyable": true,
+          "queries": {
+            "mode": "all",
+            "ids": [
+              0
+            ]
+          },
+          "field_list": true,
+          "status": "Stable",
+          "trimFactor": 300,
+          "normTimes": true
+        }
+      ],
+      "notice": false
+    }
+  ],
+  "editable": true,
+  "failover": false,
+  "index": {
+    "interval": "day",
+    "pattern": "[logstash-]YYYY.MM.DD",
+    "default": "NO_TIME_FILTER_OR_INDEX_PATTERN_NOT_MATCHED"
+  },
+  "style": "{{ARGS.style || 'dark'}}",
+  "panel_hints": true,
+  "pulldowns": [
+    {
+      "type": "query",
+      "collapse": false,
+      "notice": false,
+      "query": "*",
+      "pinned": true,
+      "history": [],
+      "remember": 10
+    },
+    {
+      "type": "filtering",
+      "collapse": true,
+      "notice": false
+    }
+  ],
+  "nav": [
+    {
+      "type": "timepicker",
+      "collapse": false,
+      "notice": false,
+      "status": "Stable",
+      "time_options": [
+        "5m",
+        "15m",
+        "1h",
+        "6h",
+        "12h",
+        "24h",
+        "2d",
+        "7d",
+        "30d"
+      ],
+      "refresh_intervals": [
+        "5s",
+        "10s",
+        "30s",
+        "1m",
+        "5m",
+        "15m",
+        "30m",
+        "1h",
+        "2h",
+        "1d"
+      ],
+      "timefield": "@timestamp",
+      "now": true,
+      "filter_id": 0
+    }
+  ],
+  "loader": {
+    "save_gist": false,
+    "save_elasticsearch": true,
+    "save_local": true,
+    "save_default": true,
+    "save_temp": true,
+    "save_temp_ttl_enable": true,
+    "save_temp_ttl": "30d",
+    "load_gist": true,
+    "load_elasticsearch": true,
+    "load_elasticsearch_size": 20,
+    "load_local": true,
+    "hide": false
+  },
+  "refresh": false
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/noted.json
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/noted.json b/opensoc-ui/lib/public/app/dashboards/noted.json
new file mode 100755
index 0000000..a4dd2d9
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/noted.json
@@ -0,0 +1,161 @@
+{
+  "title": "A few notes",
+  "services": {
+    "query": {
+      "list": {
+        "0": {
+          "query": "*",
+          "alias": "",
+          "color": "#7EB26D",
+          "id": 0,
+          "pin": false,
+          "type": "lucene"
+        }
+      },
+      "ids": [
+        0
+      ]
+    },
+    "filter": {
+      "list": {},
+      "ids": []
+    }
+  },
+  "rows": [
+    {
+      "title": "Graph",
+      "height": "250px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 3,
+          "editable": true,
+          "group": [
+            "default"
+          ],
+          "type": "text",
+          "status": "Stable",
+          "mode": "markdown",
+          "content": "See the small Filters bar above this? Click it to expand the filters row. Right now there are none, but if you were to add a Table panel, you could click on event fields to drill down and add some. Or if you had timestamped data and used a time picker, your time filter would appear there",
+          "style": {},
+          "title": "Filtering"
+        },
+        {
+          "error": false,
+          "span": 9,
+          "editable": true,
+          "group": [
+            "default"
+          ],
+          "type": "text",
+          "status": "Stable",
+          "mode": "markdown",
+          "content": "### Start here\nThis dashboard doesn't run any queries, but it's the best I can do without knowing much about your data!\n\n##### Kibana is currently configured to point at the special Elasticsearch *_all* index. You can change that by clicking on the cog icon in the title bar of this dashboard\nIf you have several indices and a lot of data, you should probably do that before you add any new panels. You can also add rows from that dialog. You can edit individual panels by click on the link that appears in their top right when you mouse over them",
+          "style": {},
+          "title": "Welcome!"
+        }
+      ],
+      "notice": false
+    },
+    {
+      "title": "Table",
+      "height": "650px",
+      "editable": true,
+      "collapse": false,
+      "collapsable": true,
+      "panels": [
+        {
+          "error": false,
+          "span": 12,
+          "editable": true,
+          "group": [
+            "default"
+          ],
+          "type": "text",
+          "status": "Stable",
+          "mode": "markdown",
+          "content": "## A good place for a table\nThis is a good place for a table panel. Table panels present your data in a tabular format and allow you pick the fields you want to see, sort on them, and drill down.",
+          "style": {},
+          "title": "Put a table here maybe?"
+        }
+      ],
+      "notice": false
+    }
+  ],
+  "editable": true,
+  "index": {
+    "interval": "none",
+    "pattern": "[logstash-]YYYY.MM.DD",
+    "default": "_all",
+    "warm_fields": false
+  },
+  "style": "dark",
+  "failover": false,
+  "panel_hints": true,
+  "loader": {
+    "save_gist": false,
+    "save_elasticsearch": true,
+    "save_local": true,
+    "save_default": true,
+    "save_temp": true,
+    "save_temp_ttl_enable": true,
+    "save_temp_ttl": "30d",
+    "load_gist": true,
+    "load_elasticsearch": true,
+    "load_elasticsearch_size": 20,
+    "load_local": true,
+    "hide": false
+  },
+  "pulldowns": [
+    {
+      "type": "query",
+      "collapse": false,
+      "notice": false,
+      "query": "*",
+      "pinned": true,
+      "history": [],
+      "remember": 10
+    },
+    {
+      "type": "filtering",
+      "collapse": true,
+      "notice": false
+    }
+  ],
+  "nav": [
+    {
+      "type": "timepicker",
+      "collapse": false,
+      "notice": false,
+      "status": "Stable",
+      "time_options": [
+        "5m",
+        "15m",
+        "1h",
+        "6h",
+        "12h",
+        "24h",
+        "2d",
+        "7d",
+        "30d"
+      ],
+      "refresh_intervals": [
+        "5s",
+        "10s",
+        "30s",
+        "1m",
+        "5m",
+        "15m",
+        "30m",
+        "1h",
+        "2h",
+        "1d"
+      ],
+      "timefield": "@timestamp"
+    }
+  ],
+  "refresh": false
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/dashboards/pcap5.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/dashboards/pcap5.js b/opensoc-ui/lib/public/app/dashboards/pcap5.js
new file mode 100644
index 0000000..c8890aa
--- /dev/null
+++ b/opensoc-ui/lib/public/app/dashboards/pcap5.js
@@ -0,0 +1,262 @@
+/* global _ */
+
+/*
+ * Complex scripted Logstash dashboard
+ * This script generates a dashboard object that Kibana can load. It also takes a number of user
+ * supplied URL parameters, none are required:
+ *
+ * index :: Which index to search? If this is specified, interval is set to 'none'
+ * pattern :: Does nothing if index is specified. Set a timestamped index pattern. Default: [logstash-]YYYY.MM.DD
+ * interval :: Sets the index interval (eg: day,week,month,year), Default: day
+ *
+ * split :: The character to split the queries on Default: ','
+ * query :: By default, a comma separated list of queries to run. Default: *
+ *
+ * from :: Search this amount of time back, eg 15m, 1h, 2d. Default: 15m
+ * timefield :: The field containing the time to filter on, Default: message.timestamp
+ *
+ * fields :: comma separated list of fields to show in the table
+ * sort :: comma separated field to sort on, and direction, eg sort=message.timestamp,desc
+ *
+ */
+
+'use strict';
+
+// Setup some variables
+var dashboard, queries, _d_timespan;
+
+// All url parameters are available via the ARGS object
+var ARGS;
+
+// Set a default timespan if one isn't specified
+_d_timespan = '3d';
+
+// Intialize a skeleton with nothing but a rows array and service object
+dashboard = {
+  rows : [],
+  services : {}
+};
+
+// Set a title
+dashboard.title = 'GoodBig Co. with PCAP';
+
+dashboard.failover = false;
+dashboard.index = {
+  default: 'bro,fireeye,qosmos,sourcefire,qradar,lancope',
+  interval: 'none'
+};
+
+
+// In this dashboard we let users pass queries as comma separated list to the query parameter.
+// Or they can specify a split character using the split aparameter
+// If query is defined, split it into a list of query objects
+// NOTE: ids must be integers, hence the parseInt()s
+if(!_.isUndefined(ARGS.query)) {
+  queries = _.object(_.map(ARGS.query.split(ARGS.split||','), function(v,k) {
+    return [k,{
+      query: v,
+      id: parseInt(k,10),
+      alias: v
+    }];
+  }));
+} else {
+  // No queries passed? Initialize a single query to match everything
+  queries = {
+    0: {
+          "query": "enrichment.alert.priority:1",
+          "alias": "Severe",
+          "color": "#FF0000",
+          "id": 0,
+          "pin": true,
+          "type": "lucene",
+          "enable": true
+    },
+    1: {
+          "query": "enrichment.alert.priority:2",
+          "alias": "Urgent",
+          "color": "#FF9900",
+          "id": 1,
+          "pin": true,
+          "type": "lucene",
+          "enable": true
+    },
+    2: {
+          "query": "enrichment.alert.priority:3",
+          "alias": "Warning",
+          "color": "#FFFF00",
+          "id": 2,
+          "pin": true,
+          "type": "lucene",
+          "enable": true
+    }
+  };
+}
+
+
+// Now populate the query service with our objects
+dashboard.services.query = {
+  list : queries,
+  ids : _.map(_.keys(queries),function(v){return parseInt(v,10);})
+};
+
+// Lets also add a default time filter, the value of which can be specified by the user
+
+dashboard.services.filter = {
+  list: {
+    0: {
+      from: "now-"+(ARGS.from||_d_timespan),
+      to: "now",
+      field: ARGS.timefield||"enrichment.message.timestamp",
+      type: "time",
+      active: true,
+      id: 0,
+    }
+  },
+  ids: [0]
+};
+
+
+
+
+// Ok, lets make some rows. The Filters row is collapsed by default
+dashboard.rows = [
+  {
+    title: "Alerts Queue Overview",
+    height: "200px"
+  },
+  {
+    title: "Alerts Query Results",
+    height: "200px"
+  }
+];
+
+// And a table row where you can specify field and sort order
+dashboard.rows[0].panels = [
+  {
+    title: 'Alerts Count type',
+    type: 'terms',
+    field: '_type',
+    span: 2,
+    other: false,
+    missing: false,
+    chart: 'table',
+    locked: true
+  },
+  {
+    title: 'Alerts Count priority',
+    type: 'terms',
+    field: 'enrichment.alert.priority',
+    span: 2,
+    other: false,
+    missing: false,
+    chart: 'table',
+    locked: true
+  },
+  {
+    title: 'Source of All Alerts',
+    type: 'terms',
+    fields: !_.isUndefined(ARGS.fields) ? ARGS.fields.split(',') : ['_type'],
+    chart: 'pie',
+    span: 4,
+    other: false,
+    missing: false,
+    locked: true
+  },
+  {
+    "span": 3,
+    "editable": true,
+    "type": "hits",
+    "loadingEditor": false,
+    "style": {
+      "font-size": "10pt"
+    },
+    "arrangement": "horizontal",
+    "chart": "bar",
+    "counter_pos": "above",
+    "donut": false,
+    "tilt": false,
+    "labels": true,
+    "spyable": true,
+    "queries": {
+      "mode": "selected",
+      "ids": [
+        0,
+        1,
+        2
+      ]
+    },
+    "locked": true,
+    "title": "Alerts Severity"
+  },
+  {
+    title: 'Alerts Severity Timeline',
+    type: 'histogram',
+    fields: !_.isUndefined(ARGS.fields) ? ARGS.fields.split(',') : ['_type'],
+    mode: 'count',
+    span: 10,
+    time_field: 'enrichment.message.timestamp'
+  },
+  {
+    title: 'Top Alerts',
+    type: 'table',
+    fields: !_.isUndefined(ARGS.fields) ? ARGS.fields.split(',') : [
+            "enrichment.message.timestamp",
+            "enrichment.alert.priority",
+            "_type",
+            "enrichment.message.ip_src_addr",
+            "enrichment.message.ip_dst_addr",
+            "enrichment.message.original_string"
+          ],
+    size: 10,
+    sort: !_.isUndefined(ARGS.sort) ? ARGS.sort.split(',') : [ARGS.timefield||'enrichment.alert.priority','desc'],
+    overflow: 'expand',
+    span: 12,
+    field_list: false,
+    timeField: 'enrichment.message.timestamp',
+    localTime: true,
+    locked: true,
+    sortable: false
+  }
+];
+
+// And Query Results
+dashboard.rows[1].panels = [
+  {
+    title: 'Alert Query Resuts',
+    type: 'table',
+    fields: !_.isUndefined(ARGS.fields) ? ARGS.fields.split(',') : [
+            "enrichment.message.timestamp",
+            "enrichment.alert.priority",
+            "_type",
+            "enrichment.message.ip_src_addr",
+            "enrichment.message.ip_dst_addr",
+            "enrichment.message.original_string"
+          ],
+    size: 30,
+    sort: !_.isUndefined(ARGS.sort) ? ARGS.sort.split(',') : [ARGS.timefield||'enrichment.message.timestamp','asc'],
+    overflow: 'expand',
+    span: 12,
+    field_list: false,
+    timeField: 'enrichment.message.timestamp',
+    localTime: true
+  },
+  {
+    title: 'PCAP Panel',
+    type: 'pcap',
+    span: 12
+  }
+];
+
+// And a PCAP Panel
+/*dashboard.rows[2].panels = [
+  {
+    title: 'PCAP Panel',
+    type: 'pcap',
+    span: 12
+  }
+];*/
+
+
+
+// Now return the object and we're good!
+return dashboard;

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/addPanel.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/addPanel.js b/opensoc-ui/lib/public/app/directives/addPanel.js
new file mode 100755
index 0000000..38a4f80
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/addPanel.js
@@ -0,0 +1,35 @@
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  angular
+    .module('kibana.directives')
+    .directive('addPanel', function($compile) {
+      return {
+        restrict: 'A',
+        link: function($scope, elem) {
+
+          $scope.$on("$destroy",function() {
+            elem.remove();
+          });
+
+          $scope.$watch('panel.type', function() {
+            var _type = $scope.panel.type;
+            $scope.reset_panel(_type);
+            if(!_.isUndefined($scope.panel.type)) {
+              $scope.panel.loadingEditor = true;
+              $scope.require(['panels/'+$scope.panel.type.replace(".","/") +'/module'], function () {
+                var template = '<div ng-controller="'+$scope.panel.type+'" ng-include="\'app/partials/paneladd.html\'"></div>';
+                elem.html($compile(angular.element(template))($scope));
+                $scope.panel.loadingEditor = false;
+              });
+            }
+          });
+        }
+      };
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/all.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/all.js b/opensoc-ui/lib/public/app/directives/all.js
new file mode 100755
index 0000000..c191ba7
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/all.js
@@ -0,0 +1,13 @@
+define([
+  './addPanel',
+  './arrayJoin',
+  './dashUpload',
+  './kibanaPanel',
+  './kibanaSimplePanel',
+  './ngBlur',
+  './ngModelOnBlur',
+  './tip',
+  './confirmClick',
+  './esVersion',
+  './configModal'
+], function () {});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/arrayJoin.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/arrayJoin.js b/opensoc-ui/lib/public/app/directives/arrayJoin.js
new file mode 100755
index 0000000..72be494
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/arrayJoin.js
@@ -0,0 +1,34 @@
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  angular
+    .module('kibana.directives')
+    .directive('arrayJoin', function() {
+      return {
+        restrict: 'A',
+        require: 'ngModel',
+        link: function(scope, element, attr, ngModel) {
+
+          function split_array(text) {
+            return (text || '').split(',');
+          }
+
+          function join_array(text) {
+            if(_.isArray(text)) {
+              return (text || '').join(',');
+            } else {
+              return text;
+            }
+          }
+
+          ngModel.$parsers.push(split_array);
+          ngModel.$formatters.push(join_array);
+        }
+      };
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/configModal.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/configModal.js b/opensoc-ui/lib/public/app/directives/configModal.js
new file mode 100755
index 0000000..d2d9ad9
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/configModal.js
@@ -0,0 +1,52 @@
+define([
+  'angular',
+  'lodash'
+],
+function (angular,_) {
+  'use strict';
+
+  angular
+    .module('kibana.directives')
+    .directive('configModal', function($modal,$q) {
+      return {
+        restrict: 'A',
+        link: function(scope, elem, attrs) {
+          var
+            model = attrs.kbnModel,
+            partial = attrs.configModal;
+
+
+          // create a new modal. Can't reuse one modal unforunately as the directive will not
+          // re-render on show.
+          elem.bind('click',function(){
+
+            // Create a temp scope so we can discard changes to it if needed
+            var tmpScope = scope.$new();
+            tmpScope[model] = angular.copy(scope[model]);
+
+            tmpScope.editSave = function(panel) {
+              // Correctly set the top level properties of the panel object
+              _.each(panel,function(v,k) {
+                scope[model][k] = panel[k];
+              });
+            };
+
+            var panelModal = $modal({
+              //template: './app/partials/paneleditor.html',
+              template: partial,
+              persist: true,
+              show: false,
+              scope: tmpScope,
+              keyboard: false
+            });
+
+            // and show it
+            $q.when(panelModal).then(function(modalEl) {
+              modalEl.modal('show');
+            });
+            scope.$apply();
+          });
+        }
+      };
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/confirmClick.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/confirmClick.js b/opensoc-ui/lib/public/app/directives/confirmClick.js
new file mode 100755
index 0000000..ac1f571
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/confirmClick.js
@@ -0,0 +1,26 @@
+define([
+  'angular',
+  'kbn'
+],
+function (angular) {
+  'use strict';
+
+  var module = angular.module('kibana.directives');
+
+  module.directive('confirmClick', function() {
+    return {
+      restrict: 'A',
+      link: function(scope, elem, attrs) {
+        elem.bind('click', function() {
+          var message = attrs.confirmation || "Are you sure you want to do that?";
+          if (window.confirm(message)) {
+            var action = attrs.confirmClick;
+            if (action) {
+              scope.$apply(scope.$eval(action));
+            }
+          }
+        });
+      },
+    };
+  });
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/dashUpload.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/dashUpload.js b/opensoc-ui/lib/public/app/directives/dashUpload.js
new file mode 100755
index 0000000..6da7506
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/dashUpload.js
@@ -0,0 +1,37 @@
+define([
+  'angular'
+],
+function (angular) {
+  'use strict';
+
+  var module = angular.module('kibana.directives');
+
+  module.directive('dashUpload', function(timer, dashboard, alertSrv){
+    return {
+      restrict: 'A',
+      link: function(scope) {
+        function file_selected(evt) {
+          var files = evt.target.files; // FileList object
+          var readerOnload = function() {
+            return function(e) {
+              dashboard.dash_load(JSON.parse(e.target.result));
+              scope.$apply();
+            };
+          };
+          for (var i = 0, f; f = files[i]; i++) {
+            var reader = new FileReader();
+            reader.onload = (readerOnload)(f);
+            reader.readAsText(f);
+          }
+        }
+        // Check for the various File API support.
+        if (window.File && window.FileReader && window.FileList && window.Blob) {
+          // Something
+          document.getElementById('dashupload').addEventListener('change', file_selected, false);
+        } else {
+          alertSrv.set('Oops','Sorry, the HTML5 File APIs are not fully supported in this browser.','error');
+        }
+      }
+    };
+  });
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/directives/esVersion.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/directives/esVersion.js b/opensoc-ui/lib/public/app/directives/esVersion.js
new file mode 100755
index 0000000..9d99aad
--- /dev/null
+++ b/opensoc-ui/lib/public/app/directives/esVersion.js
@@ -0,0 +1,24 @@
+/*
+  Only show an element if it meets an Elasticsearch version requirement
+*/
+
+define([
+  'angular',
+  'app',
+],
+function (angular) {
+  'use strict';
+
+  angular
+    .module('kibana.directives')
+    .directive('esVersion', function(esVersion) {
+      return {
+        restrict: 'A',
+        link: function(scope, elem, attr) {
+          if(!esVersion.is(attr.esVersion)) {
+            elem.hide();
+          }
+        }
+      };
+    });
+});



Mime
View raw message