Load metrics via AJAX. Fixes #819

This commit is contained in:
James Brooks
2016-02-17 17:07:34 +00:00
parent c72974de27
commit 2565774fea
4 changed files with 99 additions and 71 deletions

View File

@@ -12,29 +12,11 @@
namespace CachetHQ\Cachet\Composers; namespace CachetHQ\Cachet\Composers;
use CachetHQ\Cachet\Models\Metric; use CachetHQ\Cachet\Models\Metric;
use CachetHQ\Cachet\Repositories\Metric\MetricRepository;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
class MetricsComposer class MetricsComposer
{ {
/**
* @var \CachetHQ\Cachet\Repositories\Metric\MetricRepository
*/
protected $metricRepository;
/**
* Construct a new home controller instance.
*
* @param \CachetHQ\Cachet\Repositories\Metric\MetricRepository $metricRepository
*
* @return void
*/
public function __construct(MetricRepository $metricRepository)
{
$this->metricRepository = $metricRepository;
}
/** /**
* Metrics view composer. * Metrics view composer.
* *
@@ -45,22 +27,11 @@ class MetricsComposer
public function compose(View $view) public function compose(View $view)
{ {
$metrics = null; $metrics = null;
$metricData = [];
if ($displayMetrics = Config::get('setting.display_graphs')) { if ($displayMetrics = Config::get('setting.display_graphs')) {
$metrics = Metric::where('display_chart', 1)->orderBy('id')->get(); $metrics = Metric::where('display_chart', 1)->orderBy('id')->get();
$metrics->map(function ($metric) use (&$metricData) {
$metricData[$metric->id] = [
'last_hour' => $this->metricRepository->listPointsLastHour($metric),
'today' => $this->metricRepository->listPointsToday($metric),
'week' => $this->metricRepository->listPointsForWeek($metric),
'month' => $this->metricRepository->listPointsForMonth($metric),
];
});
} }
$view->withDisplayMetrics($displayMetrics) $view->withDisplayMetrics($displayMetrics)
->withMetrics($metrics) ->withMetrics($metrics);
->withMetricData($metricData);
} }
} }

View File

@@ -12,7 +12,10 @@
namespace CachetHQ\Cachet\Http\Controllers; namespace CachetHQ\Cachet\Http\Controllers;
use CachetHQ\Cachet\Dates\DateFactory; use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Http\Controllers\Api\AbstractApiController;
use CachetHQ\Cachet\Models\Incident; use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Models\Metric;
use CachetHQ\Cachet\Repositories\Metric\MetricRepository;
use Exception; use Exception;
use GrahamCampbell\Binput\Facades\Binput; use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
@@ -21,8 +24,25 @@ use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\View;
use Jenssegers\Date\Date; use Jenssegers\Date\Date;
class StatusPageController extends Controller class StatusPageController extends AbstractApiController
{ {
/**
* @var \CachetHQ\Cachet\Repositories\Metric\MetricRepository
*/
protected $metricRepository;
/**
* Construct a new status page controller instance.
*
* @param \CachetHQ\Cachet\Repositories\Metric\MetricRepository $metricRepository
*
* @return void
*/
public function __construct(MetricRepository $metricRepository)
{
$this->metricRepository = $metricRepository;
}
/** /**
* Displays the status page. * Displays the status page.
* *
@@ -100,4 +120,37 @@ class StatusPageController extends Controller
return View::make('incident') return View::make('incident')
->withIncident($incident); ->withIncident($incident);
} }
/**
* Returns metrics in a readily formatted way.
*
* @param \CachetHQ\Cachet\Models\Metric $metric
*
* @return \Illuminate\Http\JsonResponse
*/
public function getMetrics(Metric $metric)
{
$metricData = [];
$type = Binput::get('filter', 'last_hour');
switch ($type) {
case 'last_hour':
$metricData = $this->metricRepository->listPointsLastHour($metric);
break;
case 'today':
$metricData = $this->metricRepository->listPointsToday($metric);
break;
case 'week':
$metricData = $this->metricRepository->listPointsForWeek($metric);
break;
case 'month':
$metricData = $this->metricRepository->listPointsForMonth($metric);
break;
}
return $this->item([
'metric' => $metric->toArray(),
'items' => $metricData,
]);
}
} }

View File

