Merge pull request #312 from rashidkpc/master

Switch styles to LESS build, add inspector.html, update flot
This commit is contained in:
Rashid Khan 2013-07-31 11:25:55 -07:00
commit d84adddab7
17 changed files with 985 additions and 12479 deletions

View File

@ -46,14 +46,28 @@ module.exports = function (grunt) {
moment: false moment: false
} }
} }
},
less: {
production: {
options: {
paths: ["vendor/bootstrap/less"],
yuicompress:true
},
files: {
"common/css/bootstrap.dark.min.css": "vendor/bootstrap/less/bootstrap.dark.less",
"common/css/bootstrap.light.min.css": "vendor/bootstrap/less/bootstrap.light.less"
}
}
} }
}); });
// load plugins // load plugins
grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('assemble-less');
// Default task. // Default task.
grunt.registerTask('default', ['jshint']); grunt.registerTask('default', ['jshint','less']);
}; };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -132,10 +132,20 @@
max-width: 500px; max-width: 500px;
} }
.modal {
width: 770px;
margin-left: -385px;
top: 10px !important;
}
.tiny { .tiny {
font-size: 50%; font-size: 50%;
} }
.smaller {
font-size: 70%;
}
.small { .small {
font-size: 85%; font-size: 85%;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* Flot plugin for rendering pie charts. /* Flot plugin for rendering pie charts.
Copyright (c) 2007-2012 IOLA and Ole Laursen. Copyright (c) 2007-2013 IOLA and Ole Laursen.
Licensed under the MIT license. Licensed under the MIT license.
The plugin assumes that each series has a single data value, and that each The plugin assumes that each series has a single data value, and that each
@ -57,22 +57,22 @@ More detail and specific examples can be found in the included HTML file.
(function($) { (function($) {
// Maximum redraw attempts when fitting labels within the plot
var REDRAW_ATTEMPTS = 10;
// Factor by which to shrink the pie when fitting labels within the plot
var REDRAW_SHRINK = 0.95;
function init(plot) { function init(plot) {
var canvas = null, var canvas = null,
canvasWidth = 0,
canvasHeight = 0,
target = null, target = null,
maxRadius = null, maxRadius = null,
centerLeft = null, centerLeft = null,
centerTop = null, centerTop = null,
total = 0,
redraw = true,
redrawAttempts = 10,
shrink = 0.95,
legendWidth = 0,
processed = false, processed = false,
raw = false,
ctx = null; ctx = null;
// interactive variables // interactive variables
@ -81,16 +81,9 @@ More detail and specific examples can be found in the included HTML file.
// add hook to determine if pie plugin in enabled, and then perform necessary operations // add hook to determine if pie plugin in enabled, and then perform necessary operations
plot.hooks.processOptions.push(checkPieEnabled); plot.hooks.processOptions.push(function(plot, options) {
plot.hooks.bindEvents.push(bindEvents);
// check to see if the pie plugin is enabled
function checkPieEnabled(plot, options) {
if (options.series.pie.show) { if (options.series.pie.show) {
//disable grid
options.grid.show = false; options.grid.show = false;
// set labels.show // set labels.show
@ -120,21 +113,10 @@ More detail and specific examples can be found in the included HTML file.
} else if (options.series.pie.tilt < 0) { } else if (options.series.pie.tilt < 0) {
options.series.pie.tilt = 0; options.series.pie.tilt = 0;
} }
// add processData hook to do transformations on the data
plot.hooks.processDatapoints.push(processDatapoints);
plot.hooks.drawOverlay.push(drawOverlay);
// draw hook
plot.hooks.draw.push(draw);
} }
} });
// bind hoverable events plot.hooks.bindEvents.push(function(plot, eventHolder) {
function bindEvents(plot, eventHolder) {
var options = plot.getOptions(); var options = plot.getOptions();
if (options.series.pie.show) { if (options.series.pie.show) {
if (options.grid.hoverable) { if (options.grid.hoverable) {
@ -144,47 +126,30 @@ More detail and specific examples can be found in the included HTML file.
eventHolder.unbind("click").click(onClick); eventHolder.unbind("click").click(onClick);
} }
} }
} });
// debugging function that prints out an object plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) {
var options = plot.getOptions();
function alertObject(obj) { if (options.series.pie.show) {
processDatapoints(plot, series, data, datapoints);
var msg = "";
function traverse(obj, depth) {
if (!depth) {
depth = 0;
}
for (var i = 0; i < obj.length; ++i) {
for (var j = 0; j < depth; j++) {
msg += "\t";
}
if( typeof obj[i] == "object") {
msg += "" + i + ":\n";
traverse(obj[i], depth + 1);
} else {
msg += "" + i + ": " + obj[i] + "\n";
}
}
} }
});
traverse(obj); plot.hooks.drawOverlay.push(function(plot, octx) {
alert(msg); var options = plot.getOptions();
} if (options.series.pie.show) {
drawOverlay(plot, octx);
function calcTotal(data) {
for (var i = 0; i < data.length; ++i) {
var item = parseFloat(data[i].data[0][1]);
if (item) {
total += item;
}
} }
} });
function processDatapoints(plot, series, data, datapoints) { plot.hooks.draw.push(function(plot, newCtx) {
var options = plot.getOptions();
if (options.series.pie.show) {
draw(plot, newCtx);
}
});
function processDatapoints(plot, series, datapoints) {
if (!processed) { if (!processed) {
processed = true; processed = true;
canvas = plot.getCanvas(); canvas = plot.getCanvas();
@ -194,9 +159,127 @@ More detail and specific examples can be found in the included HTML file.
} }
} }
function setupPie() { function combine(data) {
legendWidth = target.children().filter(".legend").children().width() || 0; var total = 0,
combined = 0,
numCombined = 0,
color = options.series.pie.combine.color,
newdata = [];
// Fix up the raw data from Flot, ensuring the data is numeric
for (var i = 0; i < data.length; ++i) {
var value = data[i].data;
// If the data is an array, we'll assume that it's a standard
// Flot x-y pair, and are concerned only with the second value.
// Note how we use the original array, rather than creating a
// new one; this is more efficient and preserves any extra data
// that the user may have stored in higher indexes.
if ($.isArray(value) && value.length == 1) {
value = value[0];
}
if ($.isArray(value)) {
// Equivalent to $.isNumeric() but compatible with jQuery < 1.7
if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) {
value[1] = +value[1];
} else {
value[1] = 0;
}
} else if (!isNaN(parseFloat(value)) && isFinite(value)) {
value = [1, +value];
} else {
value = [1, 0];
}
data[i].data = [value];
}
// Sum up all the slices, so we can calculate percentages for each
for (var i = 0; i < data.length; ++i) {
total += data[i].data[0][1];
}
// Count the number of slices with percentages below the combine
// threshold; if it turns out to be just one, we won't combine.
for (var i = 0; i < data.length; ++i) {
var value = data[i].data[0][1];
if (value / total <= options.series.pie.combine.threshold) {
combined += value;
numCombined++;
if (!color) {
color = data[i].color;
}
}
}
for (var i = 0; i < data.length; ++i) {
var value = data[i].data[0][1];
if (numCombined < 2 || value / total > options.series.pie.combine.threshold) {
newdata.push({
data: [[1, value]],
color: data[i].color,
label: data[i].label,
angle: value * Math.PI * 2 / total,
percent: value / (total / 100)
});
}
}
if (numCombined > 1) {
newdata.push({
data: [[1, combined]],
color: color,
label: options.series.pie.combine.label,
angle: combined * Math.PI * 2 / total,
percent: combined / (total / 100)
});
}
return newdata;
}
function draw(plot, newCtx) {
if (!target) {
return; // if no series were passed
}
var canvasWidth = plot.getPlaceholder().width(),
canvasHeight = plot.getPlaceholder().height(),
legendWidth = target.children().filter(".legend").children().width() || 0;
ctx = newCtx;
// WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE!
// When combining smaller slices into an 'other' slice, we need to
// add a new series. Since Flot gives plugins no way to modify the
// list of series, the pie plugin uses a hack where the first call
// to processDatapoints results in a call to setData with the new
// list of series, then subsequent processDatapoints do nothing.
// The plugin-global 'processed' flag is used to control this hack;
// it starts out false, and is set to true after the first call to
// processDatapoints.
// Unfortunately this turns future setData calls into no-ops; they
// call processDatapoints, the flag is true, and nothing happens.
// To fix this we'll set the flag back to false here in draw, when
// all series have been processed, so the next sequence of calls to
// processDatapoints once again starts out with a slice-combine.
// This is really a hack; in 0.9 we need to give plugins a proper
// way to modify series before any processing begins.
processed = false;
// calculate maximum radius and center point // calculate maximum radius and center point
@ -219,111 +302,29 @@ More detail and specific examples can be found in the included HTML file.
} else if (centerLeft > canvasWidth - maxRadius) { } else if (centerLeft > canvasWidth - maxRadius) {
centerLeft = canvasWidth - maxRadius; centerLeft = canvasWidth - maxRadius;
} }
}
function fixData(data) { var slices = plot.getData(),
for (var i = 0; i < data.length; ++i) { attempts = 0;
if (typeof(data[i].data) == "number") {
data[i].data = [[1, data[i].data]];
} else if (typeof(data[i].data) == "undefined" || typeof(data[i].data[0]) == "undefined") {
if (typeof(data[i].data) != "undefined" && typeof(data[i].data.label) != "undefined") {
data[i].label = data[i].data.label; // fix weirdness coming from flot
}
data[i].data = [[1, 0]];
}
}
return data;
}
function combine(data) { // Keep shrinking the pie's radius until drawPie returns true,
// indicating that all the labels fit, or we try too many times.
data = fixData(data); do {
calcTotal(data);
var combined = 0;
var numCombined = 0;
var color = options.series.pie.combine.color;
var newdata = [];
for (var i = 0; i < data.length; ++i) {
// make sure its a number
data[i].data[0][1] = parseFloat(data[i].data[0][1]);
if (!data[i].data[0][1]) {
data[i].data[0][1] = 0;
}
if (data[i].data[0][1] / total <= options.series.pie.combine.threshold) {
combined += data[i].data[0][1];
numCombined++;
if (!color) {
color = data[i].color;
}
} else {
newdata.push({
data: [[1, data[i].data[0][1]]],
color: data[i].color,
label: data[i].label,
angle: data[i].data[0][1] * Math.PI * 2 / total,
percent: data[i].data[0][1] / (total / 100)
});
}
}
if (numCombined > 0) {
newdata.push({
data: [[1, combined]],
color: color,
label: options.series.pie.combine.label,
angle: combined * Math.PI * 2 / total,
percent: combined / (total / 100)
});
}
return newdata;
}
function draw(plot, newCtx) {
if (!target) {
return; // if no series were passed
}
canvasWidth = plot.getPlaceholder().width();
canvasHeight = plot.getPlaceholder().height();
ctx = newCtx;
setupPie();
var slices = plot.getData();
var attempts = 0;
while (redraw && attempts<redrawAttempts) {
redraw = false;
if (attempts > 0) { if (attempts > 0) {
maxRadius *= shrink; maxRadius *= REDRAW_SHRINK;
} }
attempts += 1; attempts += 1;
clear(); clear();
if (options.series.pie.tilt <= 0.8) { if (options.series.pie.tilt <= 0.8) {
drawShadow(); drawShadow();
} }
drawPie(); } while (!drawPie() && attempts < REDRAW_ATTEMPTS)
}
if (attempts >= redrawAttempts) { if (attempts >= REDRAW_ATTEMPTS) {
clear(); clear();
target.prepend("<div class='error'>Could not draw pie with labels contained inside canvas</div>"); target.prepend("<div class='error'>Could not draw pie with labels contained inside canvas</div>");
} }
// Reset the redraw flag on success, so the loop above can run
// again in the event of a resize or other update.
// TODO: We should remove this redraw system entirely!
redraw = true;
if (plot.setSeries && plot.insertLegend) { if (plot.setSeries && plot.insertLegend) {
plot.setSeries(slices); plot.setSeries(slices);
plot.insertLegend(); plot.insertLegend();
@ -408,14 +409,13 @@ More detail and specific examples can be found in the included HTML file.
drawDonutHole(ctx); drawDonutHole(ctx);
// draw labels ctx.restore();
// Draw the labels, returning true if they fit within the plot
if (options.series.pie.label.show) { if (options.series.pie.label.show) {
drawLabels(); return drawLabels();
} } else return true;
// restore to original state
ctx.restore();
function drawSlice(angle, color, fill) { function drawSlice(angle, color, fill) {
@ -456,14 +456,19 @@ More detail and specific examples can be found in the included HTML file.
for (var i = 0; i < slices.length; ++i) { for (var i = 0; i < slices.length; ++i) {
if (slices[i].percent >= options.series.pie.label.threshold * 100) { if (slices[i].percent >= options.series.pie.label.threshold * 100) {
drawLabel(slices[i], currentAngle, i); if (!drawLabel(slices[i], currentAngle, i)) {
return false;
}
} }
currentAngle += slices[i].angle; currentAngle += slices[i].angle;
} }
return true;
function drawLabel(slice, startAngle, index) { function drawLabel(slice, startAngle, index) {
if (slice.data[0][1] == 0) { if (slice.data[0][1] == 0) {
return; return true;
} }
// format label text // format label text
@ -497,7 +502,7 @@ More detail and specific examples can be found in the included HTML file.
// check to make sure that the label is not outside the canvas // check to make sure that the label is not outside the canvas
if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) { if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) {
redraw = true; return false;
} }
if (options.series.pie.label.background.opacity != 0) { if (options.series.pie.label.background.opacity != 0) {
@ -515,6 +520,8 @@ More detail and specific examples can be found in the included HTML file.
.css("opacity", options.series.pie.label.background.opacity) .css("opacity", options.series.pie.label.background.opacity)
.insertBefore(label); .insertBefore(label);
} }
return true;
} // end individual label function } // end individual label function
} // end drawLabels function } // end drawLabels function
} // end drawPie function } // end drawPie function

View File

@ -6,10 +6,10 @@ Licensed under the MIT license.
The plugin supports these options: The plugin supports these options:
selection: { selection: {
mode: null or "x" or "y" or "xy", mode: null or "x" or "y" or "xy",
color: color, color: color,
shape: "round" or "miter" or "bevel", shape: "round" or "miter" or "bevel",
minSize: number of pixels minSize: number of pixels
} }
Selection support is enabled by setting the mode to one of "x", "y" or "xy". Selection support is enabled by setting the mode to one of "x", "y" or "xy".
@ -33,11 +33,11 @@ When selection support is enabled, a "plotselected" event will be emitted on
the DOM element you passed into the plot function. The event handler gets a the DOM element you passed into the plot function. The event handler gets a
parameter with the ranges selected on the axes, like this: parameter with the ranges selected on the axes, like this:
placeholder.bind( "plotselected", function( event, ranges ) { placeholder.bind( "plotselected", function( event, ranges ) {
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to) alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
// similar for yaxis - with multiple axes, the extra ones are in // similar for yaxis - with multiple axes, the extra ones are in
// x2axis, x3axis, ... // x2axis, x3axis, ...
}); });
The "plotselected" event is only fired when the user has finished making the The "plotselected" event is only fired when the user has finished making the
selection. A "plotselecting" event is fired during the process with the same selection. A "plotselecting" event is fired during the process with the same
@ -58,7 +58,7 @@ The plugin allso adds the following methods to the plot object:
an yaxis range and both xaxis and yaxis if the selection mode is "xy", like an yaxis range and both xaxis and yaxis if the selection mode is "xy", like
this: this:
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } }); setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
setSelection will trigger the "plotselected" event when called. If you don't setSelection will trigger the "plotselected" event when called. If you don't
want that to happen, e.g. if you're inside a "plotselected" handler, pass want that to happen, e.g. if you're inside a "plotselected" handler, pass

View File

@ -1,6 +1,6 @@
/* Flot plugin for stacking data sets rather than overlyaing them. /* Flot plugin for stacking data sets rather than overlyaing them.
Copyright (c) 2007-2012 IOLA and Ole Laursen. Copyright (c) 2007-2013 IOLA and Ole Laursen.
Licensed under the MIT license. Licensed under the MIT license.
The plugin assumes the data is sorted on x (or y if stacking horizontally). The plugin assumes the data is sorted on x (or y if stacking horizontally).
@ -15,7 +15,7 @@ key (which can be any number or string or just "true"). To specify the default
stack, you can set the stack option like this: stack, you can set the stack option like this:
series: { series: {
stack: null or true or key (number/string) stack: null/false, true, or a key (number/string)
} }
You can also specify it for a single series, like this: You can also specify it for a single series, like this:
@ -55,7 +55,7 @@ charts or filled areas).
} }
function stackData(plot, s, datapoints) { function stackData(plot, s, datapoints) {
if (s.stack == null) if (s.stack == null || s.stack === false)
return; return;
var other = findMatchingSeries(s, plot.getData()); var other = findMatchingSeries(s, plot.getData());
@ -186,130 +186,3 @@ charts or filled areas).
version: '1.2' version: '1.2'
}); });
})(jQuery); })(jQuery);
(function ($) {
var options = {
series: {
stackpercent: null
} // or number/string
};
function init(plot) {
// will be built up dynamically as a hash from x-value, or y-value if horizontal
var stackBases = {};
var processed = false;
var stackSums = {};
//set percentage for stacked chart
function processRawData(plot, series, data, datapoints) {
if (!processed) {
processed = true;
stackSums = getStackSums(plot.getData());
}
if (series.stackpercent == true) {
var num = data.length;
series.percents = [];
var key_idx = 0;
var value_idx = 1;
if (series.bars && series.bars.horizontal && series.bars.horizontal === true) {
key_idx = 1;
value_idx = 0;
}
for (var j = 0; j < num; j++) {
var sum = stackSums[data[j][key_idx] + ""];
if (sum > 0) {
series.percents.push(data[j][value_idx] * 100 / sum);
} else {
series.percents.push(0);
}
}
}
}
//calculate summary
function getStackSums(_data) {
var data_len = _data.length;
var sums = {};
if (data_len > 0) {
//caculate summary
for (var i = 0; i < data_len; i++) {
if (_data[i].stackpercent) {
var key_idx = 0;
var value_idx = 1;
if (_data[i].bars && _data[i].bars.horizontal && _data[i].bars.horizontal === true) {
key_idx = 1;
value_idx = 0;
}
var num = _data[i].data.length;
for (var j = 0; j < num; j++) {
var value = 0;
if (_data[i].data[j][1] != null) {
value = _data[i].data[j][value_idx];
}
if (sums[_data[i].data[j][key_idx] + ""]) {
sums[_data[i].data[j][key_idx] + ""] += value;
} else {
sums[_data[i].data[j][key_idx] + ""] = value;
}
}
}
}
}
return sums;
}
function stackData(plot, s, datapoints) {
if (!s.stackpercent) return;
if (!processed) {
stackSums = getStackSums(plot.getData());
}
var newPoints = [];
var key_idx = 0;
var value_idx = 1;
if (s.bars && s.bars.horizontal && s.bars.horizontal === true) {
key_idx = 1;
value_idx = 0;
}
for (var i = 0; i < datapoints.points.length; i += 3) {
// note that the values need to be turned into absolute y-values.
// in other words, if you were to stack (x, y1), (x, y2), and (x, y3),
// (each from different series, which is where stackBases comes in),
// you'd want the new points to be (x, y1, 0), (x, y1+y2, y1), (x, y1+y2+y3, y1+y2)
// generally, (x, thisValue + (base up to this point), + (base up to this point))
if (!stackBases[datapoints.points[i + key_idx]]) {
stackBases[datapoints.points[i + key_idx]] = 0;
}
newPoints[i + key_idx] = datapoints.points[i + key_idx];
newPoints[i + value_idx] = datapoints.points[i + value_idx] + stackBases[datapoints.points[i + key_idx]];
newPoints[i + 2] = stackBases[datapoints.points[i + key_idx]];
stackBases[datapoints.points[i + key_idx]] += datapoints.points[i + value_idx];
// change points to percentage values
// you may need to set yaxis:{ max = 100 }
if ( stackSums[newPoints[i+key_idx]+""] > 0 ){
newPoints[i + value_idx] = newPoints[i + value_idx] * 100 / stackSums[newPoints[i + key_idx] + ""];
newPoints[i + 2] = newPoints[i + 2] * 100 / stackSums[newPoints[i + key_idx] + ""];
} else {
newPoints[i + value_idx] = 0;
newPoints[i + 2] = 0;
}
}
datapoints.points = newPoints;
}
plot.hooks.processRawData.push(processRawData);
plot.hooks.processDatapoints.push(stackData);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'stackpercent',
version: '0.1'
});
})(jQuery);

View File

@ -1,6 +1,6 @@
/* Pretty handling of time axes. /* Pretty handling of time axes.
Copyright (c) 2007-2012 IOLA and Ole Laursen. Copyright (c) 2007-2013 IOLA and Ole Laursen.
Licensed under the MIT license. Licensed under the MIT license.
Set axis.mode to "time" to enable. See the section "Time series data" in Set axis.mode to "time" to enable. See the section "Time series data" in
@ -10,7 +10,14 @@ API.txt for details.
(function($) { (function($) {
var options = {}; var options = {
xaxis: {
timezone: null, // "browser" for local to the client or timezone for timezone-js
timeformat: null, // format string to use
twelveHourClock: false, // 12 or 24 time in time mode
monthNames: null // list of names of months
}
};
// round to nearby lower multiple of base // round to nearby lower multiple of base
@ -66,6 +73,7 @@ API.txt for details.
case 'b': c = "" + monthNames[d.getMonth()]; break; case 'b': c = "" + monthNames[d.getMonth()]; break;
case 'd': c = leftPad(d.getDate()); break; case 'd': c = leftPad(d.getDate()); break;
case 'e': c = leftPad(d.getDate(), " "); break; case 'e': c = leftPad(d.getDate(), " "); break;
case 'h': // For back-compat with 0.7; remove in 1.0
case 'H': c = leftPad(hours); break; case 'H': c = leftPad(hours); break;
case 'I': c = leftPad(hours12); break; case 'I': c = leftPad(hours12); break;
case 'l': c = leftPad(hours12, " "); break; case 'l': c = leftPad(hours12, " "); break;
@ -187,7 +195,7 @@ API.txt for details.
[1, "year"]]); [1, "year"]]);
function init(plot) { function init(plot) {
plot.hooks.processDatapoints.push(function (plot, series, datapoints) { plot.hooks.processOptions.push(function (plot, options) {
$.each(plot.getAxes(), function(axisName, axis) { $.each(plot.getAxes(), function(axisName, axis) {
var opts = axis.options; var opts = axis.options;
@ -287,17 +295,23 @@ API.txt for details.
if (step >= timeUnitSize.minute) { if (step >= timeUnitSize.minute) {
d.setSeconds(0); d.setSeconds(0);
} else if (step >= timeUnitSize.hour) { }
if (step >= timeUnitSize.hour) {
d.setMinutes(0); d.setMinutes(0);
} else if (step >= timeUnitSize.day) { }
if (step >= timeUnitSize.day) {
d.setHours(0); d.setHours(0);
} else if (step >= timeUnitSize.day * 4) { }
if (step >= timeUnitSize.day * 4) {
d.setDate(1); d.setDate(1);
} else if (step >= timeUnitSize.month * 2) { }
if (step >= timeUnitSize.month * 2) {
d.setMonth(floorInBase(d.getMonth(), 3)); d.setMonth(floorInBase(d.getMonth(), 3));
} else if (step >= timeUnitSize.quarter * 2) { }
if (step >= timeUnitSize.quarter * 2) {
d.setMonth(floorInBase(d.getMonth(), 6)); d.setMonth(floorInBase(d.getMonth(), 6));
} else if (step >= timeUnitSize.year) { }
if (step >= timeUnitSize.year) {
d.setMonth(0); d.setMonth(0);
} }

View File

@ -16,7 +16,6 @@
<link rel="stylesheet" href="common/css/animate.min.css"> <link rel="stylesheet" href="common/css/animate.min.css">
<link rel="stylesheet" href="common/css/bootstrap-responsive.min.css"> <link rel="stylesheet" href="common/css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="common/css/font-awesome.min.css"> <link rel="stylesheet" href="common/css/font-awesome.min.css">
<link rel="stylesheet" href="common/css/main.css">
<link rel="stylesheet" href="common/css/timepicker.css"> <link rel="stylesheet" href="common/css/timepicker.css">
<!-- project dependency libs --> <!-- project dependency libs -->
@ -26,13 +25,15 @@
<script src="config.js"></script> <script src="config.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
<style>
</style>
</head> </head>
<body ng-controller="DashCtrl" ng-cloak> <body ng-controller="DashCtrl" ng-cloak>
<div ng-repeat='alert in global_alert' class="alert alert-{{alert.severity}} span12" style="position: fixed;top:2px;opacity:0.9;z-index:8000"> <div ng-repeat='alert in global_alert' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last">
<button type="button" class="close" ng-click="clear_alert(alert)">&times;</button> <button type="button" class="close" ng-click="clear_alert(alert)" style="padding-right:50px">&times;</button>
<strong>{{alert.title}}</strong> <span ng-bind-html-unsafe='alert.text'></span> <div class='pull-right small'> {{$index + 1}} alert(s) </div> <strong>{{alert.title}}</strong> <span ng-bind-html-unsafe='alert.text'></span> <div style="padding-right:10px" class='pull-right small'> {{$index + 1}} alert(s) </div>
</div> </div>
<div class="navbar navbar-static-top"> <div class="navbar navbar-static-top">
<div class="navbar-inner"> <div class="navbar-inner">

View File

@ -7,11 +7,15 @@ angular.module('kibana.directives', [])
return { return {
restrict: 'E', restrict: 'E',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
var template = '<img src="common/img/load.gif" class="panel-loading" ng-show="panelMeta.loading == true">'+ var template = '<i class="icon-spinner small icon-spin icon-large panel-loading" '+
'ng-show="panelMeta.loading == true && !panel.title"></i>'+
' <span class="editlink panelextra pointer" style="right:15px;top:0px" ' + ' <span class="editlink panelextra pointer" style="right:15px;top:0px" ' +
'bs-modal="\'partials/paneleditor.html\'" ng-show="panel.editable != false">'+ 'bs-modal="\'partials/paneleditor.html\'" ng-show="panel.editable != false">'+
'<span class="small">{{panel.type}}</span> <i class="icon-cog pointer"></i> '+ '<span class="small">{{panel.type}}</span> <i class="icon-cog pointer"></i> '+
'</span><h4>{{panel.title}}</h4>'; '</span><h4>'+
'{{panel.title}} '+
'<i class="icon-spinner smaller icon-spin icon-large" ng-show="panelMeta.loading == true && panel.title"></i>'+
'</h4>';
elem.prepend($compile(angular.element(template))(scope)); elem.prepend($compile(angular.element(template))(scope));
} }
}; };

View File

@ -8,7 +8,8 @@
"devDependencies": { "devDependencies": {
"grunt": "~0.4.0", "grunt": "~0.4.0",
"grunt-contrib": "~0.7.0", "grunt-contrib": "~0.7.0",
"grunt-contrib-jshint": "~0.6.0" "grunt-contrib-jshint": "~0.6.0",
"assemble-less": "~0.4.8"
}, },
"license": "Apache License" "license": "Apache License"
} }

View File

@ -165,6 +165,7 @@ angular.module('kibana.histogram', [])
data = []; data = [];
if(filterSrv.idsByType('time').length > 0) { if(filterSrv.idsByType('time').length > 0) {
data = [[_range.from.getTime(), null],[_range.to.getTime(), null]]; data = [[_range.from.getTime(), null],[_range.to.getTime(), null]];
//data = [];
} }
hits = 0; hits = 0;
} else { } else {
@ -313,7 +314,7 @@ angular.module('kibana.histogram', [])
lineWidth: scope.panel.linewidth, lineWidth: scope.panel.linewidth,
steps: false steps: false
}, },
bars: { show: scope.panel.bars, fill: 1, barWidth: barwidth/1.8 }, bars: { show: scope.panel.bars, fill: 1, barWidth: barwidth/1.8, zero: false },
points: { show: scope.panel.points, fill: 1, fillColor: false, radius: 5}, points: { show: scope.panel.points, fill: 1, fillColor: false, radius: 5},
shadowSize: 1 shadowSize: 1
}, },
@ -321,22 +322,21 @@ angular.module('kibana.histogram', [])
show: scope.panel['y-axis'], show: scope.panel['y-axis'],
min: 0, min: 0,
max: scope.panel.percentage && scope.panel.stack ? 100 : null, max: scope.panel.percentage && scope.panel.stack ? 100 : null,
color: "#c8c8c8"
}, },
xaxis: { xaxis: {
timezone: scope.panel.timezone, timezone: scope.panel.timezone,
show: scope.panel['x-axis'], show: scope.panel['x-axis'],
mode: "time", mode: "time",
min: scope.range.from.getTime(),
max: scope.range.to.getTime(),
timeformat: time_format(scope.panel.interval), timeformat: time_format(scope.panel.interval),
label: "Datetime", label: "Datetime",
color: "#c8c8c8",
}, },
grid: { grid: {
backgroundColor: null, backgroundColor: null,
borderWidth: 0, borderWidth: 0,
borderColor: '#eee',
color: "#eee",
hoverable: true, hoverable: true,
color: '#c8c8c8'
} }
}; };

View File

@ -8,7 +8,7 @@
</div> </div>
<div class="span8"> <div class="span8">
<h6>Columns <small>Click to remove</small></h6> <h6>Columns <small>Click to remove</small></h6>
<span style="margin-left:3px" ng-click="toggle_field(field)" ng-repeat="field in $parent.panel.fields" class="label remove pointer">{{field}} </span> <span style="margin-left:3px" ng-click="toggle_field(field)" ng-repeat="field in $parent.panel.fields" class="label pointer remove">{{field}} </span>
</div> </div>
</div> </div>
<div class="row-fluid"> <div class="row-fluid">

View File

@ -7,7 +7,7 @@
<div> <div>
<h5>Last Elasticsearch Query</h5> <h5>Last Elasticsearch Query</h5>
<pre>curl -XGET '{{config.elasticsearch}}/{{dashboard.indices|stringify}}/_search?pretty' -d '{{inspector}}' <pre>curl -XGET '{{config.elasticsearch}}/{{dashboard.indices|stringify}}/_search?pretty' -d '{{inspector}}'
</pre>" </pre>
</div> </div>
</div> </div>

View File

@ -190,3 +190,16 @@
.faded { .faded {
opacity: 0.2; opacity: 0.2;
} }
div.flot-text {
color: @textColor !important;
}
.dashboard-notice {
z-index:8000;
margin-left:0px;
padding:3px 0px 3px 0px;
width:100%;
color: @textColor;
padding-left:20px;
}

View File

@ -32,7 +32,7 @@
// Scaffolding // Scaffolding
// ------------------------- // -------------------------
@bodyBackground: @white; @bodyBackground: #ffffff;
@textColor: @grayDark; @textColor: @grayDark;