add big loaded animation to panels that need it. Switched up color scheme, made text panel support plain text, markdown and sanitized html

This commit is contained in:
Rashid Khan 2013-03-08 10:04:38 -07:00
parent 34d0c0838f
commit e206040f94
27 changed files with 224005 additions and 264 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
common/img/load_big.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

13
common/lib/angular-sanitize.min.js vendored Normal file
View File

@ -0,0 +1,13 @@
/*
AngularJS v1.1.3
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(I,h){'use strict';function i(a){var d={},a=a.split(","),c;for(c=0;c<a.length;c++)d[a[c]]=!0;return d}function z(a,d){function c(a,b,c,f){b=h.lowercase(b);if(m[b])for(;e.last()&&n[e.last()];)g("",e.last());o[b]&&e.last()==b&&g("",b);(f=p[b]||!!f)||e.push(b);var j={};c.replace(A,function(a,b,d,c,g){j[b]=k(d||c||g||"")});d.start&&d.start(b,j,f)}function g(a,b){var c=0,g;if(b=h.lowercase(b))for(c=e.length-1;c>=0;c--)if(e[c]==b)break;if(c>=0){for(g=e.length-1;g>=c;g--)d.end&&d.end(e[g]);e.length=
c}}var b,f,e=[],j=a;for(e.last=function(){return e[e.length-1]};a;){f=!0;if(!e.last()||!q[e.last()]){if(a.indexOf("<\!--")===0)b=a.indexOf("--\>"),b>=0&&(d.comment&&d.comment(a.substring(4,b)),a=a.substring(b+3),f=!1);else if(B.test(a)){if(b=a.match(r))a=a.substring(b[0].length),b[0].replace(r,g),f=!1}else if(C.test(a)&&(b=a.match(s)))a=a.substring(b[0].length),b[0].replace(s,c),f=!1;f&&(b=a.indexOf("<"),f=b<0?a:a.substring(0,b),a=b<0?"":a.substring(b),d.chars&&d.chars(k(f)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
e.last()+"[^>]*>","i"),function(a,b){b=b.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(b));return""}),g("",e.last());if(a==j)throw"Parse Error: "+a;j=a}g()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,c=h.bind(a,a.push);return{start:function(a,b,f){a=h.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
!0&&(c("<"),c(a),h.forEach(b,function(a,b){var d=h.lowercase(b);if(G[d]==!0&&(w[d]!==!0||a.match(H)))c(" "),c(b),c('="'),c(t(a)),c('"')}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);!d&&v[a]==!0&&(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|tel:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=h.extend({},y,x),m=h.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=h.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
q=i("script,style"),v=h.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=h.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");h.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
z(a,u(d));return d.join("")});h.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,c,g){c.addClass("ng-binding").data("$binding",g.ngBindHtml);d.$watch(g.ngBindHtml,function(b){b=a(b);c.html(b||"")})}}]);h.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(c,g){if(!c)return c;var b,f=c,e=[],j=u(e),i,k,l={};if(h.isDefined(g))l.target=g;for(;b=f.match(a);)i=
b[0],b[2]==b[3]&&(i="mailto:"+i),k=b.index,j.chars(f.substr(0,k)),l.href=i,j.start("a",l),j.chars(b[0].replace(d,"")),j.end("a"),f=f.substring(k+b[0].length);j.chars(f);return e.join("")}})})(window,window.angular);

View File

@ -8,18 +8,18 @@ modules: Panel modules to load. In the future these will be inferred
from your initial dashboard, though if you share dashboards you
will probably need to list them all here
NOTE: No timezone support yet, everything is in UTC at the moment.
NOTE: No timezone support yet, everything is in UTC at the moment.
If you need to configure the default dashboard, please see dashboard.js
If you need to configure the default dashboard, please see default.json
*/
var config = new Settings(
{
elasticsearch: 'http://localhost:9200',
kibana_index: "kibana-int",
timeformat: 'mm/dd HH:MM:ss',
modules: ['histogram','map','pie','table','stringquery','sort',
'timepicker','text','fields','hits','dashcontrol',
'column'],
elasticsearch: 'http://localhost:9200',
kibana_index: "kibana-int",
timeformat: 'mm/dd HH:MM:ss',
modules: ['histogram','map','pie','table','stringquery','sort',
'timepicker','text','fields','hits','dashcontrol',
'column'],
}
);

View File

