metron-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From omal...@apache.org
Subject [28/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:52 GMT
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.css
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.css b/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.css
new file mode 100755
index 0000000..ba2c7c4
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.css
@@ -0,0 +1,75 @@
+.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
+	-webkit-transition: -webkit-transform 0.2s ease-out, opacity 0.2s ease-in;
+	-moz-transition: -moz-transform 0.2s ease-out, opacity 0.2s ease-in;
+	-o-transition: -o-transform 0.2s ease-out, opacity 0.2s ease-in;
+	transition: transform 0.2s ease-out, opacity 0.2s ease-in;
+	}
+.marker-cluster-small {
+	background-color: rgba(181, 226, 140, 0.6);
+	}
+.marker-cluster-small div {
+	background-color: rgba(110, 204, 57, 0.6);
+	}
+
+.marker-cluster-medium {
+	background-color: rgba(241, 211, 87, 0.6);
+	}
+.marker-cluster-medium div {
+	background-color: rgba(240, 194, 12, 0.6);
+	}
+
+.marker-cluster-large {
+	background-color: rgba(253, 156, 115, 0.6);
+	}
+.marker-cluster-large div {
+	background-color: rgba(241, 128, 23, 0.6);
+	}
+
+.marker-cluster {
+	background-clip: padding-box;
+	border-radius: 20px;
+	}
+.marker-cluster div {
+	width: 30px;
+	height: 30px;
+	margin-left: 5px;
+	margin-top: 5px;
+
+	text-align: center;
+	border-radius: 15px;
+	font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
+	}
+.marker-cluster span {
+	line-height: 30px;
+	}
+
+.leaflet-label {
+	background: #1f1f1f;
+	background-clip: padding-box;
+	border-radius: 4px;
+	border-style: solid;
+	border-width: 0px;
+	display: block;
+	font-weight: 200;
+	font-size: 11pt;
+	padding: 5px;
+	position: absolute;
+	-webkit-user-select: none;
+	   -moz-user-select: none;
+	    -ms-user-select: none;
+	        user-select: none;
+	white-space: nowrap;
+	z-index: 99999 !important;
+}
+
+.leaflet-label:before {
+	border-right: 6px solid black;
+	border-right-color: inherit;
+	border-top: 6px solid transparent;
+	border-bottom: 6px solid transparent;
+	content: "";
+	position: absolute;
+	top: 5px;
+	left: -10px;
+	display: none;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.js b/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.js
new file mode 100755
index 0000000..81f6e44
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/bettermap/leaflet/plugins.js
@@ -0,0 +1,16 @@
+/*
+ Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps.
+ https://github.com/Leaflet/Leaflet.markercluster
+ (c) 2012-2013, Dave Leaver, smartrak
+*/
+!function(t,e){L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,polygonOptions:{}},initialize:function(t){L.Util.setOptions(this,t),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),L.FeatureGroup.prototype.initialize.call(this,[]),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null},addLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.addLayers(e)}if(!this._map)return this._needsClustering.push(t),this;if(this.hasLayer(t))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(t,this._maxZoom);var n=t,r=this._map.getZoom();if(t.__parent)for(;n.__parent._zoom>=r;)n=n.__pare
 nt;return this._currentShownBounds.contains(n.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(t,n):this._animationAddLayerNonAnimated(t,n)),this},removeLayer:function(t){return this._map?t.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(t)),this._removeLayer(t,!0),(t._icon||t._container)&&(L.FeatureGroup.prototype.removeLayer.call(this,t),t.setOpacity&&t.setOpacity(1)),this):this:(!this._arraySplice(this._needsClustering,t)&&this.hasLayer(t)&&this._needsRemoving.push(t),this)},addLayers:function(t){var e,i,n;if(!this._map)return this._needsClustering=this._needsClustering.concat(t),this;for(e=0,i=t.length;i>e;e++)if(n=t[e],!this.hasLayer(n)&&(this._addLayer(n,this._maxZoom),n.__parent&&2===n.__parent.getChildCount())){var r=n.__parent.getAllChildMarkers(),s=r[0]===n?r[1]:r[0];L.FeatureGroup.prototype.removeLayer.call(this,s)}for(e in this._layers)n=this._layers[e],n instanceof L.MarkerCluster&&n._iconNeedsUpdate&&n._updateIcon();return 
 this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),this},removeLayers:function(t){var e,i,n;if(!this._map){for(e=0,i=t.length;i>e;e++)this._arraySplice(this._needsClustering,t[e]);return this}for(e=0,i=t.length;i>e;e++)n=t[e],n.__parent&&(this._removeLayer(n,!0,!0),n._icon&&(L.FeatureGroup.prototype.removeLayer.call(this,n),n.setOpacity(1)));this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds);for(e in this._layers)n=this._layers[e],n instanceof L.MarkerCluster&&n._updateIcon();return this},clearLayers:function(){this._map||(this._needsClustering=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy();for(var t in this._layers)L.FeatureGroup.prototype.removeLayer.call(this,this._layers[t]);return this.eachLayer(function(t){delete t.__parent}),this._map&&this._generateInitialClusters(),this},getBounds:function(){var t=new L.LatLngBounds;if(th
 is._topClusterLevel)t.extend(this._topClusterLevel._bounds);else for(var e=this._needsClustering.length-1;e>=0;e--)t.extend(this._needsClustering[e].getLatLng());return t},eachLayer:function(t,e){var i,n=this._needsClustering.slice();for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(n),i=n.length-1;i>=0;i--)t.call(e,n[i])},hasLayer:function(t){if(!t||t._noHas)return!1;var e,i=this._needsClustering;for(e=i.length-1;e>=0;e--)if(i[e]===t)return!0;for(i=this._needsRemoving,e=i.length-1;e>=0;e--)if(i[e]===t)return!1;return!(!t.__parent||t.__parent._group!==this)},zoomToShowLayer:function(t,e){var i=function(){if((t._icon||t.__parent._icon)&&!this._inZoomAnimation)if(this._map.off("moveend",i,this),this.off("animationend",i,this),t._icon)e();else if(t.__parent._icon){var n=function(){this.off("spiderfied",n,this),e()};this.on("spiderfied",n,this),t.__parent.spiderfy()}};t._icon?e():t.__parent._zoom<this._map.getZoom()?(this._map.on("moveend",i,this),t._icon||this._map.pa
 nTo(t.getLatLng())):(this._map.on("moveend",i,this),this.on("animationend",i,this),this._map.setView(t.getLatLng(),t.__parent._zoom+1),t.__parent.zoomToBounds())},onAdd:function(t){this._map=t;var e,i,n;for(this._gridClusters||this._generateInitialClusters(),e=0,i=this._needsRemoving.length;i>e;e++)n=this._needsRemoving[e],this._removeLayer(n);for(this._needsRemoving=[],e=0,i=this._needsClustering.length;i>e;e++)n=this._needsClustering[e],n.__parent||this._addLayer(n,this._maxZoom);this._needsClustering=[],this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),this._zoom=this._map.getZoom(),this._currentShownBounds=this._getExpandedVisibleBounds(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)},onRemove:function(t){t.off("zoomend",this._zoomEnd,this),t.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._m
 ap._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove();for(var e in this._layers)L.FeatureGroup.prototype.removeLayer.call(this,this._layers[e]);this._map=null},_arraySplice:function(t,e){for(var i=t.length-1;i>=0;i--)if(t[i]===e)return t.splice(i,1),!0},_removeLayer:function(t,e,i){var n=this._gridClusters,r=this._gridUnclustered,s=this._map;if(e)for(var o=this._maxZoom;o>=0&&r[o].removeObject(t,s.project(t.getLatLng(),o));o--);var a,l=t.__parent,_=l._markers;for(this._arraySplice(_,t);l&&(l._childCount--,!(l._zoom<0));)e&&l._childCount<=1?(a=l._markers[0]===t?l._markers[1]:l._markers[0],n[l._zoom].removeObject(l,s.project(l._cLatLng,l._zoom)),r[l._zoom].addObject(a,s.project(a.getLatLng(),l._zoom)),this._arraySplice(l.__parent._childClusters,l),l.__parent._markers.push(a),a.__parent=l.__parent,l._icon&&(L.FeatureGroup.prototype.removeLayer.call(this,l),i||(a._noHas=!0,L.FeatureGroup.prototype.addLayer.call(this,a),delete a._n
 oHas))):(l._recalculateBounds(),i&&l._icon||l._updateIcon()),l=l.__parent;delete t.__parent},_propagateEvent:function(t){t.target instanceof L.MarkerCluster&&(t.type="cluster"+t.type),L.FeatureGroup.prototype._propagateEvent.call(this,t)},_defaultIconCreateFunction:function(t){var e=t.getChildCount(),i=" marker-cluster-";return i+=10>e?"small":100>e?"medium":"large",new L.DivIcon({html:"<div><span>"+e+"</span></div>",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var t=null,e=this._map,i=this.options.spiderfyOnMaxZoom,n=this.options.showCoverageOnHover,r=this.options.zoomToBoundsOnClick;(i||r)&&this.on("clusterclick",function(t){e.getMaxZoom()===e.getZoom()?i&&t.layer.spiderfy():r&&t.layer.zoomToBounds()},this),n&&(this.on("clustermouseover",function(i){this._inZoomAnimation||(t&&e.removeLayer(t),i.layer.getChildCount()>2&&i.layer!==this._spiderfied&&(t=new L.Polygon(i.layer.getConvexHull(),this.options.polygonOptions),e.addLayer(t)))},this),this.
 on("clustermouseout",function(){t&&(e.removeLayer(t),t=null)},this),e.on("zoomend",function(){t&&(e.removeLayer(t),t=null)},this),e.on("layerremove",function(i){t&&i.layer===this&&(e.removeLayer(t),t=null)},this))},_unbindEvents:function(){var t=this.options.spiderfyOnMaxZoom,e=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(t||i)&&this.off("clusterclick",null,this),e&&(this.off("clustermouseover",null,this),this.off("clustermouseout",null,this),n.off("zoomend",null,this),n.off("layerremove",null,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=this._map._zoom,this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var t=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,t),this._currentShownBounds=t}},_generateInitialClusters:fun
 ction(){var t=this._map.getMaxZoom(),e=this.options.maxClusterRadius;this.options.disableClusteringAtZoom&&(t=this.options.disableClusteringAtZoom-1),this._maxZoom=t,this._gridClusters={},this._gridUnclustered={};for(var i=t;i>=0;i--)this._gridClusters[i]=new L.DistanceGrid(e),this._gridUnclustered[i]=new L.DistanceGrid(e);this._topClusterLevel=new L.MarkerCluster(this,-1)},_addLayer:function(t,e){var i,n,r=this._gridClusters,s=this._gridUnclustered;for(this.options.singleMarkerMode&&(t.options.icon=this.options.iconCreateFunction({getChildCount:function(){return 1},getAllChildMarkers:function(){return[t]}}));e>=0;e--){i=this._map.project(t.getLatLng(),e);var o=r[e].getNearObject(i);if(o)return o._addChild(t),t.__parent=o,void 0;if(o=s[e].getNearObject(i)){var a=o.__parent;a&&this._removeLayer(o,!1);var l=new L.MarkerCluster(this,e,o,t);r[e].addObject(l,this._map.project(l._cLatLng,e)),o.__parent=l,t.__parent=l;var _=l;for(n=e-1;n>a._zoom;n--)_=new L.MarkerCluster(this,n,_),r[n].add
 Object(_,this._map.project(o.getLatLng(),n));for(a._addChild(_),n=e;n>=0&&s[n].removeObject(o,this._map.project(o.getLatLng(),n));n--);return}s[e].addObject(t,i)}this._topClusterLevel._addChild(t),t.__parent=this._topClusterLevel},_mergeSplitClusters:function(){this._zoom<this._map._zoom?(this._animationStart(),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,this._getExpandedVisibleBounds()),this._animationZoomIn(this._zoom,this._map._zoom)):this._zoom>this._map._zoom?(this._animationStart(),this._animationZoomOut(this._zoom,this._map._zoom)):this._moveEnd()},_getExpandedVisibleBounds:function(){if(!this.options.removeOutsideVisibleBounds)return this.getBounds();var t=this._map,e=t.getBounds(),i=e._southWest,n=e._northEast,r=L.Browser.mobile?0:Math.abs(i.lat-n.lat),s=L.Browser.mobile?0:Math.abs(i.lng-n.lng);return new L.LatLngBounds(new L.LatLng(i.lat-r,i.lng-s,!0),new L.LatLng(n.lat+r,n.lng+s,!0))},_animationAddLayerNonAnimated:function(t
 ,e){if(e===t)t._noHas=!0,L.FeatureGroup.prototype.addLayer.call(this,t),delete t._noHas;else if(2===e._childCount){e._addToMap();var i=e.getAllChildMarkers();L.FeatureGroup.prototype.removeLayer.call(this,i[0]),L.FeatureGroup.prototype.removeLayer.call(this,i[1])}else e._updateIcon()}}),L.MarkerClusterGroup.include(L.DomUtil.TRANSITION?{_animationStart:function(){this._map._mapPane.className+=" leaflet-cluster-anim",this._inZoomAnimation++},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_animationZoomIn:function(t,e){var i,n=this,r=this._getExpandedVisibleBounds();this._topClusterLevel._recursively(r,t,0,function(s){var o,a=s._latlng,l=s._markers;for(s._isSingleParent()&&t+1===e?(L.FeatureGroup.prototype.removeLayer.call(n,s),s._recursivelyAddChildrenToMap(null,e,r)):(s.setOpacity(0),s._recursivelyAddChildrenToMap(a,e,r)),i=l.length-1;i>=0;i--)o=l[i
 ],r.contains(o._latlng)||L.FeatureGroup.prototype.removeLayer.call(n,o)}),this._forceLayout();var s,o;n._topClusterLevel._recursivelyBecomeVisible(r,e);for(s in n._layers)o=n._layers[s],o instanceof L.MarkerCluster||!o._icon||o.setOpacity(1);n._topClusterLevel._recursively(r,t,e,function(t){t._recursivelyRestoreChildPositions(e)}),setTimeout(function(){n._topClusterLevel._recursively(r,t,0,function(t){L.FeatureGroup.prototype.removeLayer.call(n,t),t.setOpacity(1)}),n._animationEnd()},200)},_animationZoomOut:function(t,e){this._animationZoomOutSingle(this._topClusterLevel,t-1,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t,this._getExpandedVisibleBounds())},_animationZoomOutSingle:function(t,e,i){var n=this._getExpandedVisibleBounds();t._recursivelyAnimateChildrenInAndAddSelfToMap(n,e+1,i);var r=this;this._forceLayout(),t._recursivelyBecomeVisible(n,i),set
 Timeout(function(){if(1===t._childCount){var s=t._markers[0];s.setLatLng(s.getLatLng()),s.setOpacity(1)}else t._recursively(n,i,0,function(t){t._recursivelyRemoveChildrenFromMap(n,e+1)});r._animationEnd()},200)},_animationAddLayer:function(t,e){var i=this;t._noHas=!0,L.FeatureGroup.prototype.addLayer.call(this,t),delete t._noHas,e!==t&&(e._childCount>2?(e._updateIcon(),this._forceLayout(),this._animationStart(),t._setPos(this._map.latLngToLayerPoint(e.getLatLng())),t.setOpacity(0),setTimeout(function(){L.FeatureGroup.prototype.removeLayer.call(i,t),t.setOpacity(1),i._animationEnd()},200)):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(e,this._map.getMaxZoom(),this._map.getZoom())))},_forceLayout:function(){L.Util.falseFn(e.body.offsetWidth)}}:{_animationStart:function(){},_animationZoomIn:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisi
 bleBounds())},_animationZoomOut:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds())},_animationAddLayer:function(t,e){this._animationAddLayerNonAnimated(t,e)}}),L.markerClusterGroup=function(t){return new L.MarkerClusterGroup(t)},L.MarkerCluster=L.Marker.extend({initialize:function(t,e,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this}),this._group=t,this._zoom=e,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(t){t=t||[];for(var e=this._childClusters.length-1;e>=0;e--)this._childClusters[e].getAllChildMarkers(t);for(var i=this._markers.length-1;i>=0;i--)t.push(this._markers[i]);return t},getChildCount:function(){return this._childCount},zoomToBounds:function()
 {this._group._map.fitBounds(this._bounds)},getBounds:function(){var t=new L.LatLngBounds;return t.extend(this._bounds),t},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(t,e){this._iconNeedsUpdate=!0,this._expandBounds(t),t instanceof L.MarkerCluster?(e||(this._childClusters.push(t),t.__parent=this),this._childCount+=t._childCount):(e||this._markers.push(t),this._childCount++),this.__parent&&this.__parent._addChild(t,!0)},_expandBounds:function(t){var e,i=t._wLatLng||t._latlng;t instanceof L.MarkerCluster?(this._bounds.extend(t._bounds),e=t._childCount):(this._bounds.extend(i),e=1),this._cLatLng||(this._cLatLng=t._cLatLng||i);var n=this._childCount+e;this._wLatLng?(this._wLatLng.lat=(i.lat*e+this._wLatLng.lat*
 this._childCount)/n,this._wLatLng.lng=(i.lng*e+this._wLatLng.lng*this._childCount)/n):this._latlng=this._wLatLng=new L.LatLng(i.lat,i.lng)},_addToMap:function(t){t&&(this._backupLatlng=this._latlng,this.setLatLng(t)),this._noHas=!0,L.FeatureGroup.prototype.addLayer.call(this._group,this),delete this._noHas},_recursivelyAnimateChildrenIn:function(t,e,i){this._recursively(t,0,i-1,function(t){var i,n,r=t._markers;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(e),n.setOpacity(0))},function(t){var i,n,r=t._childClusters;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(e),n.setOpacity(0))})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(t,e,i){this._recursively(t,i,0,function(n){n._recursivelyAnimateChildrenIn(t,n._group._map.latLngToLayerPoint(n.getLatLng()).round(),e),n._isSingleParent()&&e-1===i?(n.setOpacity(1),n._recursivelyRemoveChildrenFromMap(t,e)):n.setOpacity(0),n._addToMap()})},_recursivelyBecomeVisible:function(t,e){this._recursively(t,0,e,null,function(t){t.
 setOpacity(1)})},_recursivelyAddChildrenToMap:function(t,e,i){this._recursively(i,-1,e,function(n){if(e!==n._zoom)for(var r=n._markers.length-1;r>=0;r--){var s=n._markers[r];i.contains(s._latlng)&&(t&&(s._backupLatlng=s.getLatLng(),s.setLatLng(t),s.setOpacity&&s.setOpacity(0)),s._noHas=!0,L.FeatureGroup.prototype.addLayer.call(n._group,s),delete s._noHas)}},function(e){e._addToMap(t)})},_recursivelyRestoreChildPositions:function(t){for(var e=this._markers.length-1;e>=0;e--){var i=this._markers[e];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(t-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var r=this._childClusters.length-1;r>=0;r--)this._childClusters[r]._recursivelyRestoreChildPositions(t)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(t,e,i){var n,r;this._recursively(t,-1,e-1,fun
 ction(t){for(r=t._markers.length-1;r>=0;r--)n=t._markers[r],i&&i.contains(n._latlng)||(L.FeatureGroup.prototype.removeLayer.call(t._group,n),n.setOpacity&&n.setOpacity(1))},function(t){for(r=t._childClusters.length-1;r>=0;r--)n=t._childClusters[r],i&&i.contains(n._latlng)||((!L.FeatureGroup.prototype.hasLayer||L.FeatureGroup.prototype.hasLayer.call(t._group,n))&&L.FeatureGroup.prototype.removeLayer.call(t._group,n),n.setOpacity&&n.setOpacity(1))})},_recursively:function(t,e,i,n,r){var s,o,a=this._childClusters,l=this._zoom;if(e>l)for(s=a.length-1;s>=0;s--)o=a[s],t.intersects(o._bounds)&&o._recursively(t,e,i,n,r);else if(n&&n(this),r&&this._zoom===i&&r(this),i>l)for(s=a.length-1;s>=0;s--)o=a[s],t.intersects(o._bounds)&&o._recursively(t,e,i,n,r)},_recalculateBounds:function(){var t,e=this._markers,i=this._childClusters;for(this._bounds=new L.LatLngBounds,delete this._wLatLng,t=e.length-1;t>=0;t--)this._expandBounds(e[t]);for(t=i.length-1;t>=0;t--)this._expandBounds(i[t])},_isSinglePar
 ent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}}),L.DistanceGrid=function(t){this._cellSize=t,this._sqCellSize=t*t,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(t,e){var i=this._getCoord(e.x),n=this._getCoord(e.y),r=this._grid,s=r[n]=r[n]||{},o=s[i]=s[i]||[],a=L.Util.stamp(t);this._objectPoint[a]=e,o.push(t)},updateObject:function(t,e){this.removeObject(t),this.addObject(t,e)},removeObject:function(t,e){var i,n,r=this._getCoord(e.x),s=this._getCoord(e.y),o=this._grid,a=o[s]=o[s]||{},l=a[r]=a[r]||[];for(delete this._objectPoint[L.Util.stamp(t)],i=0,n=l.length;n>i;i++)if(l[i]===t)return l.splice(i,1),1===n&&delete a[r],!0},eachObject:function(t,e){var i,n,r,s,o,a,l,_=this._grid;for(i in _){o=_[i];for(n in o)for(a=o[n],r=0,s=a.length;s>r;r++)l=t.call(e,a[r]),l&&(r--,s--)}},getNearObject:function(t){var e,i,n,r,s,o,a,l,_=this._getCoord(t.x),h=this._getCoord(t.y),u=this._objectPoint,d=this._sqCe
 llSize,p=null;for(e=h-1;h+1>=e;e++)if(r=this._grid[e])for(i=_-1;_+1>=i;i++)if(s=r[i])for(n=0,o=s.length;o>n;n++)a=s[n],l=this._sqDist(u[L.Util.stamp(a)],t),d>l&&(d=l,p=a);return p},_getCoord:function(t){return Math.floor(t/this._cellSize)},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(t,e){var i=e[1].lat-e[0].lat,n=e[0].lng-e[1].lng;return n*(t.lat-e[0].lat)+i*(t.lng-e[0].lng)},findMostDistantPointFromBaseLine:function(t,e){var i,n,r,s=0,o=null,a=[];for(i=e.length-1;i>=0;i--)n=e[i],r=this.getDistant(n,t),r>0&&(a.push(n),r>s&&(s=r,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(t,e){var i=[],n=this.findMostDistantPointFromBaseLine(t,e);return n.maxPoint?(i=i.concat(this.buildConvexHull([t[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,t[1]],n.newPoints))):[t]},getConvexHull:function(t){var e,i=!1,n=!1,r=null,s=null;for(e=t.length-1;e>=0;e--){var o=t[e];(i===!1||o.lat>i)&&(r=o,i=o.lat
 ),(n===!1||o.lat<n)&&(s=o,n=o.lat)}var a=[].concat(this.buildConvexHull([s,r],t),this.buildConvexHull([r,s],t));return a}}}(),L.MarkerCluster.include({getConvexHull:function(){var t,e,i,n=this.getAllChildMarkers(),r=[],s=[];for(i=n.length-1;i>=0;i--)e=n[i].getLatLng(),r.push(e);for(t=L.QuickHull.getConvexHull(r),i=t.length-1;i>=0;i--)s.push(t[i][0]);return s}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:Math.PI/6,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var t,e=this.getAllChildMarkers(),i=this._group,n=i._map,r=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,e.length>=this._circleSpiralSwitchover?t=this._generatePointsSpiral(e.length,r):(r.y+=10,t=this._generatePointsCircle(e.length,r)),this._animationSpiderfy(e,t)}},unspiderfy:function(t){this._group._inZoomAnimat
 ion||(this._animationUnspiderfy(t),this._group._spiderfied=null)},_generatePointsCircle:function(t,e){var i,n,r=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+t),s=r/this._2PI,o=this._2PI/t,a=[];for(a.length=t,i=t-1;i>=0;i--)n=this._circleStartAngle+i*o,a[i]=new L.Point(e.x+s*Math.cos(n),e.y+s*Math.sin(n))._round();return a},_generatePointsSpiral:function(t,e){var i,n=this._group.options.spiderfyDistanceMultiplier*this._spiralLengthStart,r=this._group.options.spiderfyDistanceMultiplier*this._spiralFootSeparation,s=this._group.options.spiderfyDistanceMultiplier*this._spiralLengthFactor,o=0,a=[];for(a.length=t,i=t-1;i>=0;i--)o+=r/n+5e-4*i,a[i]=new L.Point(e.x+n*Math.cos(o),e.y+n*Math.sin(o))._round(),n+=this._2PI*s/o;return a},_noanimationUnspiderfy:function(){var t,e,i=this._group,n=i._map,r=this.getAllChildMarkers();for(this.setOpacity(1),e=r.length-1;e>=0;e--)t=r[e],L.FeatureGroup.prototype.removeLayer.call(i,t),t._preSpiderfyLatlng&&(t.setLatLng(t._pr
 eSpiderfyLatlng),delete t._preSpiderfyLatlng),t.setZIndexOffset(0),t._spiderLeg&&(n.removeLayer(t._spiderLeg),delete t._spiderLeg)}}),L.MarkerCluster.include(L.DomUtil.TRANSITION?{SVG_ANIMATION:function(){return e.createElementNS("http://www.w3.org/2000/svg","animate").toString().indexOf("SVGAnimate")>-1}(),_animationSpiderfy:function(t,i){var n,r,s,o,a=this,l=this._group,_=l._map,h=_.latLngToLayerPoint(this._latlng);for(n=t.length-1;n>=0;n--)r=t[n],r.setZIndexOffset(1e6),r.setOpacity(0),r._noHas=!0,L.FeatureGroup.prototype.addLayer.call(l,r),delete r._noHas,r._setPos(h);l._forceLayout(),l._animationStart();var u=L.Path.SVG?0:.3,d=L.Path.SVG_NS;for(n=t.length-1;n>=0;n--)if(o=_.layerPointToLatLng(i[n]),r=t[n],r._preSpiderfyLatlng=r._latlng,r.setLatLng(o),r.setOpacity(1),s=new L.Polyline([a._latlng,o],{weight:1.5,color:"#222",opacity:u}),_.addLayer(s),r._spiderLeg=s,L.Path.SVG&&this.SVG_ANIMATION){var p=s._path.getTotalLength();s._path.setAttribute("stroke-dasharray",p+","+p);var c=e.
 createElementNS(d,"animate");c.setAttribute("attributeName","stroke-dashoffset"),c.setAttribute("begin","indefinite"),c.setAttribute("from",p),c.setAttribute("to",0),c.setAttribute("dur",.25),s._path.appendChild(c),c.beginElement(),c=e.createElementNS(d,"animate"),c.setAttribute("attributeName","stroke-opacity"),c.setAttribute("attributeName","stroke-opacity"),c.setAttribute("begin","indefinite"),c.setAttribute("from",0),c.setAttribute("to",.5),c.setAttribute("dur",.25),s._path.appendChild(c),c.beginElement()}if(a.setOpacity(.3),L.Path.SVG)for(this._group._forceLayout(),n=t.length-1;n>=0;n--)r=t[n]._spiderLeg,r.options.opacity=.5,r._path.setAttribute("stroke-opacity",.5);setTimeout(function(){l._animationEnd(),l.fire("spiderfied")},200)},_animationUnspiderfy:function(t){var e,i,n,r=this._group,s=r._map,o=t?s._latLngToNewLayerPoint(this._latlng,t.zoom,t.center):s.latLngToLayerPoint(this._latlng),a=this.getAllChildMarkers(),l=L.Path.SVG&&this.SVG_ANIMATION;for(r._animationStart(),this
 .setOpacity(1),i=a.length-1;i>=0;i--)e=a[i],e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng,e._setPos(o),e.setOpacity(0),l&&(n=e._spiderLeg._path.childNodes[0],n.setAttribute("to",n.getAttribute("from")),n.setAttribute("from",0),n.beginElement(),n=e._spiderLeg._path.childNodes[1],n.setAttribute("from",.5),n.setAttribute("to",0),n.setAttribute("stroke-opacity",0),n.beginElement(),e._spiderLeg._path.setAttribute("stroke-opacity",0)));setTimeout(function(){var t=0;for(i=a.length-1;i>=0;i--)e=a[i],e._spiderLeg&&t++;for(i=a.length-1;i>=0;i--)e=a[i],e._spiderLeg&&(e.setOpacity(1),e.setZIndexOffset(0),t>1&&L.FeatureGroup.prototype.removeLayer.call(r,e),s.removeLayer(e._spiderLeg),delete e._spiderLeg);r._animationEnd()},200)}}:{_animationSpiderfy:function(t,e){var i,n,r,s,o=this._group,a=o._map;for(i=t.length-1;i>=0;i--)s=a.layerPointToLatLng(e[i]),n=t[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(s),n.setZIndexOffset(1e6),L.FeatureGroup.prototype.addLay
 er.call(o,n),r=new L.Polyline([this._latlng,s],{weight:1.5,color:"#222"}),a.addLayer(r),n._spiderLeg=r;this.setOpacity(.3),o.fire("spiderfied")},_animationUnspiderfy:function(){this._noanimationUnspiderfy()}}),L.MarkerClusterGroup.include({_spiderfied:null,_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation?this._map.on("zoomstart",this._unspiderfyZoomStart,this):this._map.on("zoomend",this._unspiderfyWrapper,this),L.Path.SVG&&!L.Browser.touch&&this._map._initPathRoot()},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy()},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(t){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this
 ),this._unspiderfy(t))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(t){this._spiderfied&&this._spiderfied.unspiderfy(t)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(t){t._spiderLeg&&(L.FeatureGroup.prototype.removeLayer.call(this,t),t.setOpacity(1),t.setZIndexOffset(0),this._map.removeLayer(t._spiderLeg),delete t._spiderLeg)}})}(window,document);