@@ -39,6 +39,11 @@ class StatusPageRoutes
'as' => 'incident', 'as' => 'incident',
'uses' => 'StatusPageController@showIncident', 'uses' => 'StatusPageController@showIncident',
]); ]);
$router->get('metrics/{metric}', [
'as' => 'metrics',
'uses' => 'StatusPageController@getMetrics',
]);
}); });
} }
} }

View File

@@ -33,73 +33,72 @@
</li> </li>
@endforeach @endforeach
</ul> </ul>
<script type="text/json" id="metricData">
{!! json_encode($metric_data) !!}
</script>
<script> <script>
(function () { (function () {
Chart.defaults.global.pointHitDetectionRadius = 1; Chart.defaults.global.pointHitDetectionRadius = 1;
Chart.defaults.global.scaleBeginAtZero = true; Chart.defaults.global.scaleBeginAtZero = true;
var charts = JSON.parse(document.getElementById('metricData').text); var charts = {},
defaultData = {
var defaultData = { showTooltips: false,
showTooltips: false, labels: [],
labels: [], datasets: [{
datasets: [{ fillColor: "{{ $theme_metrics }}",
// fillColor: "rgba(220,220,220,0.1)", pointColor: "{{ color_darken($theme_metrics, -0.1) }}",
fillColor: "{{$theme_metrics}}", pointStrokeColor: "{{ color_darken($theme_metrics, -0.1) }}",
// strokeColor: "{{ $theme_metrics }}", pointHighlightFill: "{{ color_darken($theme_metrics, -0.2) }}",
pointColor: "{{ color_darken($theme_metrics, -0.1) }}", pointHighlightStroke: "{{ color_darken($theme_metrics, -0.2) }}",
pointStrokeColor: "{{ color_darken($theme_metrics, -0.1) }}", data: []
pointHighlightFill: "{{ color_darken($theme_metrics, -0.2) }}", }],
pointHighlightStroke: "{{ color_darken($theme_metrics, -0.2) }}", };
data: []
}],
};
$('a[data-filter-type]').on('click', function(e) { $('a[data-filter-type]').on('click', function(e) {
e.preventDefault(); e.preventDefault();
var $this = $(this); var $this = $(this), $li, $canvas;
// Change the selected view. $li = $this.parents('li');
var $li = $this.parents('li')
$li.find('a[data-toggle=dropdown] span.filter').text($this.text()); $li.find('a[data-toggle=dropdown] span.filter').text($this.text());
$canvas = $li.find('canvas');
var $canvas = $li.find('canvas');
$canvas.data('metric-group', $this.data('filter-type')); $canvas.data('metric-group', $this.data('filter-type'));
drawChart($canvas); drawChart($canvas);
}); });
$('canvas[data-metric-id]').each(function() { $('canvas[data-metric-id]').each(function() {
var $this = $(this); drawChart($(this));
drawChart($this);
}); });
function drawChart($el) { function drawChart($el) {
var chartConfig = defaultData;
var metricId = $el.data('metric-id'); var metricId = $el.data('metric-id');
var metricGroup = $el.data('metric-group'); var metricGroup = $el.data('metric-group');
charts[metricId].context = document.getElementById("metric-"+metricId).getContext("2d"); if (typeof charts[metricId] === 'undefined') {
charts[metricId] = {
if (typeof charts[metricId].chart !== 'undefined') { context: document.getElementById("metric-"+metricId).getContext("2d"),
charts[metricId].chart.destroy(); chart: null,
};
} }
var chartConfig = defaultData; var chart = charts[metricId];
var charter = charts[metricId][metricGroup];
chartConfig.labels = _.keys(charter); $.getJSON('/metrics/'+metricId, { filter: metricGroup }).done(function (result) {
chartConfig.datasets[0].data = _.values(charter); var data = result.data.items;
chartConfig.labels = _.keys(data);
chartConfig.datasets[0].data = _.values(data);
charts[metricId].chart = new Chart(charts[metricId].context).Line(chartConfig, { if (chart.chart !== null) {
tooltipTemplate: $el.data('metric-name') + ": <{{ '%' }}= value %> " + $el.data('metric-suffix'), chart.chart.destroy();
scaleShowVerticalLines: true, }
scaleShowLabels: false,
responsive: true, chart.chart = new Chart(chart.context).Line(chartConfig, {
maintainAspectRatio: false tooltipTemplate: $el.data('metric-name') + ": <{{ '%' }}= value %> " + $el.data('metric-suffix'),
scaleShowVerticalLines: true,
scaleShowLabels: false,
responsive: true,
maintainAspectRatio: false
});
}); });
} }
}()); }());