@ -9,7 +9,7 @@
<meta name="description" content="Search based application built using ElasticSearch, elastic.js, and Angular.js">
<meta name="viewport" content="width=device-width">
<title>Kibana Dashboard</title>
<title>Kibana 3</title>
<link rel="stylesheet" href="common/css/normalize.min.css">
<link rel="stylesheet" href="common/css/bootstrap.min.css">
@ -33,10 +33,10 @@
<button type="button" class="close" ng-click="clear_alert(alert)">&times;</button>
<strong>{{alert.title}}</strong> <span ng-bind-html-unsafe='alert.text'></span> <div class='pull-right small'> {{$index + 1}} alert(s) </div>
</div>
<div class="navbar navbar-fixed-top">
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<span class="brand"><small>Kibana 3 Preview</small></span>
<p class="navbar-text pull-right"><small>Kibana 3 Preview</small></p>
<span class="brand">{{dashboards.title}}</span>
<div class="brand"><i class='icon-edit pointer' ng-show='dashboards.editable' bs-modal="'partials/dasheditor.html'"></i></div>
</div>

View File

@ -11,6 +11,7 @@ var modules = [
'elasticjs.service',
'$strap.directives',
'kibana.panels',
'ngSanitize',
]
var scripts = []
@ -24,6 +25,7 @@ var labjs = $LAB
.script('common/lib/timepicker.js')
.script("common/lib/angular.min.js")
.script("common/lib/angular-strap.min.js")
.script("common/lib/angular-sanitize.min.js")
.script("common/lib/elastic.min.js")
.script("common/lib/elastic-angular-client.min.js")
.script("common/lib/dateformat.js")

View File

@ -79,6 +79,7 @@ angular.module('kibana.controllers', [])
title: "Row",
height: "150px",
collapse: false,
collapsable: true,
editable: true,
panels: [],
}

View File

@ -18,6 +18,8 @@
<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>
@ -26,6 +28,7 @@
<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>

View File

@ -1,7 +1,7 @@
<kibana-panel ng-controller="column" ng-init="init();">
<!-- Panels -->
<div ng-repeat="(name, panel) in panel.panels" ng-hide="panel.height == '0px'" class="row-fluid panel" style="min-height:{{panel.height}}; position:relative">
<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">

View File

@ -41,4 +41,11 @@
<label class="small">Shared Link TTL (examples: 1m,1d,1w,30d)</label><input class="input-small" type="text" ng-model="panel.temp_ttl">
</div>
</div>
<h5>Other Settings</h5>
<div class="row-fluid">
<div class="span3" >
<label class="small"> Remove this Dashboard Control from saved copies </label><input type="checkbox" ng-model="panel.hide_control" ng-checked="panel.hide_control">
</div>
</div>
</div>

View File

@ -32,7 +32,7 @@
<table class="table table-condensed table-striped">
<tr ng-repeat="dashboard in elasticsearch.dashboards">
<td><a ng-click="elasticsearch_delete(dashboard)"><i class="icon-remove"></i></a></td>
<td><a ng-click="dash_load(dashboard['_source']['dashboard'])">{{dashboard._id}}</a></td>
<td><a href="#/dashboard/elasticsearch/{{dashboard._id}}">{{dashboard._id}}</a></td>
<td><a><i class="icon-share" ng-click="share_link(dashboard._id,'elasticsearch',dashboard._id)" bs-modal="'panels/dashcontrol/share.html'"></i></a></td>
</tr>
</table>

View File