+
+/*
+  Leaflet.label, a plugin that adds labels to markers and vectors for Leaflet powered maps.
+  (c) 2012-2013, Jacob Toye, Smartrak
+
+  https://github.com/Leaflet/Leaflet.label
+  http://leafletjs.com
+  https://github.com/jacobtoye
+*/
+(function(){L.labelVersion="0.1.4-dev",L.Label=L.Popup.extend({options:{autoPan:!1,className:"",closePopupOnClick:!1,noHide:!1,offset:new L.Point(12,-15),opacity:1},onAdd:function(t){this._map=t,this._pane=this._source instanceof L.Marker?t._panes.markerPane:t._panes.popupPane,this._container||this._initLayout(),this._updateContent();var e=t.options.fadeAnimation;e&&L.DomUtil.setOpacity(this._container,0),this._pane.appendChild(this._container),t.on("viewreset",this._updatePosition,this),this._animated&&t.on("zoomanim",this._zoomAnimation,this),L.Browser.touch&&!this.options.noHide&&L.DomEvent.on(this._container,"click",this.close,this),this._update(),this.setOpacity(this.options.opacity)},onRemove:function(t){this._pane.removeChild(this._container),L.Util.falseFn(this._container.offsetWidth),t.off({viewreset:this._updatePosition,zoomanim:this._zoomAnimation},this),t.options.fadeAnimation&&L.DomUtil.setOpacity(this._container,0),this._map=null},close:function(){var t=this._map;t&&(L
 .Browser.touch&&!this.options.noHide&&L.DomEvent.off(this._container,"click",this.close),t._label=null,t.removeLayer(this))},updateZIndex:function(t){this._zIndex=t,this._container&&this._zIndex&&(this._container.style.zIndex=t)},setOpacity:function(t){this.options.opacity=t,this._container&&L.DomUtil.setOpacity(this._container,t)},_initLayout:function(){this._container=L.DomUtil.create("div","leaflet-label "+this.options.className+" leaflet-zoom-animated"),this.updateZIndex(this._zIndex)},_updateContent:function(){this._content&&"string"==typeof this._content&&(this._container.innerHTML=this._content)},_updateLayout:function(){},_updatePosition:function(){var t=this._map.latLngToLayerPoint(this._latlng);this._setPosition(t)},_setPosition:function(t){t=t.add(this.options.offset),L.DomUtil.setPosition(this._container,t)},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);this._setPosition(e)}}),L.Icon.Default.mergeOptions({labelAnchor:new 
 L.Point(9,-20)}),L.Marker.mergeOptions({icon:new L.Icon.Default}),L.Marker.include({showLabel:function(){return this._label&&this._map&&(this._label.setLatLng(this._latlng),this._map.showLabel(this._label)),this},hideLabel:function(){return this._label&&this._label.close(),this},setLabelNoHide:function(t){this._labelNoHide!==t&&(this._labelNoHide=t,t?(this._removeLabelRevealHandlers(),this.showLabel()):(this._addLabelRevealHandlers(),this.hideLabel()))},bindLabel:function(t,e){var i=L.point(this.options.icon.options.labelAnchor)||new L.Point(0,0);return i=i.add(L.Label.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=L.Util.extend({offset:i},e),this._labelNoHide=e.noHide,this._label||(this._labelNoHide||this._addLabelRevealHandlers(),this.on("remove",this.hideLabel,this).on("move",this._moveLabel,this),this._hasLabelHandlers=!0),this._label=new L.Label(e,this).setContent(t),this},unbindLabel:function(){return this._label&&(this.hideLabel(),this._label=null,this._hasLabel
 Handlers&&(this._labelNoHide||this._removeLabelRevealHandlers(),this.off("remove",this.hideLabel,this).off("move",this._moveLabel,this)),this._hasLabelHandlers=!1),this},updateLabelContent:function(t){this._label&&this._label.setContent(t)},_addLabelRevealHandlers:function(){this.on("mouseover",this.showLabel,this).on("mouseout",this.hideLabel,this),L.Browser.touch&&this.on("click",this.showLabel,this)},_removeLabelRevealHandlers:function(){this.off("mouseover",this.showLabel,this).off("mouseout",this.hideLabel,this).off("remove",this.hideLabel,this).off("move",this._moveLabel,this),L.Browser.touch&&this.off("click",this.showLabel,this)},_moveLabel:function(t){this._label.setLatLng(t.latlng)},_originalUpdateZIndex:L.Marker.prototype._updateZIndex,_updateZIndex:function(t){var e=this._zIndex+t;this._originalUpdateZIndex(t),this._label&&this._label.updateZIndex(e)},_originalSetOpacity:L.Marker.prototype.setOpacity,setOpacity:function(t,e){this.options.labelHasSemiTransparency=e,this._
 originalSetOpacity(t)},_originalUpdateOpacity:L.Marker.prototype._updateOpacity,_updateOpacity:function(){var t=0===this.options.opacity?0:1;this._originalUpdateOpacity(),this._label&&this._label.setOpacity(this.options.labelHasSemiTransparency?this.options.opacity:t)}}),L.Path.include({bindLabel:function(t,e){return this._label&&this._label.options===e||(this._label=new L.Label(e,this)),this._label.setContent(t),this._showLabelAdded||(this.on("mouseover",this._showLabel,this).on("mousemove",this._moveLabel,this).on("mouseout remove",this._hideLabel,this),L.Browser.touch&&this.on("click",this._showLabel,this),this._showLabelAdded=!0),this},unbindLabel:function(){return this._label&&(this._hideLabel(),this._label=null,this._showLabelAdded=!1,this.off("mouseover",this._showLabel,this).off("mousemove",this._moveLabel,this).off("mouseout remove",this._hideLabel,this)),this},updateLabelContent:function(t){this._label&&this._label.setContent(t)},_showLabel:function(t){this._label.setLatLn
 g(t.latlng),this._map.showLabel(this._label)},_moveLabel:function(t){this._label.setLatLng(t.latlng)},_hideLabel:function(){this._label.close()}}),L.Map.include({showLabel:function(t){return this._label=t,this.addLayer(t)}}),L.FeatureGroup.include({clearLayers:function(){return this.unbindLabel(),this.eachLayer(this.removeLayer,this),this},bindLabel:function(t,e){return this.invoke("bindLabel",t,e)},unbindLabel:function(){return this.invoke("unbindLabel")},updateLabelContent:function(t){this.invoke("updateLabelContent",t)}})})(this,document);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/bettermap/module.css
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/bettermap/module.css b/opensoc-ui/lib/public/app/panels/bettermap/module.css
new file mode 100755
index 0000000..b0e0969
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/bettermap/module.css
@@ -0,0 +1,4 @@
+/** custom additions **/
+.leaflet-marker-icon {
+  color: #333;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/bettermap/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/bettermap/module.html b/opensoc-ui/lib/public/app/panels/bettermap/module.html
new file mode 100755
index 0000000..f63d8c7
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/bettermap/module.html
@@ -0,0 +1,11 @@
+<div ng-controller='bettermap' ng-init="init()">
+  <style>
+    .leaflet-label {
+      color: #fff;
+    }
+  </style>
+  <!-- This solution might work well for other panels that have trouble with heights -->
+  <div  style="padding-right:10px;padding-top:10px;height:{{panel.height|| row.height}};overflow:hidden">
+    <div bettermap id="{{$id}}" params="{{panel}}" style="height:100%"></div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/bettermap/module.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/bettermap/module.js b/opensoc-ui/lib/public/app/panels/bettermap/module.js
new file mode 100755
index 0000000..d5af475
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/bettermap/module.js
@@ -0,0 +1,279 @@
+/** @scratch /panels/5
+ *
+ * include::panels/bettermap.asciidoc[]
+ */
+
+/** @scratch /panels/bettermap/0
+ *
+ * == Bettermap
+ * Status: *Experimental*
+ *
+ * Bettermap is called bettermap for lack of a better name. Bettermap uses geographic coordinates to
+ * create clusters of markers on map and shade them orange, yellow and green depending on the
+ * density of the cluster.
+ *
+ * To drill down, click on a cluster. The map will be zoomed and the cluster broken into smaller cluster.
+ * When it no longer makes visual sense to cluster, individual markers will be displayed. Hover over
+ * a marker to see the tooltip value/
+ *
+ * IMPORTANT: bettermap requires an internet connection to download its map panels.
+ */
+define([
+  'angular',
+  'app',
+  'lodash',
+  './leaflet/leaflet-src',
+  'require',
+
+  'css!./module.css',
+  'css!./leaflet/leaflet.css',
+  'css!./leaflet/plugins.css'
+],
+function (angular, app, _, L, localRequire) {
+  'use strict';
+
+  var module = angular.module('kibana.panels.bettermap', []);
+  app.useModule(module);
+
+  module.controller('bettermap', function($scope, querySrv, dashboard, filterSrv) {
+    $scope.panelMeta = {
+      editorTabs : [
+        {
+          title: 'Queries',
+          src: 'app/partials/querySelect.html'
+        }
+      ],
+      modals : [
+        {
+          description: "Inspect",
+          icon: "icon-info-sign",
+          partial: "app/partials/inspector.html",
+          show: $scope.panel.spyable
+        }
+      ],
+      status  : "Experimental",
+      description : "Displays geo points in clustered groups on a map. The cavaet for this panel is"+
+        " that, for better or worse, it does NOT use the terms facet and it <b>does</b> query "+
+        "sequentially. This however means that it transfers more data and is generally heavier to"+
+        " compute, while showing less actual data. If you have a time filter, it will attempt to"+
+        " show to most recent points in your search, up to your defined limit"
+    };
+
+    // Set and populate defaults
+    var _d = {
+      /** @scratch /panels/bettermap/3
+       *
+       * === Parameters
+       *
+       * field:: The field that contains the coordinates, in geojson format. GeoJSON is
+       * +[longitude,latitude]+ in an array. This is different from most implementations, which use
+       * latitude, longitude.
+       */
+      field   : null,
+      /** @scratch /panels/bettermap/5
+       * size:: The number of documents to use when drawing the map
+       */
+      size    : 1000,
+      /** @scratch /panels/bettermap/5
+       * spyable:: Should the `inspect` icon be shown?
+       */
+      spyable : true,
+      /** @scratch /panels/bettermap/5
+       * tooltip:: Which field to use for the tooltip when hovering over a marker
+       */
+      tooltip : "_id",
+      /** @scratch /panels/bettermap/5
+       *
+       * ==== Queries
+       * queries object:: This object describes the queries to use on this panel.
+       * queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
+       * queries.ids::: In +selected+ mode, which query ids are selected.
+       */
+      queries     : {
+        mode        : 'all',
+        ids         : []
+      },
+      /*
+       * locked:: whether to lock the query, preventing it from being affected by filters
+       */
+      locked: false
+    };
+
+    _.defaults($scope.panel,_d);
+
+    // inorder to use relative paths in require calls, require needs a context to run. Without
+    // setting this property the paths would be relative to the app not this context/file.
+    $scope.requireContext = localRequire;
+
+    $scope.init = function() {
+      $scope.$on('refresh',function(){
+        $scope.get_data();
+      });
+      $scope.get_data();
+    };
+
+    $scope.get_data = function(segment,query_id) {
+      $scope.require(['./leaflet/plugins'], function () {
+        $scope.panel.error =  false;
+
+        // Make sure we have everything for the request to complete
+        if(dashboard.indices.length === 0) {
+          return;
+        }
+
+        if(_.isUndefined($scope.panel.field)) {
+          $scope.panel.error = "Please select a field that contains geo point in [lon,lat] format";
+          return;
+        }
+
+        // Determine the field to sort on
+        var timeField = _.uniq(_.pluck(filterSrv.getByType('time'),'field'));
+        if(timeField.length > 1) {
+          $scope.panel.error = "Time field must be consistent amongst time filters";
+        } else if(timeField.length === 0) {
+          timeField = null;
+        } else {
+          timeField = timeField[0];
+        }
+
+        var _segment = _.isUndefined(segment) ? 0 : segment;
+
+        $scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
+        var queries = querySrv.getQueryObjs($scope.panel.queries.ids);
+
+        var boolQuery = $scope.ejs.BoolQuery();
+        _.each(queries,function(q) {
+          boolQuery = boolQuery.should(querySrv.toEjsObj(q));
+        });
+
+        var request = $scope.ejs.Request().indices(dashboard.indices[_segment])
+          .query($scope.ejs.FilteredQuery(
+            boolQuery,
+            $scope.panel.locked ? null : filterSrv.getBoolFilter(filterSrv.ids()).must($scope.ejs.ExistsFilter($scope.panel.field))
+          ))
+          .fields([$scope.panel.field,$scope.panel.tooltip])
+          .size($scope.panel.size);
+
+        if(!_.isNull(timeField)) {
+          request = request.sort(timeField,'desc');
+        }
+
+        $scope.populate_modal(request);
+
+        var results = request.doSearch();
+
+        // Populate scope when we have results
+        results.then(function(results) {
+          $scope.panelMeta.loading = false;
+
+          if(_segment === 0) {
+            $scope.hits = 0;
+            $scope.data = [];
+            query_id = $scope.query_id = new Date().getTime();
+          }
+
+          // Check for error and abort if found
+          if(!(_.isUndefined(results.error))) {
+            $scope.panel.error = $scope.parse_error(results.error);
+            return;
+          }
+
+          // Check that we're still on the same query, if not stop
+          if($scope.query_id === query_id) {
+
+            // Keep only what we need for the set
+            $scope.data = $scope.data.slice(0,$scope.panel.size).concat(_.map(results.hits.hits, function(hit) {
+              return {
+                coordinates : new L.LatLng(hit.fields[$scope.panel.field][1],hit.fields[$scope.panel.field][0]),
+                tooltip : hit.fields[$scope.panel.tooltip]
+              };
+            }));
+
+          } else {
+            return;
+          }
+
+          $scope.$emit('draw');
+
+          // Get $size results then stop querying
+          if($scope.data.length < $scope.panel.size && _segment+1 < dashboard.indices.length) {
+            $scope.get_data(_segment+1,$scope.query_id);
+          }
+
+        });
+      });
+    };
+
+    $scope.populate_modal = function(request) {
+      $scope.inspector = angular.toJson(JSON.parse(request.toString()),true);
+    };
+
+  });
+
+  module.directive('bettermap', function() {
+    return {
+      restrict: 'A',
+      link: function(scope, elem) {
+        elem.html('<center><img src="img/load_big.gif"></center>');
+
+        // Receive render events
+        scope.$on('draw',function(){
+          render_panel();
+        });
+
+        scope.$on('render', function(){
+          if(!_.isUndefined(map)) {
+            map.invalidateSize();
+            map.getPanes();
+          }
+        });
+
+        var map, layerGroup;
+
+        function render_panel() {
+          elem.css({height:scope.row.height});
+
+          scope.require(['./leaflet/plugins'], function () {
+            scope.panelMeta.loading = false;
+            L.Icon.Default.imagePath = 'app/panels/bettermap/leaflet/images';
+            if(_.isUndefined(map)) {
+              map = L.map(scope.$id, {
+                scrollWheelZoom: false,
+                center: [40, -86],
+                zoom: 10
+              });
+
+              // This could be made configurable?
+              L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg', {
+                attribution: '"Data, imagery and map information provided by MapQuest, '+
+                  'OpenStreetMap <http://www.openstreetmap.org/copyright> and contributors, ODbL',
+                maxZoom: 18,
+                minZoom: 2
+              }).addTo(map);
+              layerGroup = new L.MarkerClusterGroup({maxClusterRadius:30});
+            } else {
+              layerGroup.clearLayers();
+            }
+
+            var markerList = [];
+
+            _.each(scope.data, function(p) {
+              if(!_.isUndefined(p.tooltip) && p.tooltip !== '') {
+                markerList.push(L.marker(p.coordinates).bindLabel(_.isArray(p.tooltip) ? p.tooltip[0] : p.tooltip));
+              } else {
+                markerList.push(L.marker(p.coordinates));
+              }
+            });
+
+            layerGroup.addLayers(markerList);
+
+            layerGroup.addTo(map);
+
+            map.fitBounds(_.pluck(scope.data,'coordinates'));
+          });
+        }
+      }
+    };
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/column/editor.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/column/editor.html b/opensoc-ui/lib/public/app/panels/column/editor.html
new file mode 100755
index 0000000..06f91b3
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/column/editor.html
@@ -0,0 +1,36 @@
+<div>
+  <div class="row-fluid">
+    <h4>Add Panel to Column</h4>
+    <select class="input-medium" ng-model="new_panel.type" ng-options="f for f in _.without(config.panel_names,'column')| stringSort" ng-change="reset_panel(new_panel.type);send_render();"></select>
+    <small>Select Type</small>
+    <div ng-show="!(_.isUndefined(new_panel.type))">
+      <div column-edit panel="new_panel" config="config" row="row" dashboards="dashboards" type="new_panel.type"></div>
+      <button ng-click="add_panel(panel,new_panel); reset_panel();" class="btn btn-primary">Create Panel</button><br>
+    </div>
+  </div>
+  <div class="row-fluid">
+    <div class="span12">
+      <h4>Panels</h4>
+      <table class="table table-condensed table-striped">
+        <thead>
+          <th>Title</th>
+          <th>Type</th>
+          <th>Height</th>
+          <th>Delete</th>
+          <th>Move</th>
+          <th></th>
+          <th>Hide</th>
+        </thead>
+        <tr ng-repeat="app in panel.panels">
+          <td>{{app.title}}</td>
+          <td>{{app.type}}</td>
+          <td><input type="text" class="input-small" ng-model="app.height"></input></td>
+          <td><i ng-click="panel.panels = _.without(panel.panels,app)" class="pointer icon-remove"></i></td>
+          <td><i ng-click="_.move(panel.panels,$index,$index-1)" ng-hide="$first" class="pointer icon-arrow-up"></i></td>
+          <td><i ng-click="_.move(panel.panels,$index,$index+1)" ng-hide="$last" class="pointer icon-arrow-down"></i></td>
+          <td><input type="checkbox" ng-model="app.hide" ng-checked="app.hide"></td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/column/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/column/module.html b/opensoc-ui/lib/public/app/panels/column/module.html
new file mode 100755
index 0000000..864ec84
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/column/module.html
@@ -0,0 +1,16 @@
+<div ng-controller="column" ng-init="init();">
+  <!-- Panels -->
+  <div ng-repeat="(name, panel) in panel.panels" ng-hide="panel.height == '0px' || panel.hide" class="row-fluid panel" style="min-height:{{panel.height}}; position:relative">
+    <!-- Error Panel -->
+    <div class="row-fluid">
+      <div class="span12 alert alert-error panel-error" ng-hide="!panel.error">
+        <a class="close" ng-click="panel.error=false">&times;</a>
+        <i class="icon-exclamation-sign"></i> <strong>Oops!</strong> {{panel.error}}
+      </div>
+    </div>
+    <!-- Content Panel -->
+    <div class="row-fluid">
+      <kibana-panel type="panel.type"></kibana-panel>
+    </div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/column/module.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/column/module.js b/opensoc-ui/lib/public/app/panels/column/module.js
new file mode 100755
index 0000000..6a627ed
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/column/module.js
@@ -0,0 +1,119 @@
+/** @scratch /panels/5
+ *
+ * include::panels/column.asciidoc[]
+ */
+
+/** @scratch /panels/column/0
+ *
+ * == Column
+ * Status: *Stable*
+ *
+ * A pseudo panel that lets you add other panels to be arranged in a column with defined heights.
+ * While the column panel is stable, it does have many limitations, including the inability to drag
+ * and drop panels within its borders. It may be removed in a future release.
+ *
+ */
+define([
+  'angular',
+  'app',
+  'lodash',
+  'config'
+],
+function (angular, app, _, config) {
+  'use strict';
+
+  var module = angular.module('kibana.panels.column', []);
+
+  app.useModule(module);
+
+  module.controller('column', function($scope, $rootScope, $timeout) {
+    $scope.panelMeta = {
+      status  : "Stable",
+      description : "A pseudo panel that lets you add other panels to be arranged in a column with"+
+        "defined heights."
+    };
+
+    // Set and populate defaults
+    var _d = {
+      /** @scratch /panels/column/3
+       *
+       * === Parameters
+       *
+       * panel:: An array of panel objects
+       */
+      panels : []
+    };
+    _.defaults($scope.panel,_d);
+
+    $scope.init = function(){
+      $scope.reset_panel();
+    };
+
+    $scope.toggle_row = function(panel) {
+      panel.collapse = panel.collapse ? false : true;
+      if (!panel.collapse) {
+        $timeout(function() {
+          $scope.send_render();
+        });
+      }
+    };
+
+    $scope.send_render = function() {
+      $scope.$broadcast('render');
+    };
+
+    $scope.add_panel = function(panel,newPanel) {
+      panel.panels.push(newPanel);
+    };
+
+    $scope.reset_panel = function(type) {
+      $scope.new_panel = {
+        loading: false,
+        error: false,
+        sizeable: false,
+        draggable: false,
+        removable: false,
+        span: 10,
+        height: "150px",
+        editable: true,
+        type: type
+      };
+    };
+
+  });
+
+  module.directive('columnEdit', function($compile,$timeout) {
+    return {
+      scope : {
+        new_panel:"=panel",
+        row:"=",
+        config:"=",
+        dashboards:"=",
+        type:"=type"
+      },
+      link: function(scope, elem) {
+        scope.$on('render', function () {
+
+          // Make sure the digest has completed and populated the attributes
+          $timeout(function() {
+            // Create a reference to the new_panel as panel so that the existing
+            // editors work with our isolate scope
+            scope.panel = scope.new_panel;
+            var template = '<div ng-include src="partial(\'panelgeneral\')"></div>';
+
+            if(!(_.isUndefined(scope.type)) && scope.type !== "") {
+              template = template+'<div ng-include src="\'app/panels/'+scope.type+'/editor.html\'"></div>';
+            }
+            elem.html($compile(angular.element(template))(scope));
+          });
+        });
+      }
+    };
+  });
+
+  module.filter('withoutColumn', function() {
+    return function() {
+      return _.without(config.panel_names,'column');
+    };
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/column/panelgeneral.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/column/panelgeneral.html b/opensoc-ui/lib/public/app/panels/column/panelgeneral.html
new file mode 100755
index 0000000..b952c1e
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/column/panelgeneral.html
@@ -0,0 +1,11 @@
+  <div class="row-fluid">
+    <div class="span4">
+      <label class="small">Title</label><input type="text" class="input-medium" ng-model='panel.title'></input>
+    </div>
+    <div class="span2">
+      <label class="small">Height</label> <input type="text" class="input-mini" ng-model='panel.height'></input>
+    </div>
+    <div class="span1"> 
+      <label class="small"> Editable </label><input type="checkbox" ng-model="panel.editable" ng-checked="panel.editable">
+    </div>
+  </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/dashcontrol/editor.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/dashcontrol/editor.html b/opensoc-ui/lib/public/app/panels/dashcontrol/editor.html
new file mode 100755
index 0000000..8faf815
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/dashcontrol/editor.html
@@ -0,0 +1,44 @@
+<div>
+  <h5>Allow saving to</h5>
+  <div class="row-fluid">
+    <div class="span2">
+      <label class="small">Export</label><input type="checkbox" ng-model="panel.save.local" ng-checked="panel.save.local">
+    </div>
+    <div class="span2">
+      <label class="small">Defaults</label><input type="checkbox" ng-model="panel.save.default" ng-checked="panel.save.default">
+    </div>
+    <div class="span2">
+      <label class="small">Gist <tip>Requires your domain to be OAUTH registered with Github<tip></label><input type="checkbox" ng-model="panel.save.gist" ng-checked="panel.save.gist">
+    </div>
+    <div class="span2">
+      <label class="small">Elasticsearch</label><input type="checkbox" ng-model="panel.save.elasticsearch" ng-checked="panel.save.elasticsearch">
+    </div>
+  </div>
+  <h5>Allow loading from</h5>
+  <div class="row-fluid">
+    <div class="span2">
+      <label class="small">Local file</label><input type="checkbox" ng-model="panel.load.local" ng-checked="panel.load.local">
+    </div>
+    <div class="span2">
+      <label class="small">Gist</label><input type="checkbox" ng-model="panel.load.gist" ng-checked="panel.load.gist">
+    </div>
+    <div class="span2">
+      <label class="small">Elasticsearch</label><input type="checkbox" ng-model="panel.load.elasticsearch" ng-checked="panel.load.elasticsearch">
+    </div>
+    <div class="span3" ng-show="panel.load.elasticsearch">
+      <label class="small">ES list size</label><input class="input-mini" type="number" ng-model="panel.elasticsearch_size">
+    </div>
+  </div>
+  <h5>Sharing</h5>
+  <div class="row-fluid">
+    <div class="span2" >
+      <label class="small">Allow Sharing</label><input type="checkbox" ng-model="panel.temp" ng-checked="panel.temp">
+    </div>
+    <div class="span2" ng-show="panel.temp">
+      <label class="small">TTL</label><input type="checkbox" ng-model="panel.ttl_enable" ng-checked="panel.temp">
+    </div>
+    <div class="span5" ng-show="panel.temp && panel.ttl_enable">
+      <label class="small">TTL Duration <i class="icon-question-sign" bs-tooltip="'Elasticsearch date math, eg: 1m,1d,1w,30d'"></i></label><input class="input-small" type="text" ng-model="panel.temp_ttl">
+    </div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/dashcontrol/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/dashcontrol/module.html b/opensoc-ui/lib/public/app/panels/dashcontrol/module.html
new file mode 100755
index 0000000..4a5fa07
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/dashcontrol/module.html
@@ -0,0 +1,3 @@
+<div ng-controller='dashcontrol' ng-init="init()">
+  This panel has been removed. Please use the dashboard controls in the top right and remove this panel from your dashboard
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/dashcontrol/module.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/dashcontrol/module.js b/opensoc-ui/lib/public/app/panels/dashcontrol/module.js
new file mode 100755
index 0000000..5943ffb
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/dashcontrol/module.js
@@ -0,0 +1,198 @@
+/*
+  ## Dashcontrol
+
+  ### Parameters
+  * save
+  ** gist :: Allow saving to gist. Requires registering an oauth domain with Github
+  ** elasticsearch :: Allow saving to a special Kibana index within Elasticsearch
+  ** local :: Allow saving to local file
+  * load
+  ** gist :: Allow loading from gists
+  ** elasticsearch :: Allow searching and loading of elasticsearch saved dashboards
+  ** local :: Allow loading of dashboards from Elasticsearch
+  * hide_control :: Upon save, hide this panel
+  * elasticsearch_size :: show this many dashboards under the ES section in the load drop down
+  * temp :: Allow saving of temp dashboards
+  * ttl :: Enable setting ttl.
+  * temp_ttl :: How long should temp dashboards persist
+*/
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function(angular, app, _) {
+  'use strict';
+
+  var module = angular.module('kibana.panels.dashcontrol', []);
+  app.useModule(module);
+
+  module.controller('dashcontrol', function($scope, $http, timer, dashboard, alertSrv) {
+    $scope.panelMeta = {
+      status  : "Deprecated",
+      description : "This panel has been moved to the navigation bar. See the dashboard setting editor to configure it."
+    };
+
+    $scope.panel = $scope.panel || {};
+    // Set and populate defaults
+    var _d = {
+      save : {
+        gist: false,
+        elasticsearch: true,
+        local: true,
+        'default': true
+      },
+      load : {
+        gist: true,
+        elasticsearch: true,
+        local: true
+      },
+      hide_control: false,
+      elasticsearch_size: 20,
+      temp: true,
+      ttl_enable: true,
+      temp_ttl: '30d'
+    };
+    _.defaults($scope.panel,_d);
+
+    $scope.init = function() {
+      $scope.gist_pattern = /(^\d{5,}$)|(^[a-z0-9]{10,}$)|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/;
+      $scope.gist = {};
+      $scope.elasticsearch = {};
+    };
+
+    $scope.set_default = function() {
+      if(dashboard.set_default()) {
+        alertSrv.set('Local Default Set',dashboard.current.title+' has been set as your local default','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 local default dashboard has been cleared','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.panel.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.panel.elasticsearch_size).then(
+        function(result) {
+        if(!_.isUndefined(result.hits)) {
+          $scope.panel.error =  false;
+          $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);
+        }
+      });
+    };
+  });
+
+  module.directive('dashUpload', function(timer, dashboard, alertSrv){
+    return {
+      restrict: 'A',
+      link: function(scope) {
+        function file_selected(evt) {
+          var files = evt.target.files; // FileList object
+
+          // unused.. var output = []; // files is a FileList of File objects. List some properties.
+          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');
+        }
+      }
+    };
+  });
+
+  module.filter('gistid', function() {
+    var gist_pattern = /(\d{5,})|([a-z0-9]{10,})|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/;
+    return function(input) {
+      //return input+"boners"
+      if(!(_.isUndefined(input))) {
+        var output = input.match(gist_pattern);
+        if(!_.isNull(output) && !_.isUndefined(output)) {
+          return output[0].replace(/.*\//, '');
+        }
+      }
+    };
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/derivequeries/editor.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/derivequeries/editor.html b/opensoc-ui/lib/public/app/panels/derivequeries/editor.html
new file mode 100755
index 0000000..281c686
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/derivequeries/editor.html
@@ -0,0 +1 @@
+<div></div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/derivequeries/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/derivequeries/module.html b/opensoc-ui/lib/public/app/panels/derivequeries/module.html
new file mode 100755
index 0000000..58e96a1
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/derivequeries/module.html
@@ -0,0 +1,3 @@
+<div ng-controller='derivequeries' ng-init="init()">
+ <h4>This panel has been removed and replaced with the new topN query type. Click the colored dot associated with a query to configure the, much improved, equivilent of a derived query.</h4>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/derivequeries/module.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/derivequeries/module.js b/opensoc-ui/lib/public/app/panels/derivequeries/module.js
new file mode 100755
index 0000000..8d13af1
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/derivequeries/module.js
@@ -0,0 +1,53 @@
+/*
+  ## Derivequeries
+
+  ### Parameters
+  * label :: The label to stick over the field
+  * query :: A string to use as a filter for the terms facet
+  * field :: the field to facet on
+  * rest  :: include a filter that matches all other terms,
+  * size :: how many queries to generate
+  * fields :: a list of fields known to us
+  * query_mode :: how to create query
+
+*/
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  var module = angular.module('kibana.panels.derivequeries', []);
+  app.useModule(module);
+
+  module.controller('derivequeries', function($scope) {
+    $scope.panelMeta = {
+      status  : "Deprecated",
+      description : "This panel has been replaced with the 'topN' mode in the query pull down."
+    };
+
+    // Set and populate defaults
+    var _d = {
+      loading : false,
+      label   : "Search",
+      query   : "*",
+      ids     : [],
+      field   : '_type',
+      fields  : [],
+      spyable : true,
+      rest    : false,
+      size    : 5,
+      mode    : 'terms only',
+      exclude : [],
+      history : [],
+      remember: 10 // max: 100, angular strap can't take a variable for items param
+    };
+    _.defaults($scope.panel,_d);
+
+    $scope.init = function() {
+      $scope.editing = false;
+    };
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/fields/editor.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/fields/editor.html b/opensoc-ui/lib/public/app/panels/fields/editor.html
new file mode 100755
index 0000000..42ddee0
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/fields/editor.html
@@ -0,0 +1,10 @@
+  <div class="row-fluid">    
+    <div class="span3"><h6>Popup Position</h6> 
+      <select class="input-small" ng-model="panel.micropanel_position" ng-options="f for f in ['top','right','bottom','left']" ng-change="reload_list();"></select></span>
+    </div>
+    <div class="span3"><h6>List Arrangement</h6> 
+      <select class="input-small" ng-model="panel.arrange" ng-options="f for f in ['horizontal','vertical']"></select></span>
+    </div>
+    <div class="span3"><h6>Font Size</h6> 
+      <select class="input-small" ng-model="panel.style['font-size']" ng-options="f for f in ['6pt','7pt','8pt','9pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select></span>
+  </div>

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/fields/micropanel.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/fields/micropanel.html b/opensoc-ui/lib/public/app/panels/fields/micropanel.html
new file mode 100755
index 0000000..767c8fd
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/fields/micropanel.html
@@ -0,0 +1,25 @@
+<a class="close" ng-click="dismiss()" href="">×</a>
+<h4>
+  Micro Analysis of {{micropanel.field}} 
+  <i class="pointer icon-search" ng-click="fieldExists(micropanel.field,'must');dismiss();"></i>
+  <i class="pointer icon-ban-circle" ng-click="fieldExists(micropanel.field,'mustNot');dismiss();"></i>
+  <br><small>{{micropanel.count}} events in the table set</small>
+</h4>
+<table style="width:480px" class='table table-bordered table-striped table-condensed'>
+  <thead>
+    <th>{{micropanel.field}}</th>
+    <th>Action</th>
+    <th>In set</th>
+  </thead>
+  <tbody>
+    <tr ng-repeat='field in micropanel.values'>
+      <td>{{{true: "__blank__",false:field[0]}[field[0] == ""]}}</td>
+      <td>
+        <i class="pointer icon-search" ng-click="build_search(micropanel.field,field[0],'must');dismiss();"></i>
+        <i class="pointer icon-ban-circle" ng-click="build_search(micropanel.field,field[0],'mustNot');dismiss();"></i>
+      </td>
+      <td>{{field[1]}}</td>
+    </tr>
+  </tbody>
+</table>
+<span ng-repeat='(field,count) in micropanel.related'><a ng-click="toggle_field(field)">{{field}}</a> ({{Math.round((count / micropanel.count) * 100)}}%),</span>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/fields/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/fields/module.html b/opensoc-ui/lib/public/app/panels/fields/module.html
new file mode 100755
index 0000000..79b6f4c
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/fields/module.html
@@ -0,0 +1,3 @@
+<div ng-controller='fields' ng-init="init()">
+ <h4>The 'fields' panel is deprecated.</h4> The table panel now integrates a field selector.
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/fields/module.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/fields/module.js b/opensoc-ui/lib/public/app/panels/fields/module.js
new file mode 100755
index 0000000..a887b4f
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/fields/module.js
@@ -0,0 +1,37 @@
+/*
+  ## Fields (DEPRECATED)
+*/
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  var module = angular.module('kibana.panels.fields', []);
+  app.useModule(module);
+
+  module.controller('fields', function($scope) {
+
+    $scope.panelMeta = {
+      status  : "Deprecated",
+      description : "You should not use this table, it does not work anymore. The table panel now"+
+        "integrates a field selector. This module will soon be removed."
+    };
+
+
+    // Set and populate defaults
+    var _d = {
+      style   : {},
+      arrange : 'vertical',
+      micropanel_position : 'right',
+    };
+    _.defaults($scope.panel,_d);
+
+    $scope.init = function() {
+      // Place holder until I remove this
+    };
+
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/filtering/editor.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/filtering/editor.html b/opensoc-ui/lib/public/app/panels/filtering/editor.html
new file mode 100755
index 0000000..3100415
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/filtering/editor.html
@@ -0,0 +1,7 @@
+<div>
+  <div class="row-fluid">    
+    <div class="span12">
+      No options here
+    </div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/filtering/meta.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/filtering/meta.html b/opensoc-ui/lib/public/app/panels/filtering/meta.html
new file mode 100755
index 0000000..8af862f
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/filtering/meta.html
@@ -0,0 +1,15 @@
+<div>
+  <style>
+    .input-query-alias {
+      margin-bottom: 5px !important;
+    }
+  </style>
+  <a class="close" ng-click="render();dismiss();" href="">×</a>
+  <h6>Query Alias</h6>
+  <form>
+    <input class="input-medium input-query-alias" type="text" ng-model="queries.list[id].alias" placeholder='Alias...' />
+    <div>
+      <i ng-repeat="color in queries.colors" class="pointer" ng-class="{'icon-circle-blank':queries.list[id].color == color,'icon-circle':queries.list[id].color != color}" style="color:{{color}}" ng-click="queries.list[id].color = color;render();"> </i>
+    </div>
+  </form>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/filtering/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/filtering/module.html b/opensoc-ui/lib/public/app/panels/filtering/module.html
new file mode 100755
index 0000000..60e471d
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/filtering/module.html
@@ -0,0 +1,83 @@
+<div ng-controller='filtering' ng-init="init()">
+  <style>
+    .filtering-container {
+      margin-top: 3px;
+    }
+    .filter-panel-filter {
+      display:inline-block;
+      vertical-align: top;
+      width: 220px;
+      padding: 5px 5px 0px 5px;
+      margin: 5px 5px 5px 0px;
+      color: #fff;
+      background-color: #444;
+    }
+    .filter-panel-filter ul {
+      margin-bottom: 3px;
+    }
+    .filter-deselected {
+      opacity: 0.5;
+    }
+    .filter-action {
+      float:right;
+      margin-bottom: 0px !important;
+      margin-left: 3px;
+    }
+    .filter-mandate {
+      text-decoration: underline;
+      cursor: pointer;
+    }
+    .filter-apply {
+      float:right;
+    }
+  </style>
+
+  <div class='filtering-container'>
+    <span ng-show="dashboard.current.services.filter.ids.length == 0">
+      <h5>No filters available</h5>
+    </span>
+    <div ng-repeat="id in dashboard.current.services.filter.ids" class="small filter-panel-filter">
+      <div>
+        <strong>{{dashboard.current.services.filter.list[id].type}}</strong>
+        <span ng-show="!dashboard.current.services.filter.list[id].editing && isEditable(dashboard.current.services.filter.list[id])" class="filter-mandate" ng-click="dashboard.current.services.filter.list[id].editing = true">
+          {{dashboard.current.services.filter.list[id].mandate}}
+        </span>
+        <span ng-show="!isEditable(dashboard.current.services.filter.list[id])">
+          {{dashboard.current.services.filter.list[id].mandate}}
+        </span>
+
+        <i ng-class="getFilterClass(dashboard.current.services.filter.list[id])" class="icon-circle"></i>
+
+        <span ng-show="dashboard.current.services.filter.list[id].editing">
+          <select class="input-small" ng-model="dashboard.current.services.filter.list[id].mandate" ng-options="f for f in ['must','mustNot','either']"></select>
+        </span>
+
+        <i class="filter-action pointer icon-remove" bs-tooltip="'Remove'" ng-click="remove(id)"></i>
+        <i class="filter-action pointer" ng-class="{'icon-check': dashboard.current.services.filter.list[id].active,'icon-check-empty': !dashboard.current.services.filter.list[id].active}" bs-tooltip="'Toggle'" ng-click="toggle(id)"></i>
+        <i class="filter-action pointer icon-edit" ng-hide="dashboard.current.services.filter.list[id].editing || !isEditable(dashboard.current.services.filter.list[id])" bs-tooltip="'Edit'" ng-click="dashboard.current.services.filter.list[id].editing = true"></i>
+      </div>
+
+      <div ng-hide="dashboard.current.services.filter.list[id].editing && isEditable(dashboard.current.services.filter.list[id])">
+        <ul class="unstyled">
+          <li ng-repeat="(key,value) in dashboard.current.services.filter.list[id] track by $index" ng-show="show_key(key)">
+            <strong>{{key}}</strong> : {{value}}
+          </li>
+        </ul>
+      </div>
+      <form ng-show="dashboard.current.services.filter.list[id].editing && isEditable(dashboard.current.services.filter.list[id])">
+        <ul class="unstyled">
+          <li ng-repeat="key in _.keys(dashboard.current.services.filter.list[id])" ng-show="show_key(key)">
+            <strong>{{key}}</strong> : <input type='text' ng-model="dashboard.current.services.filter.list[id][key]">
+          </li>
+        </ul>
+        <div>
+
+          <button type="submit" ng-click="dashboard.current.services.filter.list[id].editing=undefined;refresh()" class="filter-apply btn btn-mini btn-success" bs-tooltip="'Save and refresh'">Apply</button>
+
+          <button ng-click="dashboard.current.services.filter.list[id].editing=undefined" class="filter-apply btn-mini btn" bs-tooltip="'Save without refresh'">Save</button>
+        </div>
+      </form>
+    </div>
+    <i class="pointer icon-plus-sign" ng-click="add()" bs-tooltip="'Add a query filter'" data-placement="right"></i>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/filtering/module.js
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/filtering/module.js b/opensoc-ui/lib/public/app/panels/filtering/module.js
new file mode 100755
index 0000000..fe0b532
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/filtering/module.js
@@ -0,0 +1,100 @@
+/*
+
+  ## filtering
+
+*/
+define([
+  'angular',
+  'app',
+  'lodash'
+],
+function (angular, app, _) {
+  'use strict';
+
+  var module = angular.module('kibana.panels.filtering', []);
+  app.useModule(module);
+
+  module.controller('filtering', function($scope, filterSrv, $rootScope, dashboard) {
+
+    $scope.panelMeta = {
+      status  : "Stable",
+      description : "A controllable list of all filters currently applied to the dashboard. You "+
+        "almost certainly want one of these on your dashboard somewhere."
+    };
+
+    // Set and populate defaults
+    var _d = {
+    };
+    _.defaults($scope.panel,_d);
+
+    $scope.dashboard = dashboard;
+
+    $scope.$on('filter', function() {
+      $scope.row.notice = true;
+    });
+
+    $scope.init = function() {
+      $scope.filterSrv = filterSrv;
+    };
+
+    $scope.remove = function(id) {
+      filterSrv.remove(id);
+    };
+
+    // This function should be moved to the service
+    $scope.toggle = function(id) {
+      dashboard.current.services.filter.list[id].active = !dashboard.current.services.filter.list[id].active;
+      dashboard.refresh();
+    };
+
+    $scope.add = function(query) {
+      query = query || '*';
+      filterSrv.set({
+        editing   : true,
+        type      : 'querystring',
+        query     : query,
+        mandate   : 'must'
+      },undefined,true);
+    };
+
+    $scope.refresh = function() {
+      dashboard.refresh();
+    };
+
+    $scope.render = function() {
+      $rootScope.$broadcast('render');
+    };
+
+    $scope.show_key = function(key) {
+      return !_.contains(['type','id','alias','mandate','active','editing'],key);
+    };
+
+    $scope.getFilterClass = function(filter) {
+      if(filter.active !== true) {
+        return 'muted';
+      } else {
+        switch (filter.mandate)
+        {
+        case 'must':
+          return 'text-success';
+        case 'mustNot':
+          return 'text-error';
+        case 'either':
+          return 'text-warning';
+        default:
+          return 'text-info';
+        }
+      }
+    };
+
+    $scope.isEditable = function(filter) {
+      var uneditable = ['time'];
+      if(_.contains(uneditable,filter.type)) {
+        return false;
+      } else {
+        return true;
+      }
+    };
+
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/goal/editor.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/goal/editor.html b/opensoc-ui/lib/public/app/panels/goal/editor.html
new file mode 100755
index 0000000..0e76189
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/goal/editor.html
@@ -0,0 +1,30 @@
+  <div class="editor-row">
+
+    <div class="section">
+      <h5>Parameters</h5>
+      <div class="editor-option">
+        <form style="margin-bottom: 0px">
+          <label class="small">Goal</label>
+          <input type="number" style="width:90%" ng-model="panel.query.goal" ng-change="set_refresh(true)">
+        </form>
+      </div>
+    </div>
+
+    <div class="section">
+      <h5>View Options</h5>
+      <div class="editor-option">
+        <label class="small"> Donut </label><input type="checkbox" ng-model="panel.donut" ng-checked="panel.donut">
+      </div>
+      <div class="editor-option">
+        <label class="small"> Tilt </label><input type="checkbox" ng-model="panel.tilt" ng-checked="panel.tilt">
+      </div>
+      <div class="editor-option">
+        <label class="small"> Labels </label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels">
+      </div>
+      <div class="editor-option">
+        <label class="small">Legend</label>
+        <select class="input-small" ng-model="panel.legend" ng-options="f for f in ['above','below','none']"></select></span>
+      </div>
+    </div>
+
+  </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/05e188ba/opensoc-ui/lib/public/app/panels/goal/module.html
----------------------------------------------------------------------
diff --git a/opensoc-ui/lib/public/app/panels/goal/module.html b/opensoc-ui/lib/public/app/panels/goal/module.html
new file mode 100755
index 0000000..ae4a3b8
--- /dev/null
+++ b/opensoc-ui/lib/public/app/panels/goal/module.html
@@ -0,0 +1,15 @@
+<div ng-controller='goal' ng-init="init()">
+  <style>
+    .goal-label { pointer-events: none }
+  </style>
+  <div ng-show="panel.legend == 'above'" ng-repeat="query in legend" style="float:left;padding-left: 10px;">
+    <span ng-show="panel.chart != 'none'"><i class="icon-circle" ng-style="{color:query.color}"></i></span><span class="small"> {{query.label}} ({{query.data[0][1]}}) </span></span>
+  </div>
+  <div style="clear:both"></div>
+
+  <div goal params="{{panel}}" style="position:relative"></div>
+
+  <div ng-show="panel.legend == 'below'" ng-repeat="query in legend" style="float:left;padding-left: 10px;">
+    <span ng-show="panel.chart != 'none'"><i class="icon-circle" ng-style="{color:query.color}"></i></span><span class="small"> {{query.label}} ({{query.data[0][1]}}) </span></span>
+  </div>
+</div>
\ No newline at end of file


Mime
View raw message