@ -15,6 +15,7 @@ angular.module('kibana.dashcontrol', [])
elasticsearch: true,
local: true,
},
hide_control: false,
elasticsearch_size: 20,
elasticsearch_saveto: $scope.config.kibana_index,
temp: true,
@ -118,8 +119,13 @@ angular.module('kibana.dashcontrol', [])
$scope.elasticsearch_save = function(type) {
// Clone object so we can modify it without influencing the existing obejct
var save = _.clone($scope.dashboards)
if($scope.panel.hide_control) {
$scope.panel.hide = true;
var save = _.clone($scope.dashboards)
} else {
var save = _.clone($scope.dashboards)
}
// Change title on object clone
if(type === 'dashboard')
var id = save.title = $scope.elasticsearch.title;
@ -143,6 +149,8 @@ angular.module('kibana.dashcontrol', [])
if(type === 'temp')
$scope.share_link($scope.dashboards.title,'temp',result._id)
})
$scope.panel.hide = false;
}
$scope.elasticsearch_delete = function(dashboard) {

View File

@ -1,6 +1,7 @@
<div>
<a class="close" ng-click="dismiss()" href="">×</a>
<h4>Save</h4>
<div ng-show="panel.save.default || panel.save.local">
<h5>Locally</h5>
<form>

View File

@ -134,6 +134,9 @@ angular.module('kibana.histogram', [])
restrict: 'A',
link: function(scope, elem, attrs, ctrl) {
elem.html('<center><img src="common/img/load_big.gif"></center>')
// Receive render events
scope.$on('render',function(){
render_panel();
@ -201,7 +204,8 @@ angular.module('kibana.histogram', [])
borderColor: '#eee',
color: "#eee",
hoverable: true,
}
},
colors: ['#EB6841','#00A0B0','#6A4A3C','#EDC951','#CC333F']
})
} catch(e) {
console.log(e)

View File

@ -69,6 +69,8 @@ angular.module('kibana.map', [])
restrict: 'A',
link: function(scope, elem, attrs) {
elem.html('<center><img src="common/img/load_big.gif"></center>')
// Receive render events
scope.$on('render',function(){
render_panel();

View File

@ -185,6 +185,8 @@ angular.module('kibana.pie', [])
restrict: 'A',
link: function(scope, elem, attrs) {
elem.html('<center><img src="common/img/load_big.gif"></center>')
// Receive render events
scope.$on('render',function(){
render_panel();
@ -240,7 +242,8 @@ angular.module('kibana.pie', [])
},
//grid: { hoverable: true, clickable: true },
grid: { hoverable: true, clickable: true },
legend: { show: scope.panel.legend }
legend: { show: scope.panel.legend },
colors: ['#EB6841','#00A0B0','#6A4A3C','#EDC951','#CC333F']
};
// Populate element

View File

@ -1,5 +1,16 @@
<div ng-controller="text">
<label class="small">Font Size</label> <select class="input-mini" ng-model="panel.style['font-size']" ng-options="f for f in ['6pt','7pt','8pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select>
<label class=small>Content (This area uses <a target="_blank" href="http://en.wikipedia.org/wiki/Markdown">Markdown</a>. HTML is not supported)</label>
<div class="row-fluid">
<div class="span4">
<label class="small">Mode</label> <select class="input-medium" ng-model="panel.mode" ng-options="f for f in ['html','markdown','text']"></select>
</div>
<div class="span2" ng-show="panel.mode == 'text'">
<label class="small">Font Size</label> <select class="input-mini" ng-model="panel.style['font-size']" ng-options="f for f in ['6pt','7pt','8pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select>
</div>
</div>
<label class=small>Content
<span ng-show="panel.mode == 'html'">(This area uses HTML sanitized via AngularJS's <a href='http://docs.angularjs.org/api/ngSanitize.$sanitize'>$sanitize</a> service)</span>
<span ng-show="panel.mode == 'markdown'">(This area uses <a target="_blank" href="http://en.wikipedia.org/wiki/Markdown">Markdown</a>. HTML is not supported)</span>
</label>
<textarea ng-model="panel.content" rows="6" style="width:95%"></textarea>
</div>

View File

@ -1,6 +1,10 @@
<kibana-panel ng-controller='text' ng-init="init()">
<!--<p ng-style="panel.style" ng-bind-html-unsafe="panel.content | striphtml | newlines"></p>-->
<markdown ng-show="ready">
<markdown ng-show="ready && panel.mode == 'markdown'">
{{panel.content}}
</markdown>
<p ng-show="panel.mode == 'text'" ng-style='panel.style' ng-bind-html="panel.content | striphtml | newlines">
</p>
<p ng-show="panel.mode == 'html'" ng-bind-html="panel.content">
</p>
</kibana-panel>

View File

@ -4,6 +4,7 @@ angular.module('kibana.text', [])
// Set and populate defaults
var _d = {
group : "default",
mode : "markdown",
content : "",
style: {},
}
@ -12,7 +13,7 @@ angular.module('kibana.text', [])
$scope.init = function() {
$scope.ready = false;
}
}).directive('markdown', function() {
return {
restrict: 'E',
@ -31,6 +32,9 @@ angular.module('kibana.text', [])
.replace(/</g, '&lt;');
var htmlText = converter.makeHtml(text);
element.html(htmlText);
// For whatever reason, this fixes chrome. I don't like it, I think
// it makes things slow?
scope.$apply()
});
}

View File

@ -1,5 +1,5 @@
<div class="row-fluid container" style="margin-top:50px">
<div class="row-fluid container">
<!-- Rows -->
<div ng-controller="dashcontrol" ng-init="init()"></div>
<div class="row-fluid" ng-controller="RowCtrl" ng-repeat="(row_name, row) in dashboards.rows">
@ -7,12 +7,13 @@
<div class="row-fluid row-header" style="padding:0px;margin:0px;height:0px">
<div class="span12" style="min-height:5px;vertical-align:bottom">
<i ng-show="row.editable" class="icon-edit pointer editlink" bs-modal="'partials/roweditor.html'"></i>
<span ng-click="toggle_row(row)" class="pointer"><i class="pointer" ng-class="{'icon-caret-down': !row.collapse,'icon-caret-right': row.collapse}"></i> <small>{{row.title}}</small></span>
<span ng-show="row.collapsable" ng-click="toggle_row(row)" class="pointer"><i class="pointer" ng-class="{'icon-caret-down': !row.collapse,'icon-caret-right': row.collapse}"></i> <small>{{row.title}}</small></span>
<small ng-hide="row.collapsable">{{row.title}}</small>
</div>
</div>
<div class="row-fluid" style="padding-top:10px" ng-hide="row.collapse">
<!-- Panels -->
<div ng-repeat="(name, panel) in row.panels" ng-hide="panel.span == 0" class="span{{panel.span}} panel" style="min-height:{{row.height}}; position:relative">
<div ng-repeat="(name, panel) in row.panels" ng-hide="panel.span == 0 || panel.hide" class="span{{panel.span}} panel" style="min-height:{{row.height}}; position:relative">
<!-- Error Panel -->
<div class="row-fluid">
<div class="span12 alert alert-error panel-error" ng-hide="!panel.error">

View File

@ -14,6 +14,9 @@
<div class="span1">
<label class="small"> Editable </label><input type="checkbox" ng-model="row.editable" ng-checked="row.editable" />
</div>
<div class="span1">
<label class="small"> Collapsable </label><input type="checkbox" ng-model="row.collapsable" ng-checked="row.collapsable" />
</div>
</div>
<div class="row-fluid">
<h4>New Panel</h4>
@ -36,6 +39,8 @@
<th>Span</th>
<th>Delete</th>
<th>Move</th>
<th></th>
<th>Hide</th>
</thead>
<tr ng-repeat="panel in row.panels">
<td>{{panel.title}}</td>
@ -44,6 +49,7 @@
<td><i ng-click="row.panels = _.without(row.panels,panel)" class="pointer icon-remove"></i></td>
<td><i ng-click="_.move(row.panels,$index,$index-1)" ng-hide="$first" class="pointer icon-arrow-up"></i></td>
<td><i ng-click="_.move(row.panels,$index,$index+1)" ng-hide="$last" class="pointer icon-arrow-down"></i></td>
<td><input type="checkbox" ng-model="panel.hide" ng-checked="panel.hide"></td>
</tr>
</table>
</div>

222792
scripts/indexme.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
echo "Generating bulk indexable shakespeare lines with timestamp 3 hours in the past and 10 hours into the future"
echo "Generating bulk indexable shakespeare lines with timestamp 6 hours in the past and 24ish hours into the future"
node reader.js > indexme.json
echo "Setting mapping for shakespeare index"
curl -XPUT http://localhost:9200/_template/shakespeare -d '

31
scripts/loadpi.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
echo "Generating bulk indexable shakespeare lines with timestamp 3 hours in the past and 10 hours into the future"
node reader.js > indexme.json
echo "Setting mapping for shakespeare index"
curl -XPUT http://10.1.1.18:9200/_template/shakespeare -d '
{
"template" : "shakespeare",
"mappings" : {
"_default_" : {
"properties" : {
"clientip" : { "type" : "ip" },
"speaker" : {"type": "string", "index" : "not_analyzed" },
"play_name" : {"type": "string", "index" : "not_analyzed" },
"line_id" : { "type" : "integer", "index": "not_analyzed" },
"speech_number" : { "type" : "integer", "index": "not_analyzed" },
"geo" : {
"properties": {
"state" : {"type": "string", "index" : "not_analyzed" },
"country" : {"type": "string", "index" : "not_analyzed" }
}
}
}
}
}
}
'
echo
echo "Performing bulk indexing into 10.1.1.18:9200"
curl -XPUT 10.1.1.18:9200/_bulk --data-binary @indexme.json;echo
echo
echo "If tons of JSON just scrolled above, I've probably successfully loaded over 100,000 lines of shakespeare into 10.1.1.18:9200/shakespeare"

View File

@ -21,9 +21,9 @@ fs.readFile('shakespeare.json', 'utf8', function (err,data) {
}
function print_obj(o) {
var randomnumber=Math.floor(Math.random()*57600000)
var randomnumber=Math.floor(Math.random()*137600000)
var command = {index:{_index: "shakespeare", _type: "line", _id: i}};
o['@timestamp'] = new Date((new Date()).getTime() -9000000 + randomnumber);
o['@timestamp'] = new Date((new Date()).getTime() -18000000 + randomnumber);
o.geo = {
geojson : [getRandomInRange(-90, 90, 3),getRandomInRange(-180, 180, 3)],
country : get_country()